diff options
author | Siva Chandra Reddy <sivachandra@google.com> | 2020-11-18 21:30:47 -0800 |
---|---|---|
committer | Siva Chandra Reddy <sivachandra@google.com> | 2020-12-02 11:48:49 -0800 |
commit | 19c3894f9436ef68f33f80ee1fd589166267b5a1 (patch) | |
tree | 47a95ea27e4b17d38eda57a7c75dfe777e7bcf0d /libc/test | |
parent | bc044a88ee3c16e4164740732a7adc91a29b24f5 (diff) | |
download | llvm-project-19c3894f9436ef68f33f80ee1fd589166267b5a1.tar.gz |
[libc] Fix couple of corner cases in remquo.
These two cases are fixed:
1. If numerator is not zero and denominator is infinity, then the
numerator is returned as the remainder.
2. If numerator and denominator are equal in magnitude, then quotient
with the right sign is returned.
The differet tests of remquo, remquof and remquol have been unified
into a single file to avoid duplication.
Reviewed By: lntue
Differential Revision: https://reviews.llvm.org/D92353
Diffstat (limited to 'libc/test')
-rw-r--r-- | libc/test/src/math/CMakeLists.txt | 6 | ||||
-rw-r--r-- | libc/test/src/math/RemQuoTest.h | 144 | ||||
-rw-r--r-- | libc/test/src/math/remquo_test.cpp | 80 | ||||
-rw-r--r-- | libc/test/src/math/remquof_test.cpp | 80 | ||||
-rw-r--r-- | libc/test/src/math/remquol_test.cpp | 86 |
5 files changed, 159 insertions, 237 deletions
diff --git a/libc/test/src/math/CMakeLists.txt b/libc/test/src/math/CMakeLists.txt index 2220cef00791..cdffe737d8df 100644 --- a/libc/test/src/math/CMakeLists.txt +++ b/libc/test/src/math/CMakeLists.txt @@ -686,6 +686,8 @@ add_fp_unittest( libc_math_unittests SRCS remquof_test.cpp + HDRS + RemQuoTest.h DEPENDS libc.include.math libc.src.math.remquof @@ -699,6 +701,8 @@ add_fp_unittest( libc_math_unittests SRCS remquo_test.cpp + HDRS + RemQuoTest.h DEPENDS libc.include.math libc.src.math.remquo @@ -712,6 +716,8 @@ add_fp_unittest( libc_math_unittests SRCS remquol_test.cpp + HDRS + RemQuoTest.h DEPENDS libc.include.math libc.src.math.remquol diff --git a/libc/test/src/math/RemQuoTest.h b/libc/test/src/math/RemQuoTest.h new file mode 100644 index 000000000000..29fcdb83b6a2 --- /dev/null +++ b/libc/test/src/math/RemQuoTest.h @@ -0,0 +1,144 @@ +//===-- Utility class to test different flavors of remquo -------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIBC_TEST_SRC_MATH_REMQUOTEST_H +#define LLVM_LIBC_TEST_SRC_MATH_REMQUOTEST_H + +#include "utils/FPUtil/BasicOperations.h" +#include "utils/FPUtil/FPBits.h" +#include "utils/FPUtil/TestHelpers.h" +#include "utils/MPFRWrapper/MPFRUtils.h" +#include "utils/UnitTest/Test.h" +#include <math.h> + +namespace mpfr = __llvm_libc::testing::mpfr; + +template <typename T> +class RemQuoTestTemplate : public __llvm_libc::testing::Test { + using FPBits = __llvm_libc::fputil::FPBits<T>; + using UIntType = typename FPBits::UIntType; + + const T zero = __llvm_libc::fputil::FPBits<T>::zero(); + const T negZero = __llvm_libc::fputil::FPBits<T>::negZero(); + const T inf = __llvm_libc::fputil::FPBits<T>::inf(); + const T negInf = __llvm_libc::fputil::FPBits<T>::negInf(); + const T nan = __llvm_libc::fputil::FPBits<T>::buildNaN(1); + +public: + typedef T (*RemQuoFunc)(T, T, int *); + + void testSpecialNumbers(RemQuoFunc func) { + int quotient; + T x, y; + + y = T(1.0); + x = inf; + EXPECT_NE(isnan(func(x, y, "ient)), 0); + x = negInf; + EXPECT_NE(isnan(func(x, y, "ient)), 0); + + x = T(1.0); + y = zero; + EXPECT_NE(isnan(func(x, y, "ient)), 0); + y = negZero; + EXPECT_NE(isnan(func(x, y, "ient)), 0); + + y = nan; + x = T(1.0); + EXPECT_NE(isnan(func(x, y, "ient)), 0); + + y = T(1.0); + x = nan; + EXPECT_NE(isnan(func(x, y, "ient)), 0); + + x = nan; + y = nan; + EXPECT_NE(isnan(func(x, y, "ient)), 0); + + x = zero; + y = T(1.0); + EXPECT_FP_EQ(func(x, y, "ient), zero); + + x = negZero; + y = T(1.0); + EXPECT_FP_EQ(func(x, y, "ient), negZero); + + x = T(1.125); + y = inf; + EXPECT_FP_EQ(func(x, y, "ient), x); + EXPECT_EQ(quotient, 0); + } + + void testEqualNumeratorAndDenominator(RemQuoFunc func) { + T x = T(1.125), y = T(1.125); + int q; + + // When the remainder is zero, the standard requires it to + // have the same sign as x. + + EXPECT_FP_EQ(func(x, y, &q), zero); + EXPECT_EQ(q, 1); + + EXPECT_FP_EQ(func(x, -y, &q), zero); + EXPECT_EQ(q, -1); + + EXPECT_FP_EQ(func(-x, y, &q), negZero); + EXPECT_EQ(q, -1); + + EXPECT_FP_EQ(func(-x, -y, &q), negZero); + EXPECT_EQ(q, 1); + } + + void testSubnormalRange(RemQuoFunc func) { + constexpr UIntType count = 1000001; + constexpr UIntType step = + (FPBits::maxSubnormal - FPBits::minSubnormal) / count; + for (UIntType v = FPBits::minSubnormal, w = FPBits::maxSubnormal; + v <= FPBits::maxSubnormal && w >= FPBits::minSubnormal; + v += step, w -= step) { + T x = FPBits(v), y = FPBits(w); + mpfr::BinaryOutput<T> result; + mpfr::BinaryInput<T> input{x, y}; + result.f = func(x, y, &result.i); + ASSERT_MPFR_MATCH(mpfr::Operation::RemQuo, input, result, 0.0); + } + } + + void testNormalRange(RemQuoFunc func) { + constexpr UIntType count = 1000001; + constexpr UIntType step = (FPBits::maxNormal - FPBits::minNormal) / count; + for (UIntType v = FPBits::minNormal, w = FPBits::maxNormal; + v <= FPBits::maxNormal && w >= FPBits::minNormal; + v += step, w -= step) { + T x = FPBits(v), y = FPBits(w); + mpfr::BinaryOutput<T> result; + mpfr::BinaryInput<T> input{x, y}; + result.f = func(x, y, &result.i); + + // In normal range on x86 platforms, the long double implicit 1 bit can be + // zero making the numbers NaN. Hence we test for them separately. + if (isnan(x) || isnan(y)) { + ASSERT_NE(isnan(result.f), 0); + continue; + } + + ASSERT_MPFR_MATCH(mpfr::Operation::RemQuo, input, result, 0.0); + } + } +}; + +#define LIST_REMQUO_TESTS(T, func) \ + using RemQuoTest = RemQuoTestTemplate<T>; \ + TEST_F(RemQuoTest, SpecialNumbers) { testSpecialNumbers(&func); } \ + TEST_F(RemQuoTest, EqualNumeratorAndDenominator) { \ + testEqualNumeratorAndDenominator(&func); \ + } \ + TEST_F(RemQuoTest, SubnormalRange) { testSubnormalRange(&func); } \ + TEST_F(RemQuoTest, NormalRange) { testNormalRange(&func); } + +#endif // LLVM_LIBC_TEST_SRC_MATH_REMQUOTEST_H diff --git a/libc/test/src/math/remquo_test.cpp b/libc/test/src/math/remquo_test.cpp index 197d97069001..8efec397f39d 100644 --- a/libc/test/src/math/remquo_test.cpp +++ b/libc/test/src/math/remquo_test.cpp @@ -6,82 +6,8 @@ // //===----------------------------------------------------------------------===// -#include "src/math/remquo.h" -#include "utils/FPUtil/BasicOperations.h" -#include "utils/FPUtil/FPBits.h" -#include "utils/FPUtil/TestHelpers.h" -#include "utils/MPFRWrapper/MPFRUtils.h" -#include "utils/UnitTest/Test.h" -#include <math.h> - -using FPBits = __llvm_libc::fputil::FPBits<double>; -using UIntType = FPBits::UIntType; - -namespace mpfr = __llvm_libc::testing::mpfr; - -DECLARE_SPECIAL_CONSTANTS(double) - -TEST(RemquoTest, SpecialNumbers) { - int exponent; - double x, y; - - y = 1.0; - x = inf; - EXPECT_NE(isnan(__llvm_libc::remquo(x, y, &exponent)), 0); - x = negInf; - EXPECT_NE(isnan(__llvm_libc::remquo(x, y, &exponent)), 0); - - x = 1.0; - y = zero; - EXPECT_NE(isnan(__llvm_libc::remquo(x, y, &exponent)), 0); - y = negZero; - EXPECT_NE(isnan(__llvm_libc::remquo(x, y, &exponent)), 0); +#include "RemQuoTest.h" - y = nan; - x = 1.0; - EXPECT_NE(isnan(__llvm_libc::remquo(x, y, &exponent)), 0); - - y = 1.0; - x = nan; - EXPECT_NE(isnan(__llvm_libc::remquo(x, y, &exponent)), 0); - - x = nan; - y = nan; - EXPECT_NE(isnan(__llvm_libc::remquo(x, y, &exponent)), 0); - - x = zero; - y = 1.0; - EXPECT_FP_EQ(__llvm_libc::remquo(x, y, &exponent), zero); - - x = negZero; - y = 1.0; - EXPECT_FP_EQ(__llvm_libc::remquo(x, y, &exponent), negZero); -} - -TEST(RemquoTest, SubnormalRange) { - constexpr UIntType count = 1000001; - constexpr UIntType step = - (FPBits::maxSubnormal - FPBits::minSubnormal) / count; - for (UIntType v = FPBits::minSubnormal, w = FPBits::maxSubnormal; - v <= FPBits::maxSubnormal && w >= FPBits::minSubnormal; - v += step, w -= step) { - double x = FPBits(v), y = FPBits(w); - mpfr::BinaryOutput<double> result; - mpfr::BinaryInput<double> input{x, y}; - result.f = __llvm_libc::remquo(x, y, &result.i); - ASSERT_MPFR_MATCH(mpfr::Operation::RemQuo, input, result, 0.0); - } -} +#include "src/math/remquo.h" -TEST(RemquoTest, NormalRange) { - constexpr UIntType count = 1000001; - constexpr UIntType step = (FPBits::maxNormal - FPBits::minNormal) / count; - for (UIntType v = FPBits::minNormal, w = FPBits::maxNormal; - v <= FPBits::maxNormal && w >= FPBits::minNormal; v += step, w -= step) { - double x = FPBits(v), y = FPBits(w); - mpfr::BinaryOutput<double> result; - mpfr::BinaryInput<double> input{x, y}; - result.f = __llvm_libc::remquo(x, y, &result.i); - ASSERT_MPFR_MATCH(mpfr::Operation::RemQuo, input, result, 0.0); - } -} +LIST_REMQUO_TESTS(double, __llvm_libc::remquo) diff --git a/libc/test/src/math/remquof_test.cpp b/libc/test/src/math/remquof_test.cpp index 4ede7fb3feec..1af4ba4e0153 100644 --- a/libc/test/src/math/remquof_test.cpp +++ b/libc/test/src/math/remquof_test.cpp @@ -6,82 +6,8 @@ // //===----------------------------------------------------------------------===// -#include "src/math/remquof.h" -#include "utils/FPUtil/BasicOperations.h" -#include "utils/FPUtil/FPBits.h" -#include "utils/FPUtil/TestHelpers.h" -#include "utils/MPFRWrapper/MPFRUtils.h" -#include "utils/UnitTest/Test.h" -#include <math.h> - -using FPBits = __llvm_libc::fputil::FPBits<float>; -using UIntType = FPBits::UIntType; - -namespace mpfr = __llvm_libc::testing::mpfr; - -DECLARE_SPECIAL_CONSTANTS(float) - -TEST(RemquofTest, SpecialNumbers) { - int exponent; - float x, y; - - y = 1.0f; - x = inf; - EXPECT_NE(isnan(__llvm_libc::remquof(x, y, &exponent)), 0); - x = negInf; - EXPECT_NE(isnan(__llvm_libc::remquof(x, y, &exponent)), 0); - - x = 1.0f; - y = zero; - EXPECT_NE(isnan(__llvm_libc::remquof(x, y, &exponent)), 0); - y = negZero; - EXPECT_NE(isnan(__llvm_libc::remquof(x, y, &exponent)), 0); +#include "RemQuoTest.h" - y = nan; - x = 1.0f; - EXPECT_NE(isnan(__llvm_libc::remquof(x, y, &exponent)), 0); - - y = 1.0f; - x = nan; - EXPECT_NE(isnan(__llvm_libc::remquof(x, y, &exponent)), 0); - - x = nan; - y = nan; - EXPECT_NE(isnan(__llvm_libc::remquof(x, y, &exponent)), 0); - - x = zero; - y = 1.0f; - EXPECT_FP_EQ(__llvm_libc::remquof(x, y, &exponent), zero); - - x = negZero; - y = 1.0f; - EXPECT_FP_EQ(__llvm_libc::remquof(x, y, &exponent), negZero); -} - -TEST(RemquofTest, SubnormalRange) { - constexpr UIntType count = 1000001; - constexpr UIntType step = - (FPBits::maxSubnormal - FPBits::minSubnormal) / count; - for (UIntType v = FPBits::minSubnormal, w = FPBits::maxSubnormal; - v <= FPBits::maxSubnormal && w >= FPBits::minSubnormal; - v += step, w -= step) { - float x = FPBits(v), y = FPBits(w); - mpfr::BinaryOutput<float> result; - mpfr::BinaryInput<float> input{x, y}; - result.f = __llvm_libc::remquof(x, y, &result.i); - ASSERT_MPFR_MATCH(mpfr::Operation::RemQuo, input, result, 0.0); - } -} +#include "src/math/remquof.h" -TEST(RemquofTest, NormalRange) { - constexpr UIntType count = 1000001; - constexpr UIntType step = (FPBits::maxNormal - FPBits::minNormal) / count; - for (UIntType v = FPBits::minNormal, w = FPBits::maxNormal; - v <= FPBits::maxNormal && w >= FPBits::minNormal; v += step, w -= step) { - float x = FPBits(v), y = FPBits(w); - mpfr::BinaryOutput<float> result; - mpfr::BinaryInput<float> input{x, y}; - result.f = __llvm_libc::remquof(x, y, &result.i); - ASSERT_MPFR_MATCH(mpfr::Operation::RemQuo, input, result, 0.0); - } -} +LIST_REMQUO_TESTS(float, __llvm_libc::remquof) diff --git a/libc/test/src/math/remquol_test.cpp b/libc/test/src/math/remquol_test.cpp index 1539aabead95..e4438e83fe18 100644 --- a/libc/test/src/math/remquol_test.cpp +++ b/libc/test/src/math/remquol_test.cpp @@ -6,88 +6,8 @@ // //===----------------------------------------------------------------------===// -#include "src/math/remquol.h" -#include "utils/FPUtil/BasicOperations.h" -#include "utils/FPUtil/FPBits.h" -#include "utils/FPUtil/TestHelpers.h" -#include "utils/MPFRWrapper/MPFRUtils.h" -#include "utils/UnitTest/Test.h" -#include <math.h> - -using FPBits = __llvm_libc::fputil::FPBits<long double>; -using UIntType = FPBits::UIntType; - -namespace mpfr = __llvm_libc::testing::mpfr; - -DECLARE_SPECIAL_CONSTANTS(long double) - -TEST(RemquolTest, SpecialNumbers) { - int exponent; - long double x, y; - - y = 1.0l; - x = inf; - EXPECT_NE(isnan(__llvm_libc::remquol(x, y, &exponent)), 0); - x = negInf; - EXPECT_NE(isnan(__llvm_libc::remquol(x, y, &exponent)), 0); - - x = 1.0l; - y = zero; - EXPECT_NE(isnan(__llvm_libc::remquol(x, y, &exponent)), 0); - y = negZero; - EXPECT_NE(isnan(__llvm_libc::remquol(x, y, &exponent)), 0); +#include "RemQuoTest.h" - y = nan; - x = 1.0l; - EXPECT_NE(isnan(__llvm_libc::remquol(x, y, &exponent)), 0); - - y = 1.0l; - x = nan; - EXPECT_NE(isnan(__llvm_libc::remquol(x, y, &exponent)), 0); - - x = nan; - y = nan; - EXPECT_NE(isnan(__llvm_libc::remquol(x, y, &exponent)), 0); - - x = zero; - y = 1.0l; - EXPECT_FP_EQ(__llvm_libc::remquol(x, y, &exponent), zero); - - x = negZero; - y = 1.0l; - EXPECT_FP_EQ(__llvm_libc::remquol(x, y, &exponent), negZero); -} - -TEST(RemquolTest, SubnormalRange) { - constexpr UIntType count = 1000001; - constexpr UIntType step = - (FPBits::maxSubnormal - FPBits::minSubnormal) / count; - for (UIntType v = FPBits::minSubnormal, w = FPBits::maxSubnormal; - v <= FPBits::maxSubnormal && w >= FPBits::minSubnormal; - v += step, w -= step) { - long double x = FPBits(v), y = FPBits(w); - mpfr::BinaryOutput<long double> result; - mpfr::BinaryInput<long double> input{x, y}; - result.f = __llvm_libc::remquol(x, y, &result.i); - ASSERT_MPFR_MATCH(mpfr::Operation::RemQuo, input, result, 0.0); - } -} +#include "src/math/remquol.h" -TEST(RemquolTest, NormalRange) { - constexpr UIntType count = 1000001; - constexpr UIntType step = (FPBits::maxNormal - FPBits::minNormal) / count; - for (UIntType v = FPBits::minNormal, w = FPBits::maxNormal; - v <= FPBits::maxNormal && w >= FPBits::minNormal; v += step, w -= step) { - long double x = FPBits(v), y = FPBits(w); - mpfr::BinaryOutput<long double> result; - result.f = __llvm_libc::remquol(x, y, &result.i); - // In normal range on x86 platforms, the implicit 1 bit can be zero making - // the numbers NaN. Hence we test for them separately. - if (isnan(x) || isnan(y)) { - ASSERT_NE(isnan(result.f), 0); - } else { - mpfr::BinaryInput<long double> input{x, y}; - ASSERT_MPFR_MATCH(mpfr::Operation::RemQuo, input, result, 0.0); - } - } -} +LIST_REMQUO_TESTS(long double, __llvm_libc::remquol) |