Skip to content

[libc] Unit test for isnan[f,l] #98274

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

Open
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

petrhosek
Copy link
Member

This is a follow up to #98271.

@petrhosek petrhosek added the libc label Jul 10, 2024
@petrhosek petrhosek requested a review from lntue July 10, 2024 06:10
@llvmbot
Copy link
Member

llvmbot commented Jul 10, 2024

@llvm/pr-subscribers-libc

Author: Petr Hosek (petrhosek)

Changes

This is a follow up to #98271.


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

5 Files Affected:

  • (modified) libc/test/src/math/CMakeLists.txt (+39)
  • (added) libc/test/src/math/IsNanTest.h (+53)
  • (added) libc/test/src/math/isnan_test.cpp (+16)
  • (added) libc/test/src/math/isnanf_test.cpp (+13)
  • (added) libc/test/src/math/isnanl_test.cpp (+13)
diff --git a/libc/test/src/math/CMakeLists.txt b/libc/test/src/math/CMakeLists.txt
index 0dc7ae6aae2df..2e97d46b870d0 100644
--- a/libc/test/src/math/CMakeLists.txt
+++ b/libc/test/src/math/CMakeLists.txt
@@ -2225,6 +2225,45 @@ add_fp_unittest(
     libc.src.__support.FPUtil.fp_bits
 )
 
+add_fp_unittest(
+  isnan_test
+  SUITE
+    libc-math-unittests
+  SRCS
+    isnan_test.cpp
+  HDRS
+    IsNanTest.h
+  DEPENDS
+    libc.src.math.isnan
+    libc.src.__support.FPUtil.fp_bits
+)
+
+add_fp_unittest(
+  isnanf_test
+  SUITE
+    libc-math-unittests
+  SRCS
+    isnanf_test.cpp
+  HDRS
+    IsNanTest.h
+  DEPENDS
+    libc.src.math.isnanf
+    libc.src.__support.FPUtil.fp_bits
+)
+
+add_fp_unittest(
+  isnanl_test
+  SUITE
+    libc-math-unittests
+  SRCS
+    isnanl_test.cpp
+  HDRS
+    IsNanTest.h
+  DEPENDS
+    libc.src.math.isnanl
+    libc.src.__support.FPUtil.fp_bits
+)
+
 add_subdirectory(generic)
 add_subdirectory(smoke)
 
diff --git a/libc/test/src/math/IsNanTest.h b/libc/test/src/math/IsNanTest.h
new file mode 100644
index 0000000000000..64513cef6e7d0
--- /dev/null
+++ b/libc/test/src/math/IsNanTest.h
@@ -0,0 +1,53 @@
+//===-- Utility class to test isnan[f|l] ------------------------*- 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "test/UnitTest/FEnvSafeTest.h"
+#include "test/UnitTest/FPMatcher.h"
+#include "test/UnitTest/Test.h"
+
+template <typename T>
+class IsNanTest : public LIBC_NAMESPACE::testing::FEnvSafeTest {
+
+  DECLARE_SPECIAL_CONSTANTS(T)
+
+  static constexpr T one = static_cast<T>(1.0);
+  static constexpr T neg_one = static_cast<T>(-1.0);
+
+public:
+  typedef int (*IsNanFunc)(T);
+
+  void testSpecialNumbers(IsNanFunc func) {
+    EXPECT_EQ(func(zero), 0);
+    EXPECT_EQ(func(one), 0);
+    EXPECT_EQ(func(inf), 0);
+    EXPECT_EQ(func(aNaN), 1);
+
+    EXPECT_EQ(func(neg_zero), 0);
+    EXPECT_EQ(func(neg_one), 0);
+    EXPECT_EQ(func(neg_inf), 0);
+    EXPECT_EQ(func(neg_aNaN), 1);
+  }
+
+  void testSpecialCases(IsNanFunc func) {
+    EXPECT_EQ(func(one / zero), 0);
+    EXPECT_EQ(func(one / inf), 0);
+    EXPECT_EQ(func(one / neg_inf), 0);
+    EXPECT_EQ(func(inf / neg_inf), 1);
+
+    EXPECT_EQ(func(inf * neg_inf), 0);
+    EXPECT_EQ(func(inf * zero), 1);
+    EXPECT_EQ(func(neg_inf * zero), 1);
+
+    EXPECT_EQ(func(inf + neg_inf), 1);
+  }
+};
+
+#define LIST_ISNAN_TESTS(T, func)                                              \
+  using LlvmLibcIsNanTest = IsNanTest<T>;                                      \
+  TEST_F(LlvmLibcIsNanTest, SpecialNumbers) { testSpecialNumbers(&func); }     \
+  TEST_F(LlvmLibcIsNanTest, SpecialCases) { testSpecialCases(&func); }
diff --git a/libc/test/src/math/isnan_test.cpp b/libc/test/src/math/isnan_test.cpp
new file mode 100644
index 0000000000000..ecee01b019554
--- /dev/null
+++ b/libc/test/src/math/isnan_test.cpp
@@ -0,0 +1,16 @@
+//===-- Unittests for isnan -----------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDSList-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "IsNanTest.h"
+
+// We need to avoid expanding isnan to __builtin_isnan.
+#undef isnan
+
+#include "src/math/isnan.h"
+
+LIST_ISNAN_TESTS(double, LIBC_NAMESPACE::isnan)
diff --git a/libc/test/src/math/isnanf_test.cpp b/libc/test/src/math/isnanf_test.cpp
new file mode 100644
index 0000000000000..633573a9e83b2
--- /dev/null
+++ b/libc/test/src/math/isnanf_test.cpp
@@ -0,0 +1,13 @@
+//===-- Unittests for isnanf ----------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDSList-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "IsNanTest.h"
+
+#include "src/math/isnanf.h"
+
+LIST_ISNAN_TESTS(float, LIBC_NAMESPACE::isnanf)
diff --git a/libc/test/src/math/isnanl_test.cpp b/libc/test/src/math/isnanl_test.cpp
new file mode 100644
index 0000000000000..1e5f4f4057f19
--- /dev/null
+++ b/libc/test/src/math/isnanl_test.cpp
@@ -0,0 +1,13 @@
+//===-- Unittests for isnanl ----------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDSList-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "IsNanTest.h"
+
+#include "src/math/isnanl.h"
+
+LIST_ISNAN_TESTS(long double, LIBC_NAMESPACE::isnanl)

