1 //===-- A template class for testing strfrom functions ----------*- C++ -*-===//
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
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
);
28 void floatDecimalFormat(FunctionT func
) {
30 floatDecimalSinglePrec(func
);
31 else if (is_double_prec
)
32 floatDecimalDoublePrec(func
);
34 floatDecimalLongDoublePrec(func
);
37 void floatHexExpFormat(FunctionT func
) {
39 floatHexExpSinglePrec(func
);
40 else if (is_double_prec
)
41 floatHexExpDoublePrec(func
);
43 floatHexExpLongDoublePrec(func
);
46 void floatDecimalExpFormat(FunctionT func
) {
48 floatDecimalExpSinglePrec(func
);
49 else if (is_double_prec
)
50 floatDecimalExpDoublePrec(func
);
52 floatDecimalExpLongDoublePrec(func
);
55 void floatDecimalAutoFormat(FunctionT func
) {
57 floatDecimalAutoSinglePrec(func
);
58 else if (is_double_prec
)
59 floatDecimalAutoDoublePrec(func
);
61 floatDecimalAutoLongDoublePrec(func
);
64 void improperFormatString(FunctionT func
) {
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.");
74 "%A simple string with one conversion, should overwrite.", 1.0);
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");
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",
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
) {
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
) {
121 doublePrecInfNan(func
);
122 else if (!is_single_prec
)
123 longDoublePrecInfNan(func
);
126 void floatDecimalSinglePrec(FunctionT func
) {
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
) {
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"
166 "798890819578637137508044786404370444383288387817694252323"
168 "218478670698284838720092657580373783023379478809005936895"
170 "111903896764088007465274278014249457925878882005684283811"
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");
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
) {
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
) {
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
) {
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
) {
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");
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");
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");
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");
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");
313 void floatDecimalExpSinglePrec(FunctionT func
) {
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
) {
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");
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
) {
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
) {
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");
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
) {
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
) {
468 LIBC_NAMESPACE::fputil::FPBits
<long double>::inf().get_val();
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); }