Module Name: src Committed By: martin Date: Thu Aug 22 19:53:56 UTC 2024
Modified Files: src/tests/lib/libc/stdio [netbsd-9]: t_printf.c Log Message: Pull up following revision(s) (requested by riastradh in ticket #1866): tests/lib/libc/stdio/t_printf.c: revision 1.17 tests/lib/libc/stdio/t_printf.c: revision 1.18 tests/lib/libc/stdio/t_printf.c: revision 1.11 tests/lib/libc/stdio/t_printf.c: revision 1.12 tests/lib/libc/stdio/t_printf.c: revision 1.13 tests/lib/libc/stdio/t_printf.c: revision 1.14 tests/lib/libc/stdio/t_printf.c: revision 1.15 tests/lib/libc/stdio/t_printf.c: revision 1.16 (all via patch) tests/lib/libc/stdio/t_printf: Add a couple simple %La tests. PR lib/56937: printf(3) long double %a formatting is broken tests/lib/libc/stdio/t_printf: Fix %La test. 0xa.99ap+0 is closer to (long double)10.6 in x86 ld80 and in binary128 (and possibly more formats, haven't verified). tests/lib/libc/stdio/t_printf: Fix %a test the same way. tests/lib/libc/stdio/t_printf: Add another %La test. This one was adapted from the screw case shown in https://mail-index.netbsd.org/tech-userlevel/2020/04/11/msg012329.html which wasn't broken in our libc, but which nevertheless prompted us to commit a wrong and apparently untested patch that has rendered printf %La broken for the last four years, which is a little embarrassing. (The part of that patch that led to a buffer overrun has been worked around, so now the output is just incorrect.) PR lib/56937: printf(3) long double %a formatting is broken tests/lib/libc/stdio/t_printf: Fix another rounding error. Noted by kre. This doesn't break a passing test or fix a failed test, at least on x86 -- our printf produces `0x1.533p+3' for the double case and `0xa.99ap+0' for the long double case. But of the hexadecimal number literals that that start with 0x5 having three hexadigits to the right of the fractional point, 0x5.4cdp+1 closest to the IEEE 754 binary64, VAX D, x86 extended precision, and IEEE 754 binary128 floating-point numbers closest to 10.6. The reason is that the number 10.6 (or the nearest floating-point number in any format with enough precision) is: 101.0100 1100 1100|1100... * 2^1 = 0x5.4cc|c...p+1 If we round at the vertical bar to the _nearest_ output with three hexadigits of precision, the result is: 101.0100 1100 1101 * 2^1 = 0x5.4cdp+1 tests/lib/libc/stdio/t_printf: Fix typo in ld128 case. printf %La does not write the `L' suffix. tests/lib/libc/stdio/t_printf: Fix sign error in ld128 case. Also link back to where the test case came from. To generate a diff of this commit: cvs rdiff -u -r1.8.34.1 -r1.8.34.2 src/tests/lib/libc/stdio/t_printf.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/tests/lib/libc/stdio/t_printf.c diff -u src/tests/lib/libc/stdio/t_printf.c:1.8.34.1 src/tests/lib/libc/stdio/t_printf.c:1.8.34.2 --- src/tests/lib/libc/stdio/t_printf.c:1.8.34.1 Thu Aug 22 19:40:50 2024 +++ src/tests/lib/libc/stdio/t_printf.c Thu Aug 22 19:53:56 2024 @@ -1,4 +1,4 @@ -/* $NetBSD: t_printf.c,v 1.8.34.1 2024/08/22 19:40:50 martin Exp $ */ +/* $NetBSD: t_printf.c,v 1.8.34.2 2024/08/22 19:53:56 martin Exp $ */ /*- * Copyright (c) 2010 The NetBSD Foundation, Inc. @@ -28,14 +28,16 @@ #include <sys/types.h> #include <sys/resource.h> + #include <atf-c.h> +#include <errno.h> +#include <float.h> #include <math.h> -#include <stdio.h> #include <stdint.h> +#include <stdio.h> +#include <stdlib.h> #include <string.h> #include <time.h> -#include <stdlib.h> -#include <errno.h> ATF_TC(snprintf_c99); ATF_TC_HEAD(snprintf_c99, tc) @@ -191,7 +193,68 @@ ATF_TC_BODY(snprintf_double_a, tc) char buf[1000]; snprintf(buf, sizeof buf, "%.3a", (double)10.6); - ATF_REQUIRE_STREQ("0x1.533p+3", buf); + ATF_CHECK_MSG((strcmp(buf, "0x1.533p+3") == 0 || + strcmp(buf, "0x2.a66p+2") == 0 || + strcmp(buf, "0x5.4cdp+1") == 0 || + strcmp(buf, "0xa.99ap+0") == 0), + "buf=%s", buf); + + snprintf(buf, sizeof buf, "%a", (double)0.125); + ATF_CHECK_MSG((strcmp(buf, "0x1p-3") == 0 || + strcmp(buf, "0x2p-4") == 0 || + strcmp(buf, "0x4p-5") == 0 || + strcmp(buf, "0x8p-6") == 0), + "buf=%s", buf); +} + +ATF_TC(snprintf_long_double_a); +ATF_TC_HEAD(snprintf_long_double_a, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test printf La format"); +} + +ATF_TC_BODY(snprintf_long_double_a, tc) +{ + char buf[1000]; + + snprintf(buf, sizeof buf, "%.3La", 10.6L); + ATF_CHECK_MSG((strcmp(buf, "0x1.533p+3") == 0 || + strcmp(buf, "0x2.a66p+2") == 0 || + strcmp(buf, "0x5.4cdp+1") == 0 || + strcmp(buf, "0xa.99ap+0") == 0), + "buf=%s", buf); + + snprintf(buf, sizeof buf, "%La", 0.125L); + ATF_CHECK_MSG((strcmp(buf, "0x1p-3") == 0 || + strcmp(buf, "0x2p-4") == 0 || + strcmp(buf, "0x4p-5") == 0 || + strcmp(buf, "0x8p-6") == 0), + "buf=%s", buf); + + /* + * Test case adapted from: + * + * https://mail-index.netbsd.org/tech-userlevel/2020/04/11/msg012329.html + */ +#if LDBL_MAX_EXP >= 16384 && LDBL_MANT_DIG >= 64 + snprintf(buf, sizeof buf, "%La", -0xc.ecececececececep+3788L); + ATF_CHECK_MSG((strcmp(buf, "-0x1.9d9d9d9d9d9d9d9cp+3791") == 0 || + strcmp(buf, "-0x3.3b3b3b3b3b3b3b38p+3790") == 0 || + strcmp(buf, "-0x6.7676767676767674p+3789") == 0 || + strcmp(buf, "-0xc.ecececececececep+3788") == 0), + "buf=%s", buf); +#endif + +#if LDBL_MAX_EXP >= 16384 && LDBL_MANT_DIG >= 113 + snprintf(buf, sizeof buf, "%La", + -0x1.cecececececececececececececep+3791L); + ATF_CHECK_MSG((strcmp(buf, + "-0x1.cecececececececececececececep+3791") == 0 || + strcmp(buf, "-0x3.3333333333333338p+3790") == 0 || + strcmp(buf, "-0x6.767676767676767p+3789") == 0 || + strcmp(buf, "-0xc.ecececececececep+3788") == 0), + "buf=%s", buf); +#endif } /* is "long double" and "double" different? */ @@ -235,6 +298,7 @@ ATF_TP_ADD_TCS(tp) ATF_TP_ADD_TC(tp, snprintf_float); ATF_TP_ADD_TC(tp, sprintf_zeropad); ATF_TP_ADD_TC(tp, snprintf_double_a); + ATF_TP_ADD_TC(tp, snprintf_long_double_a); #ifndef WIDE_DOUBLE ATF_TP_ADD_TC(tp, pr57250_fix); #endif