#include "test/UnitTest/Test.h"

template <typename T>
class IsNanTest : public LIBC_NAMESPACE::testing::FEnvSafeTest {
Copy link
Contributor

Choose a reason for hiding this comment

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

You can inherit from testing::FPTest<T>, remove DECLARE_SPECIAL_CONSTANTS(T), and testSpecialCases.

Copy link
Member Author

Choose a reason for hiding this comment

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

I tried that but I'm getting the following error:

In file included from /usr/local/google/home/phosek/llvm/llvm-project/libc/test/src/math/isnan_test.cpp:9:
/usr/local/google/home/phosek/llvm/llvm-project/libc/test/src/math/IsNanTest.h:26:5: error: no matching function for call to 'test'
   26 |     EXPECT_EQ(func(sNaN), 1);
      |     ^~~~~~~~~~~~~~~~~~~~~~~~
/usr/local/google/home/phosek/llvm/llvm-project/libc/test/UnitTest/LibcTest.h:420:29: note: expanded from macro 'EXPECT_EQ'
  420 | #define EXPECT_EQ(LHS, RHS) LIBC_TEST_BINOP_(EQ, LHS, RHS, )
      |                             ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/local/google/home/phosek/llvm/llvm-project/libc/test/UnitTest/LibcTest.h:413:26: note: expanded from macro 'LIBC_TEST_BINOP_'
  413 |   LIBC_TEST_SCAFFOLDING_(test(LIBC_NAMESPACE::testing::TestCond::COND, LHS,    \
      |                          ^~~~
/usr/local/google/home/phosek/llvm/llvm-project/libc/test/UnitTest/LibcTest.h:406:7: note: expanded from macro 'LIBC_TEST_SCAFFOLDING_'
  406 |   if (TEST)                                                                    \
      |       ^~~~
/usr/local/google/home/phosek/llvm/llvm-project/libc/test/UnitTest/LibcTest.h:99:6: note: candidate function template not viable: requires 7 arguments, but 6 were provided
   99 | bool test(RunContext *Ctx, TestCond Cond, ValType LHS, ValType RHS,
      |      ^    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  100 |           const char *LHSStr, const char *RHSStr, Location Loc);
      |           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
6 errors generated.

Do you know what's the issue?

Copy link
Contributor

Choose a reason for hiding this comment

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

This seems to fix the issue:

diff --git a/libc/test/src/math/IsNanTest.h b/libc/test/src/math/IsNanTest.h
index e281395f2cf4..6b55333cd608 100644
--- a/libc/test/src/math/IsNanTest.h
+++ b/libc/test/src/math/IsNanTest.h
@@ -10,7 +10,7 @@
 #include "test/UnitTest/Test.h"
 
 template <typename T>
-class IsNanTest : public LIBC_NAMESPACE::testing::FPTest<T> {
+class IsNanTest : public LIBC_NAMESPACE::testing::Test {
 
   DECLARE_SPECIAL_CONSTANTS(T)


template <typename T> class IsNanTest : public LIBC_NAMESPACE::testing::Test {
template <typename T>
class IsNanTest : public LIBC_NAMESPACE::testing::FPTest<T> {

DECLARE_SPECIAL_CONSTANTS(T)
Copy link
Contributor

Choose a reason for hiding this comment

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

with FPTest<T> you don't need to add DECLARE_SPECIAL_CONSTANTS(T): https://github.com/llvm/llvm-project/blob/main/libc/test/UnitTest/FPMatcher.h#L70

Copy link
Member Author

Choose a reason for hiding this comment

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

When I do that I get the following error:

In file included from /usr/local/google/home/phosek/llvm/llvm-project/libc/test/src/math/isnan_test.cpp:9:
/usr/local/google/home/phosek/llvm/llvm-project/libc/test/src/math/IsNanTest.h:18:20: error: use of undeclared identifier 'zero'; did you mean 'erf'?
   18 |     EXPECT_EQ(func(zero), 0);
      |                    ^~~~
      |                    erf
/usr/local/google/home/phosek/llvm/llvm-project/libc/test/UnitTest/LibcTest.h:420:50: note: expanded from macro 'EXPECT_EQ'
  420 | #define EXPECT_EQ(LHS, RHS) LIBC_TEST_BINOP_(EQ, LHS, RHS, )
      |                                                  ^
/usr/local/google/home/phosek/llvm/llvm-project/libc/test/UnitTest/LibcTest.h:413:72: note: expanded from macro 'LIBC_TEST_BINOP_'
  413 |   LIBC_TEST_SCAFFOLDING_(test(LIBC_NAMESPACE::testing::TestCond::COND, LHS,    \
      |                                                                        ^
/usr/local/google/home/phosek/llvm/llvm-project/libc/test/UnitTest/LibcTest.h:406:7: note: expanded from macro 'LIBC_TEST_SCAFFOLDING_'
  406 |   if (TEST)                                                                    \
      |       ^
/usr/local/google/home/phosek/fuchsia/prebuilt/third_party/clang/linux-x64/bin/../include/c++/v1/math.h:456:20: note: 'erf' declared here
  456 | using std::__math::erf;
      |                    ^
In file included from /usr/local/google/home/phosek/llvm/llvm-project/libc/test/src/math/isnan_test.cpp:9:
/usr/local/google/home/phosek/llvm/llvm-project/libc/test/src/math/IsNanTest.h:19:20: error: use of undeclared identifier 'neg_zero'
   19 |     EXPECT_EQ(func(neg_zero), 0);
      |                    ^
/usr/local/google/home/phosek/llvm/llvm-project/libc/test/src/math/IsNanTest.h:20:20: error: use of undeclared identifier 'inf'
   20 |     EXPECT_EQ(func(inf), 0);
      |                    ^
/usr/local/google/home/phosek/llvm/llvm-project/libc/test/src/math/IsNanTest.h:21:20: error: use of undeclared identifier 'neg_inf'
   21 |     EXPECT_EQ(func(neg_inf), 0);
      |                    ^
/usr/local/google/home/phosek/llvm/llvm-project/libc/test/src/math/IsNanTest.h:22:20: error: use of undeclared identifier 'aNaN'; did you mean 'atan'?
   22 |     EXPECT_NE(func(aNaN), 0);
      |                    ^~~~
      |                    atan

Comment on lines 25 to 26
EXPECT_EQ(func(aNaN), 1);
EXPECT_EQ(func(sNaN), 1);
Copy link
Contributor

Choose a reason for hiding this comment

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

Can you change these to EXPECT_NE(func(aNaN), 0); because C standard only requires isnan macro to be non-zero instead of 1 for non-NaN cases.

@lntue
Copy link
Contributor

lntue commented Jul 14, 2024

Do you mind moving these tests to libc/test/src/math/smoke/ folder instead? I plan to have libc/test/src/math/smoke for tests that would work any where with very low dependency, while tests in libc/test/src/math/ are those that require MPFR. Thanks,

@nickdesaulniers
Copy link
Member

Status update on this PR? Merge conflict

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.

4 participants