[OptTable] Fix typo VALUE => VALUES (NFCI) (#121523)
[llvm-project.git] / libc / test / src / stdlib / StrfromTest.h
blob5209472886f78e767563b9752b81f44602aa10f0
1 //===-- A template class for testing strfrom functions ----------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
9 #include "src/__support/CPP/type_traits.h"
10 #include "src/__support/FPUtil/FPBits.h"
11 #include "test/UnitTest/Test.h"
13 #define ASSERT_STREQ_LEN(actual_written, actual_str, expected_str) \
14 EXPECT_EQ(actual_written, static_cast<int>(sizeof(expected_str) - 1)); \
15 EXPECT_STREQ(actual_str, expected_str);
17 template <typename InputT>
18 class StrfromTest : public LIBC_NAMESPACE::testing::Test {
20 static const bool is_single_prec =
21 LIBC_NAMESPACE::cpp::is_same<InputT, float>::value;
22 static const bool is_double_prec =
23 LIBC_NAMESPACE::cpp::is_same<InputT, double>::value;
25 using FunctionT = int (*)(char *, size_t, const char *, InputT fp);
27 public:
28 void floatDecimalFormat(FunctionT func) {
29 if (is_single_prec)
30 floatDecimalSinglePrec(func);
31 else if (is_double_prec)
32 floatDecimalDoublePrec(func);
33 else
34 floatDecimalLongDoublePrec(func);
37 void floatHexExpFormat(FunctionT func) {
38 if (is_single_prec)
39 floatHexExpSinglePrec(func);
40 else if (is_double_prec)
41 floatHexExpDoublePrec(func);
42 else
43 floatHexExpLongDoublePrec(func);
46 void floatDecimalExpFormat(FunctionT func) {
47 if (is_single_prec)
48 floatDecimalExpSinglePrec(func);
49 else if (is_double_prec)
50 floatDecimalExpDoublePrec(func);
51 else
52 floatDecimalExpLongDoublePrec(func);
55 void floatDecimalAutoFormat(FunctionT func) {
56 if (is_single_prec)
57 floatDecimalAutoSinglePrec(func);
58 else if (is_double_prec)
59 floatDecimalAutoDoublePrec(func);
60 else
61 floatDecimalAutoLongDoublePrec(func);
64 void improperFormatString(FunctionT func) {
65 char buff[100];
66 int written;
67 const bool is_long_double = !is_single_prec && !is_double_prec;
69 written = func(buff, 37, "A simple string with no conversions.", 1.0);
70 ASSERT_STREQ_LEN(written, buff, "A simple string with no conversions.");
72 written =
73 func(buff, 37,
74 "%A simple string with one conversion, should overwrite.", 1.0);
75 if (is_long_double) {
76 #if defined(LIBC_TYPES_LONG_DOUBLE_IS_X86_FLOAT80)
77 ASSERT_STREQ_LEN(written, buff, "0X8P-3");
78 #elif defined(LIBC_TYPES_LONG_DOUBLE_IS_FLOAT64)
79 ASSERT_STREQ_LEN(written, buff, "0X1P+0");
80 #elif defined(LIBC_TYPES_LONG_DOUBLE_IS_FLOAT128)
81 ASSERT_STREQ_LEN(written, buff, "0X1P+0");
82 #endif
83 } else {
84 // not long double
85 ASSERT_STREQ_LEN(written, buff, "0X1P+0");
87 written = func(buff, 74,
88 "A simple string with one conversion in %A "
89 "between, writes string as it is",
90 1.0);
91 ASSERT_STREQ_LEN(written, buff,
92 "A simple string with one conversion in %A between, "
93 "writes string as it is");
95 written = func(buff, 36, "A simple string with one conversion", 1.0);
96 ASSERT_STREQ_LEN(written, buff, "A simple string with one conversion");
98 written = func(buff, 20, "%1f", 1234567890.0);
99 ASSERT_STREQ_LEN(written, buff, "%1f");
102 void insufficentBufsize(FunctionT func) {
103 char buff[20];
104 int written;
106 written = func(buff, 5, "%f", 1234567890.0);
107 EXPECT_EQ(written, 17);
108 ASSERT_STREQ(buff, "1234");
110 written = func(buff, 5, "%.5f", 1.05);
111 EXPECT_EQ(written, 7);
112 ASSERT_STREQ(buff, "1.05");
114 written = func(buff, 0, "%g", 1.0);
115 EXPECT_EQ(written, 1);
116 ASSERT_STREQ(buff, "1.05"); // Make sure that buff has not changed
119 void infNanValues(FunctionT func) {
120 if (is_double_prec)
121 doublePrecInfNan(func);
122 else if (!is_single_prec)
123 longDoublePrecInfNan(func);
126 void floatDecimalSinglePrec(FunctionT func) {
127 char buff[70];
128 int written;
130 written = func(buff, 16, "%f", 1.0);
131 ASSERT_STREQ_LEN(written, buff, "1.000000");
133 written = func(buff, 20, "%f", 1234567890.0);
134 ASSERT_STREQ_LEN(written, buff, "1234567936.000000");
136 written = func(buff, 67, "%.3f", 1.0);
137 ASSERT_STREQ_LEN(written, buff, "1.000");
140 void floatDecimalDoublePrec(FunctionT func) {
141 char buff[500];
142 int written;
144 written = func(buff, 99, "%f", 1.0);
145 ASSERT_STREQ_LEN(written, buff, "1.000000");
147 written = func(buff, 99, "%F", -1.0);
148 ASSERT_STREQ_LEN(written, buff, "-1.000000");
150 written = func(buff, 99, "%f", -1.234567);
151 ASSERT_STREQ_LEN(written, buff, "-1.234567");
153 written = func(buff, 99, "%f", 0.0);
154 ASSERT_STREQ_LEN(written, buff, "0.000000");
156 written = func(buff, 99, "%f", 1.5);
157 ASSERT_STREQ_LEN(written, buff, "1.500000");
159 // Dyadic float is only accurate to ~50 digits, so skip this 300 digit test.
160 // TODO: Create way to test just the first ~50 digits of a number.
161 #ifndef LIBC_COPT_FLOAT_TO_STR_REDUCED_PRECISION
162 written = func(buff, 499, "%f", 1e300);
163 ASSERT_STREQ_LEN(written, buff,
164 "100000000000000005250476025520442024870446858110815915491"
165 "585411551180245"
166 "798890819578637137508044786404370444383288387817694252323"
167 "536043057564479"
168 "218478670698284838720092657580373783023379478809005936895"
169 "323497079994508"
170 "111903896764088007465274278014249457925878882005684283811"
171 "566947219638686"
172 "5459400540160.000000");
173 #endif // DLIBC_COPT_FLOAT_TO_STR_REDUCED_PRECISION
175 written = func(buff, 99, "%f", 0.1);
176 ASSERT_STREQ_LEN(written, buff, "0.100000");
178 written = func(buff, 99, "%f", 1234567890123456789.0);
179 ASSERT_STREQ_LEN(written, buff, "1234567890123456768.000000");
181 written = func(buff, 99, "%f", 9999999999999.99);
182 ASSERT_STREQ_LEN(written, buff, "9999999999999.990234");
184 written = func(buff, 99, "%f", 0.1);
185 ASSERT_STREQ_LEN(written, buff, "0.100000");
187 written = func(buff, 99, "%f", 1234567890123456789.0);
188 ASSERT_STREQ_LEN(written, buff, "1234567890123456768.000000");
190 written = func(buff, 99, "%f", 9999999999999.99);
191 ASSERT_STREQ_LEN(written, buff, "9999999999999.990234");
193 // Precision Tests
194 written = func(buff, 100, "%.2f", 9999999999999.99);
195 ASSERT_STREQ_LEN(written, buff, "9999999999999.99");
197 written = func(buff, 100, "%.1f", 9999999999999.99);
198 ASSERT_STREQ_LEN(written, buff, "10000000000000.0");
200 written = func(buff, 100, "%.5f", 1.25);
201 ASSERT_STREQ_LEN(written, buff, "1.25000");
203 written = func(buff, 100, "%.0f", 1.25);
204 ASSERT_STREQ_LEN(written, buff, "1");
206 written = func(buff, 100, "%.20f", 1.234e-10);
207 ASSERT_STREQ_LEN(written, buff, "0.00000000012340000000");
210 void floatDecimalLongDoublePrec(FunctionT func) {
211 char buff[45];
212 int written;
214 written = func(buff, 40, "%f", 1.0L);
215 ASSERT_STREQ_LEN(written, buff, "1.000000");
217 written = func(buff, 10, "%.f", -2.5L);
218 ASSERT_STREQ_LEN(written, buff, "-2");
221 void floatHexExpSinglePrec(FunctionT func) {
222 char buff[25];
223 int written;
225 written = func(buff, 0, "%a", 1234567890.0);
226 EXPECT_EQ(written, 14);
228 written = func(buff, 20, "%a", 1234567890.0);
229 EXPECT_EQ(written, 14);
230 ASSERT_STREQ(buff, "0x1.26580cp+30");
232 written = func(buff, 20, "%A", 1234567890.0);
233 EXPECT_EQ(written, 14);
234 ASSERT_STREQ(buff, "0X1.26580CP+30");
237 void floatHexExpDoublePrec(FunctionT func) {
238 char buff[60];
239 int written;
241 written = func(buff, 10, "%a", 1.0);
242 ASSERT_STREQ_LEN(written, buff, "0x1p+0");
244 written = func(buff, 10, "%A", -1.0);
245 ASSERT_STREQ_LEN(written, buff, "-0X1P+0");
247 written = func(buff, 30, "%a", -0x1.abcdef12345p0);
248 ASSERT_STREQ_LEN(written, buff, "-0x1.abcdef12345p+0");
250 written = func(buff, 50, "%A", 0x1.abcdef12345p0);
251 ASSERT_STREQ_LEN(written, buff, "0X1.ABCDEF12345P+0");
253 written = func(buff, 10, "%a", 0.0);
254 ASSERT_STREQ_LEN(written, buff, "0x0p+0");
256 written = func(buff, 40, "%a", 1.0e100);
257 ASSERT_STREQ_LEN(written, buff, "0x1.249ad2594c37dp+332");
259 written = func(buff, 30, "%a", 0.1);
260 ASSERT_STREQ_LEN(written, buff, "0x1.999999999999ap-4");
263 void floatHexExpLongDoublePrec(FunctionT func) {
264 char buff[55];
265 int written;
267 written = func(buff, 50, "%a", 0.1L);
268 #if defined(LIBC_TYPES_LONG_DOUBLE_IS_X86_FLOAT80)
269 ASSERT_STREQ_LEN(written, buff, "0xc.ccccccccccccccdp-7");
270 #elif defined(LIBC_TYPES_LONG_DOUBLE_IS_FLOAT64)
271 ASSERT_STREQ_LEN(written, buff, "0x1.999999999999ap-4");
272 #elif defined(LIBC_TYPES_LONG_DOUBLE_IS_FLOAT128)
273 ASSERT_STREQ_LEN(written, buff, "0x1.999999999999999999999999999ap-4");
274 #endif
276 written = func(buff, 20, "%.1a", 0.1L);
277 #if defined(LIBC_TYPES_LONG_DOUBLE_IS_X86_FLOAT80)
278 ASSERT_STREQ_LEN(written, buff, "0xc.dp-7");
279 #elif defined(LIBC_TYPES_LONG_DOUBLE_IS_FLOAT64)
280 ASSERT_STREQ_LEN(written, buff, "0x1.ap-4");
281 #elif defined(LIBC_TYPES_LONG_DOUBLE_IS_FLOAT128)
282 ASSERT_STREQ_LEN(written, buff, "0x1.ap-4");
283 #endif
285 written = func(buff, 50, "%a", 1.0e1000L);
286 #if defined(LIBC_TYPES_LONG_DOUBLE_IS_X86_FLOAT80)
287 ASSERT_STREQ_LEN(written, buff, "0xf.38db1f9dd3dac05p+3318");
288 #elif defined(LIBC_TYPES_LONG_DOUBLE_IS_FLOAT64)
289 ASSERT_STREQ_LEN(written, buff, "inf");
290 #elif defined(LIBC_TYPES_LONG_DOUBLE_IS_FLOAT128)
291 ASSERT_STREQ_LEN(written, buff, "0x1.e71b63f3ba7b580af1a52d2a7379p+3321");
292 #endif
294 written = func(buff, 50, "%a", 1.0e-1000L);
295 #if defined(LIBC_TYPES_LONG_DOUBLE_IS_X86_FLOAT80)
296 ASSERT_STREQ_LEN(written, buff, "0x8.68a9188a89e1467p-3325");
297 #elif defined(LIBC_TYPES_LONG_DOUBLE_IS_FLOAT64)
298 ASSERT_STREQ_LEN(written, buff, "0x0p+0");
299 #elif defined(LIBC_TYPES_LONG_DOUBLE_IS_FLOAT128)
300 ASSERT_STREQ_LEN(written, buff, "0x1.0d152311513c28ce202627c06ec2p-3322");
301 #endif
303 written = func(buff, 50, "%.1a", 0xf.fffffffffffffffp16380L);
304 #if defined(LIBC_TYPES_LONG_DOUBLE_IS_X86_FLOAT80)
305 ASSERT_STREQ_LEN(written, buff, "0x1.0p+16384");
306 #elif defined(LIBC_TYPES_LONG_DOUBLE_IS_FLOAT64)
307 ASSERT_STREQ_LEN(written, buff, "inf");
308 #elif defined(LIBC_TYPES_LONG_DOUBLE_IS_FLOAT128)
309 ASSERT_STREQ_LEN(written, buff, "0x2.0p+16383");
310 #endif
313 void floatDecimalExpSinglePrec(FunctionT func) {
314 char buff[25];
315 int written;
317 written = func(buff, 20, "%.9e", 1234567890.0);
318 ASSERT_STREQ_LEN(written, buff, "1.234567936e+09");
320 written = func(buff, 20, "%.9E", 1234567890.0);
321 ASSERT_STREQ_LEN(written, buff, "1.234567936E+09");
324 void floatDecimalExpDoublePrec(FunctionT func) {
325 char buff[101];
326 int written;
328 written = func(buff, 100, "%e", 1.0);
329 ASSERT_STREQ_LEN(written, buff, "1.000000e+00");
331 written = func(buff, 100, "%E", -1.0);
332 ASSERT_STREQ_LEN(written, buff, "-1.000000E+00");
334 written = func(buff, 100, "%e", -1.234567);
335 ASSERT_STREQ_LEN(written, buff, "-1.234567e+00");
337 written = func(buff, 100, "%e", 0.0);
338 ASSERT_STREQ_LEN(written, buff, "0.000000e+00");
340 written = func(buff, 100, "%e", 1.5);
341 ASSERT_STREQ_LEN(written, buff, "1.500000e+00");
343 written = func(buff, 100, "%e", 1e300);
344 ASSERT_STREQ_LEN(written, buff, "1.000000e+300");
346 written = func(buff, 100, "%e", 1234567890123456789.0);
347 ASSERT_STREQ_LEN(written, buff, "1.234568e+18");
349 // Precision Tests
350 written = func(buff, 100, "%.1e", 1.0);
351 ASSERT_STREQ_LEN(written, buff, "1.0e+00");
353 written = func(buff, 100, "%.1e", 1.99);
354 ASSERT_STREQ_LEN(written, buff, "2.0e+00");
356 written = func(buff, 100, "%.1e", 9.99);
357 ASSERT_STREQ_LEN(written, buff, "1.0e+01");
360 void floatDecimalExpLongDoublePrec(FunctionT func) {
361 // Mark as maybe_unused to silence unused variable
362 // warning when long double is not 80-bit
363 [[maybe_unused]] char buff[100];
364 [[maybe_unused]] int written;
366 #if defined(LIBC_TYPES_LONG_DOUBLE_IS_X86_FLOAT80)
367 written = func(buff, 90, "%.9e", 1000000000500000000.1L);
368 ASSERT_STREQ_LEN(written, buff, "1.000000001e+18");
370 written = func(buff, 90, "%.9e", 1000000000500000000.0L);
371 ASSERT_STREQ_LEN(written, buff, "1.000000000e+18");
373 written = func(buff, 90, "%e", 0xf.fffffffffffffffp+16380L);
374 ASSERT_STREQ_LEN(written, buff, "1.189731e+4932");
375 #endif // LIBC_TYPES_LONG_DOUBLE_IS_X86_FLOAT80
378 void floatDecimalAutoSinglePrec(FunctionT func) {
379 char buff[25];
380 int written;
382 written = func(buff, 20, "%.9g", 1234567890.0);
383 ASSERT_STREQ_LEN(written, buff, "1.23456794e+09");
385 written = func(buff, 20, "%.9G", 1234567890.0);
386 ASSERT_STREQ_LEN(written, buff, "1.23456794E+09");
389 void floatDecimalAutoDoublePrec(FunctionT func) {
390 char buff[120];
391 int written;
393 written = func(buff, 100, "%g", 1234567890123456789.0);
394 ASSERT_STREQ_LEN(written, buff, "1.23457e+18");
396 written = func(buff, 100, "%g", 9999990000000.00);
397 ASSERT_STREQ_LEN(written, buff, "9.99999e+12");
399 written = func(buff, 100, "%g", 9999999000000.00);
400 ASSERT_STREQ_LEN(written, buff, "1e+13");
402 written = func(buff, 100, "%g", 0xa.aaaaaaaaaaaaaabp-7);
403 ASSERT_STREQ_LEN(written, buff, "0.0833333");
405 written = func(buff, 100, "%g", 0.00001);
406 ASSERT_STREQ_LEN(written, buff, "1e-05");
408 // Precision Tests
409 written = func(buff, 100, "%.0g", 0.0);
410 ASSERT_STREQ_LEN(written, buff, "0");
412 written = func(buff, 100, "%.2g", 0.1);
413 ASSERT_STREQ_LEN(written, buff, "0.1");
415 written = func(buff, 100, "%.2g", 1.09);
416 ASSERT_STREQ_LEN(written, buff, "1.1");
418 written = func(buff, 100, "%.15g", 22.25);
419 ASSERT_STREQ_LEN(written, buff, "22.25");
421 written = func(buff, 100, "%.20g", 1.234e-10);
422 ASSERT_STREQ_LEN(written, buff, "1.2340000000000000814e-10");
425 void floatDecimalAutoLongDoublePrec(FunctionT func) {
426 // Mark as maybe_unused to silence unused variable
427 // warning when long double is not 80-bit
428 [[maybe_unused]] char buff[100];
429 [[maybe_unused]] int written;
431 #if defined(LIBC_TYPES_LONG_DOUBLE_IS_X86_FLOAT80)
432 written = func(buff, 99, "%g", 0xf.fffffffffffffffp+16380L);
433 ASSERT_STREQ_LEN(written, buff, "1.18973e+4932");
435 written = func(buff, 99, "%g", 0xa.aaaaaaaaaaaaaabp-7L);
436 ASSERT_STREQ_LEN(written, buff, "0.0833333");
438 written = func(buff, 99, "%g", 9.99999999999e-100L);
439 ASSERT_STREQ_LEN(written, buff, "1e-99");
440 #endif // LIBC_TYPES_LONG_DOUBLE_IS_X86_FLOAT80
443 void doublePrecInfNan(FunctionT func) {
444 char buff[15];
445 int written;
447 double inf = LIBC_NAMESPACE::fputil::FPBits<double>::inf().get_val();
448 double nan = LIBC_NAMESPACE::fputil::FPBits<double>::quiet_nan().get_val();
450 written = func(buff, 10, "%f", inf);
451 ASSERT_STREQ_LEN(written, buff, "inf");
453 written = func(buff, 10, "%A", -inf);
454 ASSERT_STREQ_LEN(written, buff, "-INF");
456 written = func(buff, 10, "%f", nan);
457 ASSERT_STREQ_LEN(written, buff, "nan");
459 written = func(buff, 10, "%A", -nan);
460 ASSERT_STREQ_LEN(written, buff, "-NAN");
463 void longDoublePrecInfNan(FunctionT func) {
464 char buff[15];
465 int written;
467 long double ld_inf =
468 LIBC_NAMESPACE::fputil::FPBits<long double>::inf().get_val();
469 long double ld_nan =
470 LIBC_NAMESPACE::fputil::FPBits<long double>::quiet_nan().get_val();
472 written = func(buff, 10, "%f", ld_inf);
473 ASSERT_STREQ_LEN(written, buff, "inf");
475 written = func(buff, 10, "%A", -ld_inf);
476 ASSERT_STREQ_LEN(written, buff, "-INF");
478 written = func(buff, 10, "%f", ld_nan);
479 ASSERT_STREQ_LEN(written, buff, "nan");
481 written = func(buff, 10, "%A", -ld_nan);
482 ASSERT_STREQ_LEN(written, buff, "-NAN");
486 #define STRFROM_TEST(InputType, name, func) \
487 using LlvmLibc##name##Test = StrfromTest<InputType>; \
488 TEST_F(LlvmLibc##name##Test, FloatDecimalFormat) { \
489 floatDecimalFormat(func); \
491 TEST_F(LlvmLibc##name##Test, FloatHexExpFormat) { floatHexExpFormat(func); } \
492 TEST_F(LlvmLibc##name##Test, FloatDecimalAutoFormat) { \
493 floatDecimalAutoFormat(func); \
495 TEST_F(LlvmLibc##name##Test, FloatDecimalExpFormat) { \
496 floatDecimalExpFormat(func); \
498 TEST_F(LlvmLibc##name##Test, ImproperFormatString) { \
499 improperFormatString(func); \
501 TEST_F(LlvmLibc##name##Test, InsufficientBufferSize) { \
502 insufficentBufsize(func); \
504 TEST_F(LlvmLibc##name##Test, InfAndNanValues) { infNanValues(func); }