Skip to content

[libc] Add inf/nan tests for strfrom*() functions #86663

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

Merged
merged 1 commit into from
Mar 28, 2024

Conversation

vinayakdsci
Copy link
Contributor

Adds tests for inf and nan values to the tests for strfrom*() functions.

Also marks some variables as [[maybe_unused]] to silence unused variable warnings.

@llvmbot llvmbot added the libc label Mar 26, 2024
@llvmbot
Copy link
Member

llvmbot commented Mar 26, 2024

@llvm/pr-subscribers-libc

Author: Vinayak Dev (vinayakdsci)

Changes

Adds tests for inf and nan values to the tests for strfrom*() functions.

Also marks some variables as [[maybe_unused]] to silence unused variable warnings.


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

2 Files Affected:

  • (modified) libc/test/src/stdlib/CMakeLists.txt (+1)
  • (modified) libc/test/src/stdlib/StrfromTest.h (+81-10)
diff --git a/libc/test/src/stdlib/CMakeLists.txt b/libc/test/src/stdlib/CMakeLists.txt
index 3ccc1cde91934c..28c5b566cc4772 100644
--- a/libc/test/src/stdlib/CMakeLists.txt
+++ b/libc/test/src/stdlib/CMakeLists.txt
@@ -174,6 +174,7 @@ add_header_library(
   StrfromTest.h
   DEPENDS
   libc.src.__support.CPP.type_traits
+  libc.src.__support.FPUtil.fp_bits
 )
 
 add_libc_test(
diff --git a/libc/test/src/stdlib/StrfromTest.h b/libc/test/src/stdlib/StrfromTest.h
index f695bbb335bdbe..0b9a48e69165c1 100644
--- a/libc/test/src/stdlib/StrfromTest.h
+++ b/libc/test/src/stdlib/StrfromTest.h
@@ -7,6 +7,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "src/__support/CPP/type_traits.h"
+#include "src/__support/FPUtil/FPBits.h"
 #include "test/UnitTest/Test.h"
 
 #define ASSERT_STREQ_LEN(actual_written, actual_str, expected_str)             \
@@ -68,11 +69,27 @@ class StrfromTest : public LIBC_NAMESPACE::testing::Test {
     written = func(buff, 37, "A simple string with no conversions.", 1.0);
     ASSERT_STREQ_LEN(written, buff, "A simple string with no conversions.");
 
-    written =
-        func(buff, 37,
-             "%A simple string with one conversion, should overwrite.", 1.0);
-    ASSERT_STREQ_LEN(written, buff, is_long_double ? "0X8P-3" : "0X1P+0");
-
+    if (is_long_double) {
+      // 64-bit long double values require checking as they will give
+      // a different result
+#if defined(LIBC_TYPES_LONG_DOUBLE_IS_FLOAT64)
+      written =
+          func(buff, 37,
+               "%A simple string with one conversion, should overwrite.", 1.0);
+      ASSERT_STREQ_LEN(written, buff, "0X1P+0");
+#else
+      written =
+          func(buff, 37,
+               "%A simple string with one conversion, should overwrite.", 1.0);
+      ASSERT_STREQ_LEN(written, buff, "0X8P-3");
+#endif
+    } else {
+      // not long double
+      written =
+          func(buff, 37,
+               "%A simple string with one conversion, should overwrite.", 1.0);
+      ASSERT_STREQ_LEN(written, buff, "0X1P+0");
+    }
     written = func(buff, 74,
                    "A simple string with one conversion in %A "
                    "between, writes string as it is",
@@ -105,6 +122,13 @@ class StrfromTest : public LIBC_NAMESPACE::testing::Test {
     ASSERT_STREQ(buff, "1.05"); // Make sure that buff has not changed
   }
 
+  void infNanValues(FunctionT func) {
+    if(is_double_prec)
+      doublePrecInfNan(func);
+    else if(!is_single_prec)
+      longDoublePrecInfNan(func);
+  }
+
   void floatDecimalSinglePrec(FunctionT func) {
     char buff[70];
     int written;
@@ -336,8 +360,10 @@ class StrfromTest : public LIBC_NAMESPACE::testing::Test {
   }
 
   void floatDecimalExpLongDoublePrec(FunctionT func) {
-    char buff[100];
-    int written;
+    // Mark as maybe_unused to silence unused variable
+    // warning when long double is not 80-bit
+    [[maybe_unused]] char buff[100];
+    [[maybe_unused]] int written;
 
 #if defined(LIBC_TYPES_LONG_DOUBLE_IS_X86_FLOAT80)
     written = func(buff, 90, "%.9e", 1000000000500000000.1L);
@@ -399,8 +425,10 @@ class StrfromTest : public LIBC_NAMESPACE::testing::Test {
   }
 
   void floatDecimalAutoLongDoublePrec(FunctionT func) {
-    char buff[100];
-    int written;
+    // Mark as maybe_unused to silence unused variable
+    // warning when long double is not 80-bit
+    [[maybe_unused]] char buff[100];
+    [[maybe_unused]] int written;
 
 #if defined(LIBC_TYPES_LONG_DOUBLE_IS_X86_FLOAT80)
     written = func(buff, 99, "%g", 0xf.fffffffffffffffp+16380L);
@@ -413,6 +441,48 @@ class StrfromTest : public LIBC_NAMESPACE::testing::Test {
     ASSERT_STREQ_LEN(written, buff, "1e-99");
 #endif // LIBC_TYPES_LONG_DOUBLE_IS_X86_FLOAT80
   }
+
+  void doublePrecInfNan(FunctionT func) {
+    char buff[15];
+    int written;
+
+    double inf = LIBC_NAMESPACE::fputil::FPBits<double>::inf().get_val();
+    double nan = LIBC_NAMESPACE::fputil::FPBits<double>::quiet_nan().get_val();
+
+    written = func(buff, 10, "%f", inf);
+    ASSERT_STREQ_LEN(written, buff, "inf");
+
+    written = func(buff, 10, "%A", -inf);
+    ASSERT_STREQ_LEN(written, buff, "-INF");
+
+    written = func(buff, 10, "%f", nan);
+    ASSERT_STREQ_LEN(written, buff, "nan");
+
+    written = func(buff, 10, "%A", -nan);
+    ASSERT_STREQ_LEN(written, buff, "-NAN");
+  }
+
+  void longDoublePrecInfNan(FunctionT func) {
+    char buff[15];
+    int written;
+
+    long double ld_inf =
+        LIBC_NAMESPACE::fputil::FPBits<long double>::inf().get_val();
+    long double ld_nan =
+        LIBC_NAMESPACE::fputil::FPBits<long double>::quiet_nan().get_val();
+
+    written = func(buff, 10, "%f", ld_inf);
+    ASSERT_STREQ_LEN(written, buff, "inf");
+
+    written = func(buff, 10, "%A", -ld_inf);
+    ASSERT_STREQ_LEN(written, buff, "-INF");
+
+    written = func(buff, 10, "%f", ld_nan);
+    ASSERT_STREQ_LEN(written, buff, "nan");
+
+    written = func(buff, 10, "%A", -ld_nan);
+    ASSERT_STREQ_LEN(written, buff, "-NAN");
+  }
 };
 
 #define STRFROM_TEST(InputType, name, func)                                    \
@@ -432,4 +502,5 @@ class StrfromTest : public LIBC_NAMESPACE::testing::Test {
   }                                                                            \
   TEST_F(LlvmLibc##name##Test, InsufficientBufferSize) {                       \
     insufficentBufsize(func);                                                  \
-  }
+  }                                                                            \
+  TEST_F(LlvmLibc##name##Test, InfAndNanValues) { infNanValues(func); }

Copy link

github-actions bot commented Mar 26, 2024

✅ With the latest revision this PR passed the C/C++ code formatter.

@vinayakdsci vinayakdsci force-pushed the add-strfrom-inf-nan-tests branch from be79ebc to 534f8bc Compare March 26, 2024 14:06
Copy link
Contributor

@michaelrj-google michaelrj-google left a comment

Choose a reason for hiding this comment

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

This patch LGTM

If you're looking for more things to do, then adding the strfrom functions to the bazel build would also be useful.

@vinayakdsci
Copy link
Contributor Author

This patch LGTM

Thanks! Could you land this for me?

If you're looking for more things to do, then adding the strfrom functions to the bazel build would also be useful.

OK, I will look into that too. It might take some time, though, as I would need to familiarise myself with bazel.

if (is_long_double) {
// 64-bit long double values require checking as they will give
// a different result
#if defined(LIBC_TYPES_LONG_DOUBLE_IS_FLOAT64)
Copy link
Contributor

Choose a reason for hiding this comment

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

long double can be 64, 80 or 128 bits so technically we'd need the following cases:

  • LIBC_TYPES_LONG_DOUBLE_IS_FLOAT64
  • LIBC_TYPES_LONG_DOUBLE_IS_X86_FLOAT80
  • LIBC_TYPES_LONG_DOUBLE_IS_FLOAT128

Copy link
Contributor Author

@vinayakdsci vinayakdsci Mar 27, 2024

Choose a reason for hiding this comment

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

@gchatelet The tests work for 64 bit and 80-bit long doubles, but I am unsure on how to test for 128 bit ones. Do you have any pointers?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@gchatelet I am sorry, I ran some tests on my computer using libquadmath, and I found that 64-bit and 128-bit floats give identical outputs, while 80-bits do not. I will update the tests, and re-push.
Thanks for the review!

@vinayakdsci vinayakdsci force-pushed the add-strfrom-inf-nan-tests branch from 534f8bc to 9d79236 Compare March 27, 2024 18:46
@michaelrj-google michaelrj-google merged commit 6373577 into llvm:main Mar 28, 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.

4 participants