-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[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
[libc] Add inf/nan tests for strfrom*() functions #86663
Conversation
@llvm/pr-subscribers-libc Author: Vinayak Dev (vinayakdsci) ChangesAdds tests for Also marks some variables as Full diff: https://github.com/llvm/llvm-project/pull/86663.diff 2 Files Affected:
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); }
|
✅ With the latest revision this PR passed the C/C++ code formatter. |
be79ebc
to
534f8bc
Compare
There was a problem hiding this 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.
Thanks! Could you land this for me?
OK, I will look into that too. It might take some time, though, as I would need to familiarise myself with bazel. |
libc/test/src/stdlib/StrfromTest.h
Outdated
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) |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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!
534f8bc
to
9d79236
Compare
Adds tests for
inf
andnan
values to the tests forstrfrom*()
functions.Also marks some variables as
[[maybe_unused]]
to silence unused variable warnings.