Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[libc][math] Add MPFR unit tests for nearbyint{,f,l,f16} #94479

Merged
merged 2 commits into from
Jul 1, 2024

Conversation

overmighty
Copy link
Member

No description provided.

@overmighty
Copy link
Member Author

cc @lntue

Based on #94473.

@@ -131,7 +138,7 @@ class RIntTestTemplate : public LIBC_NAMESPACE::testing::FEnvSafeTest {
for (int mode : ROUNDING_MODES) {
LIBC_NAMESPACE::fputil::set_round(mode);
mpfr::RoundingMode mpfr_mode = to_mpfr_rounding_mode(mode);
ASSERT_FP_EQ(func(x), mpfr::round(x, mpfr_mode));
EXPECT_FP_EQ(func(x), mpfr::round(x, mpfr_mode));
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it be worth it to also use EXPECT_FP_EQ_WITH_EXCEPTION here based on the mantissa of x/xbits?

@overmighty overmighty marked this pull request as draft June 5, 2024 17:22
@overmighty
Copy link
Member Author

Marking as draft until #94383 is relanded.

@overmighty overmighty force-pushed the libc-math-nearbyint-mpfr-tests branch from b22bafa to 23b9596 Compare June 26, 2024 16:29
@overmighty overmighty marked this pull request as ready for review June 26, 2024 16:29
@llvmbot llvmbot added the libc label Jun 26, 2024
@overmighty
Copy link
Member Author

cc @lntue

@llvmbot
Copy link
Member

llvmbot commented Jun 26, 2024

@llvm/pr-subscribers-libc

Author: OverMighty (overmighty)

Changes

Full diff: https://github.com/llvm/llvm-project/pull/94479.diff

6 Files Affected:

  • (modified) libc/test/src/math/CMakeLists.txt (+64)
  • (added) libc/test/src/math/NearbyIntTest.h (+128)
  • (added) libc/test/src/math/nearbyint_test.cpp (+13)
  • (added) libc/test/src/math/nearbyintf16_test.cpp (+13)
  • (added) libc/test/src/math/nearbyintf_test.cpp (+13)
  • (added) libc/test/src/math/nearbyintl_test.cpp (+13)
diff --git a/libc/test/src/math/CMakeLists.txt b/libc/test/src/math/CMakeLists.txt
index ba588662f469e..aaf1009ba0f75 100644
--- a/libc/test/src/math/CMakeLists.txt
+++ b/libc/test/src/math/CMakeLists.txt
@@ -574,6 +574,70 @@ add_fp_unittest(
     libc.src.__support.FPUtil.fp_bits
 )
 
+add_fp_unittest(
+  nearbyint_test
+  NEED_MPFR
+  SUITE
+    libc-math-unittests
+  SRCS
+    nearbyint_test.cpp
+  HDRS
+    NearbyIntTest.h
+  DEPENDS
+    libc.hdr.fenv_macros
+    libc.src.math.nearbyint
+    libc.src.__support.CPP.algorithm
+    libc.src.__support.FPUtil.fenv_impl
+)
+
+add_fp_unittest(
+  nearbyintf_test
+  NEED_MPFR
+  SUITE
+    libc-math-unittests
+  SRCS
+    nearbyintf_test.cpp
+  HDRS
+    NearbyIntTest.h
+  DEPENDS
+    libc.hdr.fenv_macros
+    libc.src.math.nearbyintf
+    libc.src.__support.CPP.algorithm
+    libc.src.__support.FPUtil.fenv_impl
+)
+
+add_fp_unittest(
+  nearbyintl_test
+  NEED_MPFR
+  SUITE
+    libc-math-unittests
+  SRCS
+    nearbyintl_test.cpp
+  HDRS
+    NearbyIntTest.h
+  DEPENDS
+    libc.hdr.fenv_macros
+    libc.src.math.nearbyintl
+    libc.src.__support.CPP.algorithm
+    libc.src.__support.FPUtil.fenv_impl
+)
+
+add_fp_unittest(
+  nearbyintf16_test
+  NEED_MPFR
+  SUITE
+    libc-math-unittests
+  SRCS
+    nearbyintf16_test.cpp
+  HDRS
+    NearbyIntTest.h
+  DEPENDS
+    libc.hdr.fenv_macros
+    libc.src.math.nearbyintf16
+    libc.src.__support.CPP.algorithm
+    libc.src.__support.FPUtil.fenv_impl
+)
+
 add_fp_unittest(
   rint_test
   NEED_MPFR
diff --git a/libc/test/src/math/NearbyIntTest.h b/libc/test/src/math/NearbyIntTest.h
new file mode 100644
index 0000000000000..fabe4bf00e150
--- /dev/null
+++ b/libc/test/src/math/NearbyIntTest.h
@@ -0,0 +1,128 @@
+//===-- Utility class to test different flavors of nearbyint ----*- 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_NEARBYINTTEST_H
+#define LLVM_LIBC_TEST_SRC_MATH_NEARBYINTTEST_H
+
+#include "src/__support/CPP/algorithm.h"
+#include "src/__support/FPUtil/FEnvImpl.h"
+#include "test/UnitTest/FEnvSafeTest.h"
+#include "test/UnitTest/FPMatcher.h"
+#include "test/UnitTest/Test.h"
+#include "utils/MPFRWrapper/MPFRUtils.h"
+
+#include "hdr/fenv_macros.h"
+
+namespace mpfr = LIBC_NAMESPACE::testing::mpfr;
+
+template <typename T>
+class NearbyIntTestTemplate : public LIBC_NAMESPACE::testing::FEnvSafeTest {
+
+  DECLARE_SPECIAL_CONSTANTS(T)
+
+  static constexpr int ROUNDING_MODES[4] = {FE_UPWARD, FE_DOWNWARD,
+                                            FE_TOWARDZERO, FE_TONEAREST};
+
+  static constexpr StorageType MIN_SUBNORMAL =
+      FPBits::min_subnormal().uintval();
+  static constexpr StorageType MAX_SUBNORMAL =
+      FPBits::max_subnormal().uintval();
+  static constexpr StorageType MIN_NORMAL = FPBits::min_normal().uintval();
+  static constexpr StorageType MAX_NORMAL = FPBits::max_normal().uintval();
+
+  static mpfr::RoundingMode to_mpfr_rounding_mode(int mode) {
+    switch (mode) {
+    case FE_UPWARD:
+      return mpfr::RoundingMode::Upward;
+    case FE_DOWNWARD:
+      return mpfr::RoundingMode::Downward;
+    case FE_TOWARDZERO:
+      return mpfr::RoundingMode::TowardZero;
+    case FE_TONEAREST:
+      return mpfr::RoundingMode::Nearest;
+    default:
+      __builtin_unreachable();
+    }
+  }
+
+public:
+  using NearbyIntFunc = T (*)(T);
+
+  void test_round_numbers(NearbyIntFunc func) {
+    for (int mode : ROUNDING_MODES) {
+      LIBC_NAMESPACE::fputil::set_round(mode);
+      mpfr::RoundingMode mpfr_mode = to_mpfr_rounding_mode(mode);
+      EXPECT_FP_EQ(func(T(1.0)), mpfr::round(T(1.0), mpfr_mode));
+      EXPECT_FP_EQ(func(T(-1.0)), mpfr::round(T(-1.0), mpfr_mode));
+      EXPECT_FP_EQ(func(T(10.0)), mpfr::round(T(10.0), mpfr_mode));
+      EXPECT_FP_EQ(func(T(-10.0)), mpfr::round(T(-10.0), mpfr_mode));
+      EXPECT_FP_EQ(func(T(1234.0)), mpfr::round(T(1234.0), mpfr_mode));
+      EXPECT_FP_EQ(func(T(-1234.0)), mpfr::round(T(-1234.0), mpfr_mode));
+    }
+  }
+
+  void test_fractions(NearbyIntFunc func) {
+    for (int mode : ROUNDING_MODES) {
+      LIBC_NAMESPACE::fputil::set_round(mode);
+      mpfr::RoundingMode mpfr_mode = to_mpfr_rounding_mode(mode);
+      EXPECT_FP_EQ(func(T(0.5)), mpfr::round(T(0.5), mpfr_mode));
+      EXPECT_FP_EQ(func(T(-0.5)), mpfr::round(T(-0.5), mpfr_mode));
+      EXPECT_FP_EQ(func(T(0.115)), mpfr::round(T(0.115), mpfr_mode));
+      EXPECT_FP_EQ(func(T(-0.115)), mpfr::round(T(-0.115), mpfr_mode));
+      EXPECT_FP_EQ(func(T(0.715)), mpfr::round(T(0.715), mpfr_mode));
+      EXPECT_FP_EQ(func(T(-0.715)), mpfr::round(T(-0.715), mpfr_mode));
+    }
+  }
+
+  void test_subnormal_range(NearbyIntFunc func) {
+    constexpr int COUNT = 100'001;
+    const StorageType STEP = LIBC_NAMESPACE::cpp::max(
+        static_cast<StorageType>((MAX_SUBNORMAL - MIN_SUBNORMAL) / COUNT),
+        StorageType(1));
+    for (StorageType i = MIN_SUBNORMAL; i <= MAX_SUBNORMAL; i += STEP) {
+      T x = FPBits(i).get_val();
+      for (int mode : ROUNDING_MODES) {
+        LIBC_NAMESPACE::fputil::set_round(mode);
+        mpfr::RoundingMode mpfr_mode = to_mpfr_rounding_mode(mode);
+        EXPECT_FP_EQ(func(x), mpfr::round(x, mpfr_mode));
+      }
+    }
+  }
+
+  void test_normal_range(NearbyIntFunc func) {
+    constexpr int COUNT = 100'001;
+    const StorageType STEP = LIBC_NAMESPACE::cpp::max(
+        static_cast<StorageType>((MAX_NORMAL - MIN_NORMAL) / COUNT),
+        StorageType(1));
+    for (StorageType i = MIN_NORMAL; i <= MAX_NORMAL; i += STEP) {
+      FPBits xbits(i);
+      T x = xbits.get_val();
+      // In normal range on x86 platforms, the long double implicit 1 bit can be
+      // zero making the numbers NaN. We will skip them.
+      if (xbits.is_nan())
+        continue;
+
+      for (int mode : ROUNDING_MODES) {
+        LIBC_NAMESPACE::fputil::set_round(mode);
+        mpfr::RoundingMode mpfr_mode = to_mpfr_rounding_mode(mode);
+        EXPECT_FP_EQ(func(x), mpfr::round(x, mpfr_mode));
+      }
+    }
+  }
+};
+
+#define LIST_NEARBYINT_TESTS(F, func)                                          \
+  using LlvmLibcNearbyIntTest = NearbyIntTestTemplate<F>;                      \
+  TEST_F(LlvmLibcNearbyIntTest, RoundNumbers) { test_round_numbers(&func); }   \
+  TEST_F(LlvmLibcNearbyIntTest, Fractions) { test_fractions(&func); }          \
+  TEST_F(LlvmLibcNearbyIntTest, SubnormalRange) {                              \
+    test_subnormal_range(&func);                                               \
+  }                                                                            \
+  TEST_F(LlvmLibcNearbyIntTest, NormalRange) { test_normal_range(&func); }
+
+#endif // LLVM_LIBC_TEST_SRC_MATH_NEARBYINTTEST_H
diff --git a/libc/test/src/math/nearbyint_test.cpp b/libc/test/src/math/nearbyint_test.cpp
new file mode 100644
index 0000000000000..11a5c3372e73e
--- /dev/null
+++ b/libc/test/src/math/nearbyint_test.cpp
@@ -0,0 +1,13 @@
+//===-- Unittests for nearbyint -------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "NearbyIntTest.h"
+
+#include "src/math/nearbyint.h"
+
+LIST_NEARBYINT_TESTS(double, LIBC_NAMESPACE::nearbyint)
diff --git a/libc/test/src/math/nearbyintf16_test.cpp b/libc/test/src/math/nearbyintf16_test.cpp
new file mode 100644
index 0000000000000..e6ec250cec91f
--- /dev/null
+++ b/libc/test/src/math/nearbyintf16_test.cpp
@@ -0,0 +1,13 @@
+//===-- Unittests for nearbyintf16 ----------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "NearbyIntTest.h"
+
+#include "src/math/nearbyintf16.h"
+
+LIST_NEARBYINT_TESTS(float16, LIBC_NAMESPACE::nearbyintf16)
diff --git a/libc/test/src/math/nearbyintf_test.cpp b/libc/test/src/math/nearbyintf_test.cpp
new file mode 100644
index 0000000000000..fd26153cfffb9
--- /dev/null
+++ b/libc/test/src/math/nearbyintf_test.cpp
@@ -0,0 +1,13 @@
+//===-- Unittests for nearbyintf ------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "NearbyIntTest.h"
+
+#include "src/math/nearbyintf.h"
+
+LIST_NEARBYINT_TESTS(float, LIBC_NAMESPACE::nearbyintf)
diff --git a/libc/test/src/math/nearbyintl_test.cpp b/libc/test/src/math/nearbyintl_test.cpp
new file mode 100644
index 0000000000000..a6d81a1439e17
--- /dev/null
+++ b/libc/test/src/math/nearbyintl_test.cpp
@@ -0,0 +1,13 @@
+//===-- Unittests for nearbyintl ------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "NearbyIntTest.h"
+
+#include "src/math/nearbyintl.h"
+
+LIST_NEARBYINT_TESTS(long double, LIBC_NAMESPACE::nearbyintl)

@lntue lntue merged commit 44a2589 into llvm:main Jul 1, 2024
6 checks passed
lravenclaw pushed a commit to lravenclaw/llvm-project that referenced this pull request Jul 3, 2024
kbluck pushed a commit to kbluck/llvm-project that referenced this pull request Jul 6, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants