Skip to content

Commit 95da57e

Browse files
committed
test: Add some floating point conversion corner cases
glibc uses the special value 3752432815e-39 to test strtod, strtof and sscanf. In hex, it's just a bit more than 0x1.306efbp-98 while 3752432815e-39 is just a bit less. Doing a conversion to float should yield 0x1.306efcp-98, but slighty incautious code might generate 0x1.306efap-98 instead. Signed-off-by: Keith Packard <[email protected]>
1 parent a93d02d commit 95da57e

File tree

4 files changed

+24
-4
lines changed

4 files changed

+24
-4
lines changed

test/libc-testsuite/sscanf.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535

3636
#define TEST_F(x) ( \
3737
TEST(i, sscanf(# x, "%lf", &d), 1, "got %d fields, expected %d"), \
38-
TEST(t, d, (double)x, "%g != %g") )
38+
TEST(t, d, (double)x, "%a != %a") )
3939

4040
#pragma GCC diagnostic ignored "-Wpragmas"
4141
#pragma GCC diagnostic ignored "-Wunknown-warning-option"
@@ -137,6 +137,7 @@ static int test_sscanf(void)
137137
TEST_F(0.2);
138138
TEST_F(0.1e-10);
139139
TEST_F(0x1234p56);
140+
TEST_F(3752432815e-39);
140141

141142
#ifndef __PICOLIBC__
142143
/* both tinystdio and legacy stdio fail this test */

test/printf_scanf.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -514,8 +514,11 @@ main(void)
514514
sscanf(buf, scanf_format, &r);
515515
e = fabs(v-r) / v;
516516
if (e > (float_type) ERROR_MAX) {
517-
printf("\tf %3d: wanted %.7e got %.7e (error %.7e, buf %s)\n", x,
518-
printf_float(v), printf_float(r), printf_float(e), buf);
517+
printf("\tf %3d: wanted %.7e %a got %.7e %a (error %.7e %a, buf %s)\n", x,
518+
printf_float(v), printf_float(v),
519+
printf_float(r), printf_float(r),
520+
printf_float(e), printf_float(e),
521+
buf);
519522
errors++;
520523
fflush(stdout);
521524
}

test/test-strtod.c

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,12 @@ static const struct {
5757
} tests[] = {
5858
{ "1e2@", 100.0, 100.0f, 100.0l, "@" },
5959
#ifdef FULL_TESTS
60+
#if !defined(TINY_STDIO) || defined(_IO_FLOAT_EXACT)
61+
{ "3752432815e-39%", 0x1.306efbp-98, 0x1.306efcp-98f, 3752432815e-39l, "%" },
62+
{ "3.752432815e-30%", 0x1.306efbp-98, 0x1.306efcp-98f, 3752432815e-39l, "%" },
63+
{ "3752432814e-39^", 3752432814e-39, 0x1.306efap-98f, 3752432814e-39l, "^" },
64+
{ "3.752432814e-30^", 3752432814e-39, 0x1.306efap-98f, 3752432814e-39l, "^" },
65+
#endif
6066
{ "0x10.000@", 16.0, 16.0f, 16.0l, "@" },
6167
{ "0x10.000p@", 16.0, 16.0f, 16.0l, "p@" },
6268
{ "0x10.000p+@", 16.0, 16.0f, 16.0l, "p+@" },
@@ -158,9 +164,18 @@ int main(void)
158164
tests[i].string, end, tests[i].end_test);
159165
ret = 1;
160166
}
167+
if (tests[i].end_test[0] == '%') {
168+
if ((float) d != f) {
169+
printf("strtof(\"%s\") got %a strtod got %a\n", tests[i].string, (double) f, d);
170+
ret = 1;
171+
}
172+
}
161173
#ifdef _TEST_LONG_DOUBLE
162174
#ifdef FULL_TESTS
163-
if (sizeof(long double) > sizeof(double)) {
175+
if (sizeof(long double) > sizeof(double)
176+
&& tests[i].end_test[0] != '%'
177+
&& tests[i].end_test[0] != '^')
178+
{
164179
ld = strtold(tests[i].string, &end);
165180
if (ld != tests[i].ldvalue) {
166181
printf("strtold(\"%s\"): got %.17Le %La want %.17Le %La\n", tests[i].string,

test/testcases.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -702,6 +702,7 @@
702702
result |= test(__LINE__, "0x0p-126", "%.a", 0x1p-127);
703703
#endif
704704
#else
705+
result |= test(__LINE__, "0x1.306efbp-98", "%a", 3752432815e-39);
705706
#ifdef NORMALIZED_A
706707
/* newlib legacy stdio normalizes %a format */
707708
result |= test(__LINE__, "0x1p-1074", "%a", 0x1p-1074);

0 commit comments

Comments
 (0)