1 /* tsprintf.c -- test file for mpfr_sprintf, mpfr_vsprintf, mpfr_snprintf,
2 and mpfr_vsnprintf
3
4 Copyright 2007-2023 Free Software Foundation, Inc.
5 Contributed by the AriC and Caramba projects, INRIA.
6
7 This file is part of the GNU MPFR Library.
8
9 The GNU MPFR Library is free software; you can redistribute it and/or modify
10 it under the terms of the GNU Lesser General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or (at your
12 option) any later version.
13
14 The GNU MPFR Library is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
17 License for more details.
18
19 You should have received a copy of the GNU Lesser General Public License
20 along with the GNU MPFR Library; see the file COPYING.LESSER. If not, see
21 https://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
22 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
23
24 /* Note: If you use a C99-compatible implementation and GMP (or MPIR)
25 * has been compiled without HAVE_VSNPRINTF defined, then this test
26 * may fail with an error like
27 * repl-vsnprintf.c:389: GNU MP assertion failed: len < total_width
28 *
29 * The reason is that __gmp_replacement_vsnprintf does not support %a/%A,
30 * even though the C library supports it.
31 *
32 * References:
33 * https://sympa.inria.fr/sympa/arc/mpfr/2022-10/msg00001.html
34 * https://sympa.inria.fr/sympa/arc/mpfr/2022-10/msg00027.html
35 * https://gmplib.org/list-archives/gmp-bugs/2022-October/005200.html
36 */
37
38 /* Needed due to the tests on HAVE_STDARG and MPFR_USE_MINI_GMP */
39 #ifdef HAVE_CONFIG_H
40 # include "config.h"
41 #endif
42
43 #if defined(HAVE_STDARG) && !defined(MPFR_USE_MINI_GMP)
44 #include <stdarg.h>
45
46 #include <float.h>
47 #include <errno.h>
48
49 #ifdef HAVE_LOCALE_H
50 #include <locale.h>
51 #endif
52
53 #define MPFR_NEED_INTMAX_H
54 #include "mpfr-test.h"
55
56 const int prec_max_printf = 5000; /* limit for random precision in
57 random_double() */
58 #define BUF_SIZE 65536
59
60 int randsize;
61
62 /* 1. compare expected string with the string BUFFER returned by
63 mpfr_sprintf(buffer, fmt, x)
64 2. then test mpfr_snprintf (buffer, p, fmt, x) with a random p. */
65 static void
check_sprintf(const char * expected,const char * fmt,mpfr_srcptr x)66 check_sprintf (const char *expected, const char *fmt, mpfr_srcptr x)
67 {
68 int n0, n1;
69 char buffer[BUF_SIZE];
70
71 /* test mpfr_sprintf */
72 n0 = mpfr_sprintf (buffer, fmt, x);
73 if (strcmp (buffer, expected) != 0)
74 {
75 printf ("Error in mpfr_sprintf (s, \"%s\", x);\n", fmt);
76 printf ("expected: \"%s\"\ngot: \"%s\"\n", expected, buffer);
77
78 exit (1);
79 }
80
81 /* test mpfr_snprintf */
82 randsize = (int) (randlimb () % (n0 + 3)) - 3; /* between -3 and n0 - 1 */
83 if (randsize < 0)
84 {
85 n1 = mpfr_snprintf (NULL, 0, fmt, x);
86 }
87 else
88 {
89 buffer[randsize] = 17;
90 n1 = mpfr_snprintf (buffer, randsize, fmt, x);
91 if (buffer[randsize] != 17)
92 {
93 printf ("Buffer overflow in mpfr_snprintf for randsize = %d!\n",
94 randsize);
95 exit (1);
96 }
97 }
98 if (n0 != n1)
99 {
100 printf ("Error in mpfr_snprintf (s, %d, \"%s\", x) return value\n",
101 randsize, fmt);
102 printf ("expected: %d\ngot: %d\nx='", n0, n1);
103 mpfr_printf (fmt, x);
104 printf ("'\n");
105 exit (1);
106 }
107 if ((randsize > 1 && strncmp (expected, buffer, randsize - 1) != 0)
108 || (randsize == 1 && buffer[0] != '\0'))
109 {
110 char part_expected[BUF_SIZE];
111 strncpy (part_expected, expected, randsize);
112 part_expected[randsize - 1] = '\0';
113 printf ("Error in mpfr_vsnprintf (s, %d, \"%s\", ...);\n",
114 randsize, fmt);
115 printf ("expected: \"%s\"\ngot: \"%s\"\n", part_expected, buffer);
116 exit (1);
117 }
118 }
119
120 /* 1. compare expected string with the string BUFFER returned by
121 mpfr_vsprintf(buffer, fmt, ...)
122 2. then, test mpfr_vsnprintf. */
123 static int
check_vsprintf(const char * expected,const char * fmt,...)124 check_vsprintf (const char *expected, const char *fmt, ...)
125 {
126 int n0, n1;
127 char buffer[BUF_SIZE];
128 va_list ap0, ap1;
129
130 va_start (ap0, fmt);
131 n0 = mpfr_vsprintf (buffer, fmt, ap0);
132 va_end (ap0);
133
134 if (strcmp (buffer, expected) != 0)
135 {
136 printf ("Error in mpfr_vsprintf (s, \"%s\", ...);\n", fmt);
137 printf ("expected: \"%s\"\ngot: \"%s\"\n", expected, buffer);
138 exit (1);
139 }
140
141 va_start (ap1, fmt);
142
143 /* test mpfr_snprintf */
144 randsize = (int) (randlimb () % (n0 + 3)) - 3; /* between -3 and n0 - 1 */
145 if (randsize < 0)
146 {
147 n1 = mpfr_vsnprintf (NULL, 0, fmt, ap1);
148 }
149 else
150 {
151 buffer[randsize] = 17;
152 n1 = mpfr_vsnprintf (buffer, randsize, fmt, ap1);
153 if (buffer[randsize] != 17)
154 {
155 printf ("Buffer overflow in mpfr_vsnprintf for randsize = %d!\n",
156 randsize);
157 exit (1);
158 }
159 }
160
161 va_end (ap1);
162
163 if (n0 != n1)
164 {
165 printf ("Error in mpfr_vsnprintf (s, %d, \"%s\", ...) return value\n",
166 randsize, fmt);
167 printf ("expected: %d\ngot: %d\n", n0, n1);
168 exit (1);
169 }
170 if ((randsize > 1 && strncmp (expected, buffer, randsize - 1) != 0)
171 || (randsize == 1 && buffer[0] != '\0'))
172 {
173 char part_expected[BUF_SIZE];
174
175 strncpy (part_expected, expected, randsize);
176 part_expected[randsize - 1] = '\0';
177 printf ("Error in mpfr_vsnprintf (s, %d, \"%s\", ...);\n",
178 randsize, fmt);
179 printf ("expected: \"%s\"\ngot: \"%s\"\n", part_expected, buffer);
180 exit (1);
181 }
182
183 return n0;
184 }
185
186 static void
native_types(void)187 native_types (void)
188 {
189 int c = 'a';
190 int i = -1;
191 unsigned int ui = 1;
192 double d[] = { -1.25, 7.62939453125e-6 /* 2^(-17) */ };
193 char s[] = "test";
194 char buf[255];
195 int k;
196
197 sprintf (buf, "%c", c);
198 check_vsprintf (buf, "%c", c);
199
200 sprintf (buf, "%d", i);
201 check_vsprintf (buf, "%d", i);
202
203 check_vsprintf ("0", "%d", 0);
204 check_vsprintf ("", "%.d", 0);
205 check_vsprintf ("", "%.0d", 0);
206
207 sprintf (buf, "%i", i);
208 check_vsprintf (buf, "%i", i);
209
210 check_vsprintf ("0", "%i", 0);
211 check_vsprintf ("", "%.i", 0);
212 check_vsprintf ("", "%.0i", 0);
213
214 for (k = 0; k < numberof(d); k++)
215 {
216 sprintf (buf, "%e", d[k]);
217 check_vsprintf (buf, "%e", d[k]);
218
219 sprintf (buf, "%E", d[k]);
220 check_vsprintf (buf, "%E", d[k]);
221
222 sprintf (buf, "%f", d[k]);
223 check_vsprintf (buf, "%f", d[k]);
224
225 sprintf (buf, "%g", d[k]);
226 check_vsprintf (buf, "%g", d[k]);
227
228 sprintf (buf, "%G", d[k]);
229 check_vsprintf (buf, "%G", d[k]);
230
231 #if __MPFR_STDC (199901L)
232
233 gmp_sprintf (buf, "%a", d[k]);
234 check_vsprintf (buf, "%a", d[k]);
235
236 gmp_sprintf (buf, "%A", d[k]);
237 check_vsprintf (buf, "%A", d[k]);
238
239 gmp_sprintf (buf, "%la", d[k]);
240 check_vsprintf (buf, "%la", d[k]);
241
242 gmp_sprintf (buf, "%lA", d[k]);
243 check_vsprintf (buf, "%lA", d[k]);
244
245 sprintf (buf, "%le", d[k]);
246 check_vsprintf (buf, "%le", d[k]);
247
248 sprintf (buf, "%lE", d[k]);
249 check_vsprintf (buf, "%lE", d[k]);
250
251 sprintf (buf, "%lf", d[k]);
252 check_vsprintf (buf, "%lf", d[k]);
253
254 sprintf (buf, "%lg", d[k]);
255 check_vsprintf (buf, "%lg", d[k]);
256
257 sprintf (buf, "%lG", d[k]);
258 check_vsprintf (buf, "%lG", d[k]);
259
260 #endif
261 }
262
263 sprintf (buf, "%o", i);
264 check_vsprintf (buf, "%o", i);
265
266 sprintf (buf, "%s", s);
267 check_vsprintf (buf, "%s", s);
268
269 sprintf (buf, "--%s++", "");
270 check_vsprintf (buf, "--%s++", "");
271
272 sprintf (buf, "%u", ui);
273 check_vsprintf (buf, "%u", ui);
274
275 sprintf (buf, "%x", ui);
276 check_vsprintf (buf, "%x", ui);
277 }
278
279 static void
special(void)280 special (void)
281 {
282 mpfr_t x;
283 const char *ns[] = { "nan", "NAN", "inf", "INF" };
284 const char *ps[] = { "", " ", "+", "+ ", " +" };
285 const char *rs[] = { "", "U", "D", "Y", "Z", "N" };
286 const char *fs[] = { "efgab", "EFGA" };
287 int ntests = 0, neg, psflag, r, f;
288 unsigned int i;
289
290 mpfr_init2 (x, 128); /* initialized to NaN */
291
292 for (i = 0; i < numberof (ns); i++)
293 {
294 if (i == 2)
295 MPFR_SET_INF (x);
296
297 for (neg = 0; neg < 2; neg++)
298 {
299 MPFR_SET_SIGN (x, neg ? MPFR_SIGN_NEG : MPFR_SIGN_POS);
300 for (psflag = 0; psflag < 3; psflag++)
301 for (r = 0; r < numberof (rs); r++)
302 for (f = 0; fs[i & 1][f] != '\0'; f++)
303 {
304 int fmtpsflags = psflag;
305 int zeroflag, width;
306 char ws[4], fmt[20], expected[20], sign, *p;
307 int sp;
308
309 /* In case of '+' flag, let's randomly test an additional
310 space flag, which should be ignored. */
311 if (psflag == 2)
312 fmtpsflags += randlimb () % 3;
313
314 /* '0' flag ignored for NaN and Inf; use it randomly. */
315 zeroflag = RAND_BOOL ();
316
317 width = randlimb () % 12;
318 if (width != 0)
319 sprintf (ws, "%d", width);
320 else
321 ws[0] = '\0';
322
323 /* The following is a common prefix to better identify
324 error messages produced in this function. */
325 strcpy (expected, "special ");
326
327 sprintf (fmt, "%s%%%s%s%sR%s%c", expected, ps[fmtpsflags],
328 zeroflag ? "0" : "", ws, rs[r], fs[i & 1][f]);
329 /* printf ("Format string: \"%s\"\n", fmt); */
330
331 p = expected + 8;
332 sign = neg ? '-' : ps[psflag][0];
333 for (sp = width - (sign != '\0') - 3; sp > 0; sp--)
334 *p++ = ' ';
335 if (sign != '\0')
336 *p++ = sign;
337 strcpy (p, ns[i]);
338
339 check_sprintf (expected, fmt, x);
340 ntests++;
341 }
342 }
343 }
344
345 /* 2 base values (NaN and Inf), 2 signs (positive and negative),
346 3 possible '+'/space flag cases, 6 cases for the rounding mode,
347 9 format specifiers (efgab / EFGA). */
348 MPFR_ASSERTN (ntests == 2 * 2 * 3 * 6 * 9);
349
350 mpfr_clear (x);
351 }
352
353 static void
decimal(void)354 decimal (void)
355 {
356 mpfr_prec_t p = 128;
357 mpfr_t x, y, z;
358
359 /* specifier 'P' for precision */
360 check_vsprintf ("128", "%Pu", p);
361 check_vsprintf ("00128", "%.5Pu", p);
362 check_vsprintf (" 128", "%5Pu", p);
363 check_vsprintf ("000128", "%06Pu", p);
364 check_vsprintf ("128 :", "%-7Pu:", p);
365 check_vsprintf ("000128:", "%-2.6Pd:", p);
366 check_vsprintf (" 000128:", "%8.6Pd:", p);
367 check_vsprintf ("000128 :", "%-8.6Pd:", p);
368 check_vsprintf ("+128:", "%+Pd:", p);
369 check_vsprintf (" 128:", "% Pd:", p);
370 check_vsprintf ("80:", "% Px:", p);
371 check_vsprintf ("0x80:", "% #Px:", p);
372 check_vsprintf ("0x80:", "%0#+ -Px:", p);
373 check_vsprintf ("0200:", "%0#+ -Po:", p);
374 check_vsprintf ("+0000128 :", "%0+ *.*Pd:", -9, 7, p);
375 check_vsprintf ("+12345 :", "%0+ -*.*Pd:", -9, -3, (mpfr_prec_t) 12345);
376 check_vsprintf ("0", "%Pu", (mpfr_prec_t) 0);
377 /* Do not add a test like "%05.1Pd" as MS Windows is buggy: when
378 a precision is given, the '0' flag must be ignored. */
379
380 /* specifier 'P' with precision field 0 */
381 check_vsprintf ("128", "%.Pu", p);
382 check_vsprintf ("128", "%.0Pd", p);
383 check_vsprintf ("", "%.Pu", (mpfr_prec_t) 0);
384 check_vsprintf ("", "%.0Pd", (mpfr_prec_t) 0);
385
386 mpfr_init (z);
387 mpfr_init2 (x, 128);
388
389 /* special numbers: tested in special() */
390
391 /* positive numbers */
392 mpfr_set_str (x, "18993474.61279296875", 10, MPFR_RNDN);
393 mpfr_init2 (y, 59);
394 mpfr_set (y, x, MPFR_RNDN);
395 mpfr_set_ui (z, 0, MPFR_RNDD);
396
397 /* simplest case right justified */
398 check_sprintf ("1.899347461279296875000000000000000000000e+07", "%30Re", x);
399 check_sprintf (" 1.899347461279296875e+07", "%30Re", y);
400 check_sprintf (" 2e+07", "%30.0Re", x);
401 check_sprintf (" 18993474.612793", "%30Rf", x);
402 check_sprintf (" 18993474.6127930", "%30.7Rf", x);
403 check_sprintf (" 1.89935e+07", "%30Rg", x);
404 check_sprintf (" 2e+07", "%30.0Rg", x);
405 check_sprintf (" 18993474.61279296875", "%30.19Rg", x);
406 check_sprintf (" 0.0000000000000000e+00", "%30Re", z);
407 check_sprintf (" 0.000000", "%30Rf", z);
408 check_sprintf (" 0", "%30Rg", z);
409 check_sprintf (" 0.00000", "%#30Rg", z);
410 check_sprintf (" 0e+00", "%30.0Re", z);
411 check_sprintf (" 0", "%30.0Rf", z);
412 check_sprintf (" 0.0000", "%30.4Rf", z);
413 check_sprintf (" 0", "%30.0Rg", z);
414 check_sprintf (" 0", "%30.4Rg", z);
415 /* sign or space, pad with leading zeros */
416 check_sprintf (" 1.899347461279296875000000000000000000000E+07", "% 030RE", x);
417 check_sprintf (" 000001.899347461279296875E+07", "% 030RE", y);
418 check_sprintf (" 0000000000000000001.89935E+07", "% 030RG", x);
419 check_sprintf (" 0000000000000000000000002E+07", "% 030.0RE", x);
420 check_sprintf (" 0000000000000000000000000E+00", "% 030.0RE", z);
421 check_sprintf (" 00000000000000000000000000000", "% 030.0RF", z);
422 /* sign + or -, left justified */
423 check_sprintf ("+1.899347461279296875000000000000000000000e+07", "%+-30Re", x);
424 check_sprintf ("+1.899347461279296875e+07 ", "%+-30Re", y);
425 check_sprintf ("+2e+07 ", "%+-30.0Re", x);
426 check_sprintf ("+0e+00 ", "%+-30.0Re", z);
427 check_sprintf ("+0 ", "%+-30.0Rf", z);
428 /* decimal point, left justified, precision and rounding parameter */
429 check_vsprintf ("1.9E+07 ", "%#-10.*R*E", 1, MPFR_RNDN, x);
430 check_vsprintf ("2.E+07 ", "%#*.*R*E", -10, 0, MPFR_RNDN, x);
431 check_vsprintf ("2.E+07 ", "%#-10.*R*G", 0, MPFR_RNDN, x);
432 check_vsprintf ("0.E+00 ", "%#-10.*R*E", 0, MPFR_RNDN, z);
433 check_vsprintf ("0. ", "%#-10.*R*F", 0, MPFR_RNDN, z);
434 check_vsprintf ("0. ", "%#-10.*R*G", 0, MPFR_RNDN, z);
435 /* sign or space */
436 check_sprintf (" 1.899e+07", "% .3RNe", x);
437 check_sprintf (" 2e+07", "% .0RNe", x);
438 /* sign + or -, decimal point, pad with leading zeros */
439 check_sprintf ("+0001.8E+07", "%0+#11.1RZE", x);
440 check_sprintf ("+00001.E+07", "%0+#11.0RZE", x);
441 check_sprintf ("+0000.0E+00", "%0+#11.1RZE", z);
442 check_sprintf ("+00000000.0", "%0+#11.1RZF", z);
443 /* pad with leading zero */
444 check_sprintf ("1.899347461279296875000000000000000000000e+07", "%030RDe", x);
445 check_sprintf ("0000001.899347461279296875e+07", "%030RDe", y);
446 check_sprintf ("00000000000000000000000001e+07", "%030.0RDe", x);
447 /* sign or space, decimal point, left justified */
448 check_sprintf (" 1.8E+07 ", "%- #11.1RDE", x);
449 check_sprintf (" 1.E+07 ", "%- #11.0RDE", x);
450 /* large requested precision */
451 check_sprintf ("18993474.61279296875", "%.2147483647Rg", x);
452
453 /* negative numbers */
454 mpfr_mul_si (x, x, -1, MPFR_RNDD);
455 mpfr_mul_si (z, z, -1, MPFR_RNDD);
456
457 /* sign + or - */
458 check_sprintf (" -1.8e+07", "%+10.1RUe", x);
459 check_sprintf (" -1e+07", "%+10.0RUe", x);
460 check_sprintf (" -0e+00", "%+10.0RUe", z);
461 check_sprintf (" -0", "%+10.0RUf", z);
462
463 /* neighborhood of 1 */
464 mpfr_set_str (x, "0.99993896484375", 10, MPFR_RNDN);
465 mpfr_set_prec (y, 43);
466 mpfr_set (y, x, MPFR_RNDN);
467 check_sprintf ("9.999389648437500000000000000000000000000E-01", "%-20RE", x);
468 check_sprintf ("9.9993896484375E-01 ", "%-20RE", y);
469 check_sprintf ("1E+00 ", "%-20.RE", x);
470 check_sprintf ("1E+00 ", "%-20.RE", y);
471 check_sprintf ("1E+00 ", "%-20.0RE", x);
472 check_sprintf ("1.0E+00 ", "%-20.1RE", x);
473 check_sprintf ("1.00E+00 ", "%-20.2RE", x);
474 check_sprintf ("9.999E-01 ", "%-20.3RE", x);
475 check_sprintf ("9.9994E-01 ", "%-20.4RE", x);
476 check_sprintf ("0.999939 ", "%-20RF", x);
477 check_sprintf ("1 ", "%-20.RF", x);
478 check_sprintf ("1 ", "%-20.0RF", x);
479 check_sprintf ("1.0 ", "%-20.1RF", x);
480 check_sprintf ("1.00 ", "%-20.2RF", x);
481 check_sprintf ("1.000 ", "%-20.3RF", x);
482 check_sprintf ("0.9999 ", "%-20.4RF", x);
483 check_sprintf ("0.999939 ", "%-#20RF", x);
484 check_sprintf ("1. ", "%-#20.RF", x);
485 check_sprintf ("1. ", "%-#20.0RF", x);
486 check_sprintf ("1.0 ", "%-#20.1RF", x);
487 check_sprintf ("1.00 ", "%-#20.2RF", x);
488 check_sprintf ("1.000 ", "%-#20.3RF", x);
489 check_sprintf ("0.9999 ", "%-#20.4RF", x);
490 check_sprintf ("0.999939 ", "%-20RG", x);
491 check_sprintf ("1 ", "%-20.RG", x);
492 check_sprintf ("1 ", "%-20.0RG", x);
493 check_sprintf ("1 ", "%-20.1RG", x);
494 check_sprintf ("1 ", "%-20.2RG", x);
495 check_sprintf ("1 ", "%-20.3RG", x);
496 check_sprintf ("0.9999 ", "%-20.4RG", x);
497 check_sprintf ("0.999939 ", "%-#20RG", x);
498 check_sprintf ("1. ", "%-#20.RG", x);
499 check_sprintf ("1. ", "%-#20.0RG", x);
500 check_sprintf ("1. ", "%-#20.1RG", x);
501 check_sprintf ("1.0 ", "%-#20.2RG", x);
502 check_sprintf ("1.00 ", "%-#20.3RG", x);
503 check_sprintf ("0.9999 ", "%-#20.4RG", x);
504
505 /* powers of 10 */
506 mpfr_set_str (x, "1e17", 10, MPFR_RNDN);
507 check_sprintf ("1.000000000000000000000000000000000000000e+17", "%Re", x);
508 check_sprintf ("1.000e+17", "%.3Re", x);
509 check_sprintf ("100000000000000000", "%.Rf", x);
510 check_sprintf ("100000000000000000", "%.0Rf", x);
511 check_sprintf ("100000000000000000.0", "%.1Rf", x);
512 check_sprintf ("100000000000000000.000000", "%'Rf", x);
513 check_sprintf ("100000000000000000.0", "%'.1Rf", x);
514
515 mpfr_ui_div (x, 1, x, MPFR_RNDN); /* x=1e-17 */
516 check_sprintf ("1.000000000000000000000000000000000000000e-17", "%Re", x);
517 check_sprintf ("0.000000", "%Rf", x);
518 check_sprintf ("1e-17", "%Rg", x);
519 check_sprintf ("0.0", "%.1RDf", x);
520 check_sprintf ("0.0", "%.1RZf", x);
521 check_sprintf ("0.1", "%.1RUf", x);
522 check_sprintf ("0.1", "%.1RYf", x);
523 check_sprintf ("0", "%.0RDf", x);
524 check_sprintf ("0", "%.0RZf", x);
525 check_sprintf ("1", "%.0RUf", x);
526 check_sprintf ("1", "%.0RYf", x);
527
528 /* powers of 10 with 'g' style */
529 mpfr_set_str (x, "10", 10, MPFR_RNDN);
530 check_sprintf ("10", "%Rg", x);
531 check_sprintf ("1e+01", "%.0Rg", x);
532 check_sprintf ("1e+01", "%.1Rg", x);
533 check_sprintf ("10", "%.2Rg", x);
534
535 mpfr_ui_div (x, 1, x, MPFR_RNDN);
536 check_sprintf ("0.1", "%Rg", x);
537 check_sprintf ("0.1", "%.0Rg", x);
538 check_sprintf ("0.1", "%.1Rg", x);
539
540 mpfr_set_str (x, "1000", 10, MPFR_RNDN);
541 check_sprintf ("1000", "%Rg", x);
542 check_sprintf ("1e+03", "%.0Rg", x);
543 check_sprintf ("1e+03", "%.3Rg", x);
544 check_sprintf ("1000", "%.4Rg", x);
545 check_sprintf ("1e+03", "%.3Rg", x);
546 check_sprintf ("1000", "%.4Rg", x);
547 check_sprintf (" 1e+03", "%9.3Rg", x);
548 check_sprintf (" 1000", "%9.4Rg", x);
549 check_sprintf ("00001e+03", "%09.3Rg", x);
550 check_sprintf ("000001000", "%09.4Rg", x);
551
552 mpfr_ui_div (x, 1, x, MPFR_RNDN);
553 check_sprintf ("0.001", "%Rg", x);
554 check_sprintf ("0.001", "%.0Rg", x);
555 check_sprintf ("0.001", "%.1Rg", x);
556
557 mpfr_set_str (x, "100000", 10, MPFR_RNDN);
558 check_sprintf ("100000", "%Rg", x);
559 check_sprintf ("1e+05", "%.0Rg", x);
560 check_sprintf ("1e+05", "%.5Rg", x);
561 check_sprintf ("100000", "%.6Rg", x);
562 check_sprintf (" 1e+05", "%17.5Rg", x);
563 check_sprintf (" 100000", "%17.6Rg", x);
564 check_sprintf ("0000000000001e+05", "%017.5Rg", x);
565 check_sprintf ("00000000000100000", "%017.6Rg", x);
566
567 mpfr_ui_div (x, 1, x, MPFR_RNDN);
568 check_sprintf ("1e-05", "%Rg", x);
569 check_sprintf ("1e-05", "%.0Rg", x);
570 check_sprintf ("1e-05", "%.1Rg", x);
571
572 /* check rounding mode */
573 mpfr_set_str (x, "0.0076", 10, MPFR_RNDN);
574 check_sprintf ("0.007", "%.3RDF", x);
575 check_sprintf ("0.007", "%.3RZF", x);
576 check_sprintf ("0.008", "%.3RF", x);
577 check_sprintf ("0.008", "%.3RUF", x);
578 check_sprintf ("0.008", "%.3RYF", x);
579 check_vsprintf ("0.008", "%.3R*F", MPFR_RNDA, x);
580
581 /* check limit between %f-style and %g-style */
582 mpfr_set_str (x, "0.0000999", 10, MPFR_RNDN);
583 check_sprintf ("0.0001", "%.0Rg", x);
584 check_sprintf ("9e-05", "%.0RDg", x);
585 check_sprintf ("0.0001", "%.1Rg", x);
586 check_sprintf ("0.0001", "%.2Rg", x);
587 check_sprintf ("9.99e-05", "%.3Rg", x);
588
589 /* trailing zeros */
590 mpfr_set_si_2exp (x, -1, -15, MPFR_RNDN); /* x=-2^-15 */
591 check_sprintf ("-3.0517578125e-05", "%.30Rg", x);
592 check_sprintf ("-3.051757812500000000000000000000e-05", "%.30Re", x);
593 check_sprintf ("-3.05175781250000000000000000000e-05", "%#.30Rg", x);
594 check_sprintf ("-0.000030517578125000000000000000", "%.30Rf", x);
595
596 /* bug 20081023 */
597 check_sprintf ("-3.0517578125e-05", "%.30Rg", x);
598 mpfr_set_str (x, "1.9999", 10, MPFR_RNDN);
599 check_sprintf ("1.999900 ", "%-#10.7RG", x);
600 check_sprintf ("1.9999 ", "%-10.7RG", x);
601 mpfr_set_ui (x, 1, MPFR_RNDN);
602 check_sprintf ("1.", "%#.1Rg", x);
603 check_sprintf ("1. ", "%-#5.1Rg", x);
604 check_sprintf (" 1.0", "%#5.2Rg", x);
605 check_sprintf ("1.00000000000000000000000000000", "%#.30Rg", x);
606 check_sprintf ("1", "%.30Rg", x);
607 mpfr_set_ui (x, 0, MPFR_RNDN);
608 check_sprintf ("0.", "%#.1Rg", x);
609 check_sprintf ("0. ", "%-#5.1Rg", x);
610 check_sprintf (" 0.0", "%#5.2Rg", x);
611 check_sprintf ("0.00000000000000000000000000000", "%#.30Rg", x);
612 check_sprintf ("0", "%.30Rg", x);
613
614 /* following tests with precision 53 bits */
615 mpfr_set_prec (x, 53);
616
617 /* Exponent zero has a plus sign */
618 mpfr_set_str (x, "-9.95645044213728791504536275169812142849e-01", 10,
619 MPFR_RNDN);
620 check_sprintf ("-1.0e+00", "%- #0.1Re", x);
621
622 /* Decimal point and no figure after it with '#' flag and 'G' style */
623 mpfr_set_str (x, "-9.90597761233942053494e-01", 10, MPFR_RNDN);
624 check_sprintf ("-1.", "%- #0.1RG", x);
625
626 /* precision zero */
627 mpfr_set_d (x, 9.5, MPFR_RNDN);
628 check_sprintf ("9", "%.0RDf", x);
629 check_sprintf ("10", "%.0RUf", x);
630
631 mpfr_set_d (x, 19.5, MPFR_RNDN);
632 check_sprintf ("19", "%.0RDf", x);
633 check_sprintf ("20", "%.0RUf", x);
634
635 mpfr_set_d (x, 99.5, MPFR_RNDN);
636 check_sprintf ("99", "%.0RDf", x);
637 check_sprintf ("100", "%.0RUf", x);
638
639 mpfr_set_d (x, -9.5, MPFR_RNDN);
640 check_sprintf ("-10", "%.0RDf", x);
641 check_sprintf ("-10", "%.0RYf", x);
642 check_sprintf ("-10", "%.0Rf", x);
643 check_sprintf ("-1e+01", "%.0Re", x);
644 check_sprintf ("-1e+01", "%.0Rg", x);
645 mpfr_set_ui_2exp (x, 1, -1, MPFR_RNDN);
646 check_sprintf ("0", "%.0Rf", x);
647 check_sprintf ("5e-01", "%.0Re", x);
648 check_sprintf ("0.5", "%.0Rg", x);
649 mpfr_set_ui_2exp (x, 3, -1, MPFR_RNDN);
650 check_sprintf ("2", "%.0Rf", x);
651 mpfr_set_ui_2exp (x, 5, -1, MPFR_RNDN);
652 check_sprintf ("2", "%.0Rf", x);
653 mpfr_set_ui (x, 0x1f, MPFR_RNDN);
654 check_sprintf ("0x1p+5", "%.0Ra", x);
655 mpfr_set_ui (x, 3, MPFR_RNDN);
656 check_sprintf ("1p+2", "%.0Rb", x);
657
658 /* round to next ten power with %f but not with %g */
659 mpfr_set_str (x, "-6.64464380544039223686e-02", 10, MPFR_RNDN);
660 check_sprintf ("-0.1", "%.1Rf", x);
661 check_sprintf ("-0.0", "%.1RZf", x);
662 check_sprintf ("-0.07", "%.1Rg", x);
663 check_sprintf ("-0.06", "%.1RZg", x);
664
665 /* round to next ten power and do not remove trailing zeros */
666 mpfr_set_str (x, "9.98429393291486722006e-02", 10, MPFR_RNDN);
667 check_sprintf ("0.1", "%#.1Rg", x);
668 check_sprintf ("0.10", "%#.2Rg", x);
669 check_sprintf ("0.099", "%#.2RZg", x);
670
671 /* Halfway cases */
672 mpfr_set_str (x, "1.5", 10, MPFR_RNDN);
673 check_sprintf ("2e+00", "%.0Re", x);
674 mpfr_set_str (x, "2.5", 10, MPFR_RNDN);
675 check_sprintf ("2e+00", "%.0Re", x);
676 mpfr_set_str (x, "9.5", 10, MPFR_RNDN);
677 check_sprintf ("1e+01", "%.0Re", x);
678 mpfr_set_str (x, "1.25", 10, MPFR_RNDN);
679 check_sprintf ("1.2e+00", "%.1Re", x);
680 mpfr_set_str (x, "1.75", 10, MPFR_RNDN);
681 check_sprintf ("1.8e+00", "%.1Re", x);
682 mpfr_set_str (x, "-0.5", 10, MPFR_RNDN);
683 check_sprintf ("-0", "%.0Rf", x);
684 mpfr_set_str (x, "1.25", 10, MPFR_RNDN);
685 check_sprintf ("1.2", "%.1Rf", x);
686 mpfr_set_str (x, "1.75", 10, MPFR_RNDN);
687 check_sprintf ("1.8", "%.1Rf", x);
688 mpfr_set_str (x, "1.5", 10, MPFR_RNDN);
689 check_sprintf ("2", "%.1Rg", x);
690 mpfr_set_str (x, "2.5", 10, MPFR_RNDN);
691 check_sprintf ("2", "%.1Rg", x);
692 mpfr_set_str (x, "9.25", 10, MPFR_RNDN);
693 check_sprintf ("9.2", "%.2Rg", x);
694 mpfr_set_str (x, "9.75", 10, MPFR_RNDN);
695 check_sprintf ("9.8", "%.2Rg", x);
696
697 /* assertion failure in r6320 */
698 mpfr_set_str (x, "-9.996", 10, MPFR_RNDN);
699 check_sprintf ("-10.0", "%.1Rf", x);
700
701 /* regression in MPFR 3.1.0 (bug introduced in r7761, fixed in r7931) */
702 check_sprintf ("-10", "%.2Rg", x);
703
704 mpfr_clears (x, y, z, (mpfr_ptr) 0);
705 }
706
707 static void
hexadecimal(void)708 hexadecimal (void)
709 {
710 mpfr_t x, z;
711
712 mpfr_inits2 (64, x, z, (mpfr_ptr) 0);
713
714 /* special numbers: tested in special() */
715
716 /* regular numbers */
717 mpfr_set_str (x, "FEDCBA9.87654321", 16, MPFR_RNDN);
718 mpfr_set_ui (z, 0, MPFR_RNDZ);
719
720 /* simplest case right justified */
721 check_sprintf (" 0xf.edcba987654321p+24", "%25Ra", x);
722 check_sprintf (" 0xf.edcba987654321p+24", "%25RUa", x);
723 check_sprintf (" 0xf.edcba987654321p+24", "%25RDa", x);
724 check_sprintf (" 0xf.edcba987654321p+24", "%25RYa", x);
725 check_sprintf (" 0xf.edcba987654321p+24", "%25RZa", x);
726 check_sprintf (" 0xf.edcba987654321p+24", "%25RNa", x);
727 check_sprintf (" 0x1p+28", "%25.0Ra", x);
728 check_sprintf (" 0x0p+0", "%25.0Ra", z);
729 check_sprintf (" 0x0p+0", "%25Ra", z);
730 check_sprintf (" 0x0.p+0", "%#25Ra", z);
731 /* sign or space, pad with leading zeros */
732 check_sprintf (" 0X00F.EDCBA987654321P+24", "% 025RA", x);
733 check_sprintf (" 0X000000000000000001P+28", "% 025.0RA", x);
734 check_sprintf (" 0X0000000000000000000P+0", "% 025.0RA", z);
735 /* sign + or -, left justified */
736 check_sprintf ("+0xf.edcba987654321p+24 ", "%+-25Ra", x);
737 check_sprintf ("+0x1p+28 ", "%+-25.0Ra", x);
738 check_sprintf ("+0x0p+0 ", "%+-25.0Ra", z);
739 /* decimal point, left justified, precision and rounding parameter */
740 check_vsprintf ("0XF.FP+24 ", "%#-10.*R*A", 1, MPFR_RNDN, x);
741 check_vsprintf ("0X1.P+28 ", "%#-10.*R*A", 0, MPFR_RNDN, x);
742 check_vsprintf ("0X0.P+0 ", "%#-10.*R*A", 0, MPFR_RNDN, z);
743 /* sign or space */
744 check_sprintf (" 0xf.eddp+24", "% .3RNa", x);
745 check_sprintf (" 0x1p+28", "% .0RNa", x);
746 /* sign + or -, decimal point, pad with leading zeros */
747 check_sprintf ("+0X0F.EP+24", "%0+#11.1RZA", x);
748 check_sprintf ("+0X00F.P+24", "%0+#11.0RZA", x);
749 check_sprintf ("+0X000.0P+0", "%0+#11.1RZA", z);
750 /* pad with leading zero */
751 check_sprintf ("0x0000f.edcba987654321p+24", "%026RDa", x);
752 check_sprintf ("0x0000000000000000000fp+24", "%026.0RDa", x);
753 /* sign or space, decimal point, left justified */
754 check_sprintf (" 0XF.EP+24 ", "%- #11.1RDA", x);
755 check_sprintf (" 0XF.P+24 ", "%- #11.0RDA", x);
756
757 mpfr_mul_si (x, x, -1, MPFR_RNDD);
758 mpfr_mul_si (z, z, -1, MPFR_RNDD);
759
760 /* sign + or - */
761 check_sprintf ("-0xf.ep+24", "%+10.1RUa", x);
762 check_sprintf (" -0xfp+24", "%+10.0RUa", x);
763 check_sprintf (" -0x0p+0", "%+10.0RUa", z);
764
765 /* rounding bit is zero */
766 mpfr_set_str (x, "0xF.7", 16, MPFR_RNDN);
767 check_sprintf ("0XFP+0", "%.0RNA", x);
768 /* tie case in round to nearest mode */
769 mpfr_set_str (x, "0x0.8800000000000000p+3", 16, MPFR_RNDN);
770 check_sprintf ("0x9.p-1", "%#.0RNa", x);
771 mpfr_set_str (x, "-0x0.9800000000000000p+3", 16, MPFR_RNDN);
772 check_sprintf ("-0xap-1", "%.0RNa", x);
773 /* trailing zeros in fractional part */
774 check_sprintf ("-0X4.C0000000000000000000P+0", "%.20RNA", x);
775 /* rounding bit is one and the first non zero bit is far away */
776 mpfr_set_prec (x, 1024);
777 mpfr_set_ui_2exp (x, 29, -1, MPFR_RNDN);
778 mpfr_nextabove (x);
779 check_sprintf ("0XFP+0", "%.0RNA", x);
780
781 /* with more than one limb */
782 mpfr_set_prec (x, 300);
783 mpfr_set_str (x, "0xf.ffffffffffffffffffffffffffffffffffffffffffffffffffff"
784 "fffffffffffffffff", 16, MPFR_RNDN);
785 check_sprintf ("0x1p+4 [300]", "%.0RNa [300]", x);
786 check_sprintf ("0xfp+0 [300]", "%.0RZa [300]", x);
787 check_sprintf ("0x1p+4 [300]", "%.0RYa [300]", x);
788 check_sprintf ("0xfp+0 [300]", "%.0RDa [300]", x);
789 check_sprintf ("0x1p+4 [300]", "%.0RUa [300]", x);
790 check_sprintf ("0x1.0000000000000000000000000000000000000000p+4",
791 "%.40RNa", x);
792 check_sprintf ("0xf.ffffffffffffffffffffffffffffffffffffffffp+0",
793 "%.40RZa", x);
794 check_sprintf ("0x1.0000000000000000000000000000000000000000p+4",
795 "%.40RYa", x);
796 check_sprintf ("0xf.ffffffffffffffffffffffffffffffffffffffffp+0",
797 "%.40RDa", x);
798 check_sprintf ("0x1.0000000000000000000000000000000000000000p+4",
799 "%.40RUa", x);
800
801 mpfr_set_str (x, "0xf.7fffffffffffffffffffffffffffffffffffffffffffffffffff"
802 "ffffffffffffffffff", 16, MPFR_RNDN);
803 check_sprintf ("0XFP+0", "%.0RNA", x);
804 check_sprintf ("0XFP+0", "%.0RZA", x);
805 check_sprintf ("0X1P+4", "%.0RYA", x);
806 check_sprintf ("0XFP+0", "%.0RDA", x);
807 check_sprintf ("0X1P+4", "%.0RUA", x);
808 check_sprintf ("0XF.8P+0", "%.1RNA", x);
809 check_sprintf ("0XF.7P+0", "%.1RZA", x);
810 check_sprintf ("0XF.8P+0", "%.1RYA", x);
811 check_sprintf ("0XF.7P+0", "%.1RDA", x);
812 check_sprintf ("0XF.8P+0", "%.1RUA", x);
813
814 /* do not round up to the next power of the base */
815 mpfr_set_str (x, "0xf.fffffffffffffffffffffffffffffffffffffeffffffffffffff"
816 "ffffffffffffffffff", 16, MPFR_RNDN);
817 check_sprintf ("0xf.ffffffffffffffffffffffffffffffffffffff00p+0",
818 "%.40RNa", x);
819 check_sprintf ("0xf.fffffffffffffffffffffffffffffffffffffeffp+0",
820 "%.40RZa", x);
821 check_sprintf ("0xf.ffffffffffffffffffffffffffffffffffffff00p+0",
822 "%.40RYa", x);
823 check_sprintf ("0xf.fffffffffffffffffffffffffffffffffffffeffp+0",
824 "%.40RDa", x);
825 check_sprintf ("0xf.ffffffffffffffffffffffffffffffffffffff00p+0",
826 "%.40RUa", x);
827
828 mpfr_clears (x, z, (mpfr_ptr) 0);
829 }
830
831 static void
binary(void)832 binary (void)
833 {
834 mpfr_t x;
835 mpfr_t z;
836
837 mpfr_inits2 (64, x, z, (mpfr_ptr) 0);
838
839 /* special numbers: tested in special() */
840
841 /* regular numbers */
842 mpfr_set_str (x, "1110010101.1001101", 2, MPFR_RNDN);
843 mpfr_set_ui (z, 0, MPFR_RNDN);
844
845 /* simplest case: right justified */
846 check_sprintf (" 1.1100101011001101p+9", "%25Rb", x);
847 check_sprintf (" 0p+0", "%25Rb", z);
848 check_sprintf (" 0.p+0", "%#25Rb", z);
849 /* sign or space, pad with leading zeros */
850 check_sprintf (" 0001.1100101011001101p+9", "% 025Rb", x);
851 check_sprintf (" 000000000000000000000p+0", "% 025Rb", z);
852 /* sign + or -, left justified */
853 check_sprintf ("+1.1100101011001101p+9 ", "%+-25Rb", x);
854 check_sprintf ("+0p+0 ", "%+-25Rb", z);
855 /* sign or space */
856 check_sprintf (" 1.110p+9", "% .3RNb", x);
857 check_sprintf (" 1.1101p+9", "% .4RNb", x);
858 check_sprintf (" 0.0000p+0", "% .4RNb", z);
859 /* sign + or -, decimal point, pad with leading zeros */
860 check_sprintf ("+00001.1p+9", "%0+#11.1RZb", x);
861 check_sprintf ("+0001.0p+10", "%0+#11.1RNb", x);
862 check_sprintf ("+000000.p+0", "%0+#11.0RNb", z);
863 /* pad with leading zero */
864 check_sprintf ("00001.1100101011001101p+9", "%025RDb", x);
865 /* sign or space, decimal point (unused), left justified */
866 check_sprintf (" 1.1p+9 ", "%- #11.1RDb", x);
867 check_sprintf (" 1.p+9 ", "%- #11.0RDb", x);
868 check_sprintf (" 1.p+10 ", "%- #11.0RUb", x);
869 check_sprintf (" 1.p+9 ", "%- #11.0RZb", x);
870 check_sprintf (" 1.p+10 ", "%- #11.0RYb", x);
871 check_sprintf (" 1.p+10 ", "%- #11.0RNb", x);
872
873 mpfr_mul_si (x, x, -1, MPFR_RNDD);
874 mpfr_mul_si (z, z, -1, MPFR_RNDD);
875
876 /* sign + or - */
877 check_sprintf (" -1.1p+9", "%+10.1RUb", x);
878 check_sprintf (" -0.0p+0", "%+10.1RUb", z);
879
880 /* precision 0 */
881 check_sprintf ("-1p+10", "%.0RNb", x);
882 check_sprintf ("-1p+10", "%.0RDb", x);
883 check_sprintf ("-1p+9", "%.0RUb", x);
884 check_sprintf ("-1p+9", "%.0RZb", x);
885 check_sprintf ("-1p+10", "%.0RYb", x);
886 /* round to next base power */
887 check_sprintf ("-1.0p+10", "%.1RNb", x);
888 check_sprintf ("-1.0p+10", "%.1RDb", x);
889 check_sprintf ("-1.0p+10", "%.1RYb", x);
890 /* do not round to next base power */
891 check_sprintf ("-1.1p+9", "%.1RUb", x);
892 check_sprintf ("-1.1p+9", "%.1RZb", x);
893 /* rounding bit is zero */
894 check_sprintf ("-1.11p+9", "%.2RNb", x);
895 /* tie case in round to nearest mode */
896 check_sprintf ("-1.1100101011001101p+9", "%.16RNb", x);
897 /* trailing zeros in fractional part */
898 check_sprintf ("-1.110010101100110100000000000000p+9", "%.30RNb", x);
899
900 mpfr_clears (x, z, (mpfr_ptr) 0);
901 }
902
903 static void
mixed(void)904 mixed (void)
905 {
906 int n1;
907 int n2;
908 int i = 121;
909 #ifdef PRINTF_L
910 long double d = 1. / 31.;
911 #endif
912 mpf_t mpf;
913 mpq_t mpq;
914 mpz_t mpz;
915 mpfr_t x;
916 mpfr_rnd_t rnd;
917 int k;
918
919 mpf_init (mpf);
920 mpf_set_ui (mpf, 40);
921 mpf_div_ui (mpf, mpf, 31); /* mpf = 40.0 / 31.0 */
922 mpq_init (mpq);
923 mpq_set_ui (mpq, 123456, 4567890);
924 mpz_init (mpz);
925 mpz_fib_ui (mpz, 64);
926 mpfr_init (x);
927 mpfr_set_str (x, "-12345678.875", 10, MPFR_RNDN);
928 rnd = MPFR_RNDD;
929
930 check_vsprintf ("121%", "%i%%", i);
931 check_vsprintf ("121% -1.2345678875000000E+07", "%i%% %RNE", i, x);
932 check_vsprintf ("121, -12345679", "%i, %.0Rf", i, x);
933 check_vsprintf ("10610209857723, -1.2345678875000000e+07", "%Zi, %R*e", mpz, rnd,
934 x);
935 check_vsprintf ("-12345678.9, 121", "%.1Rf, %i", x, i);
936 check_vsprintf ("-12345678, 1e240/45b352", "%.0R*f, %Qx", MPFR_RNDZ, x, mpq);
937
938 /* TODO: Systematically test with and without %n in check_vsprintf? */
939 /* Do the test several times due to random parameters in check_vsprintf
940 and the use of %n. In r11501, n2 is incorrect (seems random) when
941 randsize <= 0, i.e. when the size argument of mpfr_vsnprintf is 0. */
942 for (k = 0; k < 30; k++)
943 {
944 n2 = -17;
945 /* If this value is obtained for n2 after the check_vsprintf call below,
946 this probably means that n2 has not been written as expected. */
947 n1 = check_vsprintf ("121, -12345678.875000000000, 1.290323",
948 "%i, %.*Rf, %Ff%n", i, 12, x, mpf, &n2);
949 if (n1 != n2)
950 {
951 printf ("error in number of characters written by mpfr_vsprintf"
952 " for k = %d, randsize = %d\n", k, randsize);
953 printf ("expected: %d\n", n2);
954 printf (" got: %d\n", n1);
955 exit (1);
956 }
957 }
958
959 #ifdef PRINTF_L
960 /* under MinGW, -D__USE_MINGW_ANSI_STDIO is required to support %Lf
961 see https://gcc.gnu.org/legacy-ml/gcc/2013-03/msg00103.html */
962 check_vsprintf ("00000010610209857723, -1.2345678875000000e+07, 0.032258",
963 "%.*Zi, %R*e, %Lf", 20, mpz, rnd, x, d);
964 #endif
965
966 /* check invalid spec.spec */
967 check_vsprintf ("%,", "%,");
968 check_vsprintf ("%3*Rg", "%3*Rg");
969
970 /* check empty format */
971 check_vsprintf ("%", "%");
972
973 mpf_clear (mpf);
974 mpq_clear (mpq);
975 mpz_clear (mpz);
976 mpfr_clear (x);
977 }
978
979 #if defined(HAVE_LOCALE_H) && defined(HAVE_SETLOCALE) && MPFR_LCONV_DPTS
980
981 /* Check with locale "da_DK.utf8" or "da_DK".
982 On most platforms, decimal point is ',' and thousands separator is '.';
983 if this is not the case or if the locale does not exist, the test is not
984 performed (and if the MPFR_CHECK_LOCALES environment variable is set,
985 the program fails). */
986 static void
locale_da_DK(void)987 locale_da_DK (void)
988 {
989 mpfr_prec_t p = 128;
990 mpfr_t x, y;
991
992 if ((setlocale (LC_ALL, "da_DK.utf8") == 0 &&
993 setlocale (LC_ALL, "da_DK") == 0) ||
994 localeconv()->decimal_point[0] != ',' ||
995 localeconv()->thousands_sep[0] != '.')
996 {
997 setlocale (LC_ALL, "C");
998
999 if (getenv ("MPFR_CHECK_LOCALES") == NULL)
1000 return;
1001
1002 fprintf (stderr,
1003 "Cannot test the da_DK locale (not found or inconsistent).\n");
1004 exit (1);
1005 }
1006
1007 mpfr_init2 (x, p);
1008
1009 /* positive numbers */
1010 mpfr_set_str (x, "18993474.61279296875", 10, MPFR_RNDN);
1011 mpfr_init2 (y, 59);
1012 mpfr_set (y, x, MPFR_RNDN);
1013
1014 /* simplest case right justified with thousands separator */
1015 check_sprintf ("1,899347461279296875000000000000000000000e+07", "%'30Re", x);
1016 check_sprintf (" 1,899347461279296875e+07", "%'30Re", y);
1017 check_sprintf (" 1,89935e+07", "%'30Rg", x);
1018 check_sprintf (" 18.993.474,61279296875", "%'30.19Rg", x);
1019 check_sprintf (" 18.993.474,612793", "%'30Rf", x);
1020
1021 /* sign or space, pad, thousands separator with leading zeros */
1022 check_sprintf (" 1,899347461279296875000000000000000000000E+07", "%' 030RE", x);
1023 check_sprintf (" 000001,899347461279296875E+07", "%' 030RE", y);
1024 check_sprintf (" 0000000000000000001,89935E+07", "%' 030RG", x);
1025 check_sprintf (" 000000018.993.474,61279296875", "%' 030.19RG", x);
1026 check_sprintf (" 00000000000018.993.474,612793", "%' 030RF", x);
1027
1028 #define T1 "000"
1029 #define T2 ".000"
1030 #define S1 T1 T1 T1 T1 T1 T1 T1 T1 T1 T1 T1 T1 T1 T1 T1 T1
1031 #define S2 T2 T2 T2 T2 T2 T2 T2 T2 T2 T2 T2 T2 T2 T2 T2 T2 ","
1032
1033 mpfr_set_ui (x, 48, MPFR_RNDN);
1034 mpfr_exp10 (x, x, MPFR_RNDN);
1035 check_sprintf ("1" S1, "%.0Rf", x);
1036 check_sprintf ("1" S2, "%'#.0Rf", x);
1037 check_sprintf ("1" S2 "0000", "%'.4Rf", x);
1038 mpfr_mul_ui (x, x, 10, MPFR_RNDN);
1039 check_sprintf ("10" S1, "%.0Rf", x);
1040 check_sprintf ("10" S2, "%'#.0Rf", x);
1041 check_sprintf ("10" S2 "0000", "%'.4Rf", x);
1042 mpfr_mul_ui (x, x, 10, MPFR_RNDN);
1043 check_sprintf ("100" S1, "%.0Rf", x);
1044 check_sprintf ("100" S2, "%'#.0Rf", x);
1045 check_sprintf ("100" S2 "0000", "%'.4Rf", x);
1046
1047 mpfr_clear (x);
1048 mpfr_clear (y);
1049
1050 setlocale (LC_ALL, "C");
1051 }
1052
1053 #endif /* ... && MPFR_LCONV_DPTS */
1054
1055 /* check concordance between mpfr_asprintf result with a regular mpfr float
1056 and with a regular double float */
1057 static void
random_double(void)1058 random_double (void)
1059 {
1060 mpfr_t x; /* random regular mpfr float */
1061 double y; /* regular double float (equal to x) */
1062
1063 char flag[] =
1064 {
1065 '-',
1066 '+',
1067 ' ',
1068 '#',
1069 '0', /* no ambiguity: first zeros are flag zero */
1070 '\'' /* SUS extension */
1071 };
1072 /* no 'a': mpfr and glibc do not have the same semantic */
1073 char specifier[] =
1074 {
1075 'e',
1076 'f',
1077 'g',
1078 'E',
1079 'f', /* SUSv2 doesn't accept %F, but %F and %f are the same for
1080 regular numbers */
1081 'G',
1082 };
1083 int spec; /* random index in specifier[] */
1084 int prec; /* random value for precision field */
1085
1086 /* in the format string for mpfr_t variable, the maximum length is
1087 reached by something like "%-+ #0'.*Rf", that is 12 characters. */
1088 #define FMT_MPFR_SIZE 12
1089 char fmt_mpfr[FMT_MPFR_SIZE];
1090 char *ptr_mpfr;
1091
1092 /* in the format string for double variable, the maximum length is
1093 reached by something like "%-+ #0'.*f", that is 11 characters. */
1094 #define FMT_SIZE 11
1095 char fmt[FMT_SIZE];
1096 char *ptr;
1097
1098 int xi;
1099 char *xs;
1100 int yi;
1101 char *ys;
1102
1103 int i, j, jmax;
1104
1105 mpfr_init2 (x, MPFR_LDBL_MANT_DIG);
1106
1107 for (i = 0; i < 1000; ++i)
1108 {
1109 /* 1. random double */
1110 do
1111 {
1112 y = DBL_RAND ();
1113 }
1114 while (ABS(y) < DBL_MIN);
1115
1116 if (RAND_BOOL ())
1117 y = -y;
1118
1119 mpfr_set_d (x, y, MPFR_RNDN);
1120 if (y != mpfr_get_d (x, MPFR_RNDN))
1121 /* conversion error: skip this one */
1122 continue;
1123
1124 /* 2. build random format strings fmt_mpfr and fmt */
1125 ptr_mpfr = fmt_mpfr;
1126 ptr = fmt;
1127 *ptr_mpfr++ = *ptr++ = '%';
1128 /* random specifier 'e', 'f', 'g', 'E', 'F', or 'G' */
1129 spec = (int) (randlimb() % 6);
1130 /* random flags, but no ' flag with %e or with non-glibc */
1131 #if __MPFR_GLIBC(1,0)
1132 jmax = (spec == 0 || spec == 3) ? 5 : 6;
1133 #else
1134 jmax = 5;
1135 #endif
1136 for (j = 0; j < jmax; j++)
1137 {
1138 if (randlimb() % 3 == 0)
1139 *ptr_mpfr++ = *ptr++ = flag[j];
1140 }
1141 *ptr_mpfr++ = *ptr++ = '.';
1142 *ptr_mpfr++ = *ptr++ = '*';
1143 *ptr_mpfr++ = 'R';
1144 *ptr_mpfr++ = *ptr++ = specifier[spec];
1145 *ptr_mpfr = *ptr = '\0';
1146 MPFR_ASSERTN (ptr - fmt < FMT_SIZE);
1147 MPFR_ASSERTN (ptr_mpfr - fmt_mpfr < FMT_MPFR_SIZE);
1148
1149 /* advantage small precision */
1150 prec = RAND_BOOL () ? 10 : prec_max_printf;
1151 prec = (int) (randlimb () % prec);
1152
1153 /* 3. calls and checks */
1154 /* the double float case is handled by the libc asprintf through
1155 gmp_asprintf */
1156 xi = mpfr_asprintf (&xs, fmt_mpfr, prec, x);
1157 yi = mpfr_asprintf (&ys, fmt, prec, y);
1158
1159 /* test if XS and YS differ, beware that ISO C99 doesn't specify
1160 the sign of a zero exponent (the C99 rationale says: "The sign
1161 of a zero exponent in %e format is unspecified. The committee
1162 knows of different implementations and choose not to require
1163 implementations to document their behavior in this case
1164 (by making this be implementation defined behaviour). Most
1165 implementations use a "+" sign, e.g., 1.2e+00; but there is at
1166 least one implementation that uses the sign of the unlimited
1167 precision result, e.g., the 0.987 would be 9.87e-01, so could
1168 end up as 1e-00 after rounding to one digit of precision."),
1169 while mpfr always uses '+' */
1170 if (xi != yi
1171 || ((strcmp (xs, ys) != 0)
1172 && (spec == 1 || spec == 4
1173 || ((strstr (xs, "e+00") == NULL
1174 || strstr (ys, "e-00") == NULL)
1175 && (strstr (xs, "E+00") == NULL
1176 || strstr (ys, "E-00") == NULL)))))
1177 {
1178 mpfr_printf ("Error in mpfr_asprintf(\"%s\", %d, %Re)\n",
1179 fmt_mpfr, prec, x);
1180 printf ("expected: %s\n", ys);
1181 printf (" got: %s\n", xs);
1182 printf ("xi=%d yi=%d spec=%d\n", xi, yi, spec);
1183
1184 exit (1);
1185 }
1186
1187 mpfr_free_str (xs);
1188 mpfr_free_str (ys);
1189 }
1190
1191 mpfr_clear (x);
1192 }
1193
1194 static void
bug20080610(void)1195 bug20080610 (void)
1196 {
1197 /* bug on icc found on June 10, 2008 */
1198 /* this is not a bug but a different implementation choice: ISO C99 doesn't
1199 specify the sign of a zero exponent (see note in random_double above). */
1200 mpfr_t x;
1201 double y;
1202 int xi;
1203 char *xs;
1204 int yi;
1205 char *ys;
1206
1207 mpfr_init2 (x, MPFR_LDBL_MANT_DIG);
1208
1209 y = -9.95645044213728791504536275169812142849e-01;
1210 mpfr_set_d (x, y, MPFR_RNDN);
1211
1212 xi = mpfr_asprintf (&xs, "%- #0.*Re", 1, x);
1213 yi = mpfr_asprintf (&ys, "%- #0.*e", 1, y);
1214
1215 if (xi != yi || strcmp (xs, ys) != 0)
1216 {
1217 printf ("Error in bug20080610\n");
1218 printf ("expected: %s\n", ys);
1219 printf (" got: %s\n", xs);
1220 printf ("xi=%d yi=%d\n", xi, yi);
1221
1222 exit (1);
1223 }
1224
1225 mpfr_free_str (xs);
1226 mpfr_free_str (ys);
1227 mpfr_clear (x);
1228 }
1229
1230 static void
bug20081214(void)1231 bug20081214 (void)
1232 {
1233 /* problem with glibc 2.3.6, December 14, 2008:
1234 the system asprintf outputs "-1.0" instead of "-1.". */
1235 mpfr_t x;
1236 double y;
1237 int xi;
1238 char *xs;
1239 int yi;
1240 char *ys;
1241
1242 mpfr_init2 (x, MPFR_LDBL_MANT_DIG);
1243
1244 y = -9.90597761233942053494e-01;
1245 mpfr_set_d (x, y, MPFR_RNDN);
1246
1247 xi = mpfr_asprintf (&xs, "%- #0.*RG", 1, x);
1248 yi = mpfr_asprintf (&ys, "%- #0.*G", 1, y);
1249
1250 if (xi != yi || strcmp (xs, ys) != 0)
1251 {
1252 mpfr_printf ("Error in bug20081214\n"
1253 "mpfr_asprintf(\"%- #0.*Re\", 1, %Re)\n", x);
1254 printf ("expected: %s\n", ys);
1255 printf (" got: %s\n", xs);
1256 printf ("xi=%d yi=%d\n", xi, yi);
1257
1258 exit (1);
1259 }
1260
1261 mpfr_free_str (xs);
1262 mpfr_free_str (ys);
1263 mpfr_clear (x);
1264 }
1265
1266 static void
bug20111102(void)1267 bug20111102 (void)
1268 {
1269 mpfr_t t;
1270 char s[100];
1271
1272 mpfr_init2 (t, 84);
1273 mpfr_set_str (t, "999.99999999999999999999", 10, MPFR_RNDN);
1274 mpfr_sprintf (s, "%.20RNg", t);
1275 if (strcmp (s, "1000") != 0)
1276 {
1277 printf ("Error in bug20111102, expected 1000, got %s\n", s);
1278 exit (1);
1279 }
1280 mpfr_clear (t);
1281 }
1282
1283 /* In particular, the following test makes sure that the rounding
1284 * for %Ra and %Rb is not done on the MPFR number itself (as it
1285 * would overflow). Note: it has been reported on comp.std.c that
1286 * some C libraries behave differently on %a, but this is a bug.
1287 */
1288 static void
check_emax_aux(mpfr_exp_t e)1289 check_emax_aux (mpfr_exp_t e)
1290 {
1291 mpfr_t x;
1292 char *s1, s2[256];
1293 int i;
1294 mpfr_exp_t emax;
1295
1296 MPFR_ASSERTN (e <= LONG_MAX);
1297 emax = mpfr_get_emax ();
1298 set_emax (e);
1299
1300 mpfr_init2 (x, 16);
1301
1302 mpfr_set_inf (x, 1);
1303 mpfr_nextbelow (x);
1304
1305 i = mpfr_asprintf (&s1, "%Ra %.2Ra", x, x);
1306 MPFR_ASSERTN (i > 0);
1307
1308 mpfr_snprintf (s2, 256, "0x7.fff8p+%ld 0x8.00p+%ld", e-3, e-3);
1309
1310 if (strcmp (s1, s2) != 0)
1311 {
1312 printf ("Error in check_emax_aux for emax = ");
1313 if (e > LONG_MAX)
1314 printf ("(>LONG_MAX)\n");
1315 else
1316 printf ("%ld\n", (long) e);
1317 printf ("Expected '%s'\n", s2);
1318 printf ("Got '%s'\n", s1);
1319 exit (1);
1320 }
1321
1322 mpfr_free_str (s1);
1323
1324 i = mpfr_asprintf (&s1, "%Rb %.2Rb", x, x);
1325 MPFR_ASSERTN (i > 0);
1326
1327 mpfr_snprintf (s2, 256, "1.111111111111111p+%ld 1.00p+%ld", e-1, e);
1328
1329 if (strcmp (s1, s2) != 0)
1330 {
1331 printf ("Error in check_emax_aux for emax = ");
1332 if (e > LONG_MAX)
1333 printf ("(>LONG_MAX)\n");
1334 else
1335 printf ("%ld\n", (long) e);
1336 printf ("Expected %s\n", s2);
1337 printf ("Got %s\n", s1);
1338 exit (1);
1339 }
1340
1341 mpfr_free_str (s1);
1342
1343 mpfr_clear (x);
1344 set_emax (emax);
1345 }
1346
1347 static void
check_emax(void)1348 check_emax (void)
1349 {
1350 check_emax_aux (15);
1351 check_emax_aux (MPFR_EMAX_MAX);
1352 }
1353
1354 static void
check_emin_aux(mpfr_exp_t e)1355 check_emin_aux (mpfr_exp_t e)
1356 {
1357 mpfr_t x;
1358 char *s1, s2[256];
1359 int i;
1360 mpfr_exp_t emin;
1361 mpz_t ee;
1362
1363 MPFR_ASSERTN (e >= LONG_MIN);
1364 emin = mpfr_get_emin ();
1365 set_emin (e);
1366
1367 mpfr_init2 (x, 16);
1368 mpz_init (ee);
1369
1370 mpfr_setmin (x, e);
1371 mpz_set_si (ee, e);
1372 mpz_sub_ui (ee, ee, 1);
1373
1374 i = mpfr_asprintf (&s1, "%Ra", x);
1375 MPFR_ASSERTN (i > 0);
1376
1377 gmp_snprintf (s2, 256, "0x1p%Zd", ee);
1378
1379 if (strcmp (s1, s2) != 0)
1380 {
1381 printf ("Error in check_emin_aux for emin = %ld\n", (long) e);
1382 printf ("Expected %s\n", s2);
1383 printf ("Got %s\n", s1);
1384 exit (1);
1385 }
1386
1387 mpfr_free_str (s1);
1388
1389 i = mpfr_asprintf (&s1, "%Rb", x);
1390 MPFR_ASSERTN (i > 0);
1391
1392 gmp_snprintf (s2, 256, "1p%Zd", ee);
1393
1394 if (strcmp (s1, s2) != 0)
1395 {
1396 printf ("Error in check_emin_aux for emin = %ld\n", (long) e);
1397 printf ("Expected %s\n", s2);
1398 printf ("Got %s\n", s1);
1399 exit (1);
1400 }
1401
1402 mpfr_free_str (s1);
1403
1404 mpfr_clear (x);
1405 mpz_clear (ee);
1406 set_emin (emin);
1407 }
1408
1409 static void
check_emin(void)1410 check_emin (void)
1411 {
1412 check_emin_aux (-15);
1413 check_emin_aux (mpfr_get_emin ());
1414 check_emin_aux (MPFR_EMIN_MIN);
1415 }
1416
1417 static void
test20161214(void)1418 test20161214 (void)
1419 {
1420 mpfr_t x;
1421 char buf[32];
1422 const char s[] = "0x0.fffffffffffff8p+1024";
1423 int r;
1424
1425 mpfr_init2 (x, 64);
1426 mpfr_set_str (x, s, 16, MPFR_RNDN);
1427 r = mpfr_snprintf (buf, 32, "%.*RDf", -2, x);
1428 MPFR_ASSERTN(r == 316);
1429 r = mpfr_snprintf (buf, 32, "%.*RDf", INT_MIN + 1, x);
1430 MPFR_ASSERTN(r == 316);
1431 r = mpfr_snprintf (buf, 32, "%.*RDf", INT_MIN, x);
1432 MPFR_ASSERTN(r == 316);
1433 mpfr_clear (x);
1434 }
1435
1436 /* http://gforge.inria.fr/tracker/index.php?func=detail&aid=21056 */
1437 static void
bug21056(void)1438 bug21056 (void)
1439 {
1440 mpfr_t x;
1441 const char s[] = "0x0.fffffffffffff8p+1024";
1442 int ndigits, r;
1443
1444 mpfr_init2 (x, 64);
1445
1446 mpfr_set_str (x, s, 16, MPFR_RNDN);
1447
1448 ndigits = 1000;
1449 r = mpfr_snprintf (0, 0, "%.*RDf", ndigits, x);
1450 /* the return value should be ndigits + 310 */
1451 MPFR_ASSERTN(r == ndigits + 310);
1452
1453 ndigits = INT_MAX - 310;
1454 r = mpfr_snprintf (0, 0, "%.*RDf", ndigits, x);
1455 MPFR_ASSERTN(r == INT_MAX);
1456
1457 ndigits = INT_MAX - 10;
1458 r = mpfr_snprintf (0, 0, "%.*RDa", ndigits, x);
1459 MPFR_ASSERTN(r == INT_MAX);
1460
1461 ndigits = INT_MAX - 7;
1462 r = mpfr_snprintf (0, 0, "%.*RDe", ndigits, x);
1463 MPFR_ASSERTN(r == INT_MAX);
1464
1465 ndigits = 1000;
1466 r = mpfr_snprintf (0, 0, "%.*RDg", ndigits, x);
1467 /* since trailing zeros are removed with %g, we get less digits */
1468 MPFR_ASSERTN(r == 309);
1469
1470 ndigits = INT_MAX;
1471 r = mpfr_snprintf (0, 0, "%.*RDg", ndigits, x);
1472 /* since trailing zeros are removed with %g, we get less digits */
1473 MPFR_ASSERTN(r == 309);
1474
1475 ndigits = INT_MAX - 1;
1476 r = mpfr_snprintf (0, 0, "%#.*RDg", ndigits, x);
1477 MPFR_ASSERTN(r == ndigits + 1);
1478
1479 mpfr_clear (x);
1480 }
1481
1482 /* Fails for i = 5, i.e. t[i] = (size_t) UINT_MAX + 1,
1483 with r11427 on 64-bit machines (4-byte int, 8-byte size_t).
1484 On such machines, t[5] converted to int typically gives 0.
1485 Note: the assumed behavior corresponds to the snprintf behavior
1486 in ISO C, but this conflicts with POSIX:
1487 https://sourceware.org/bugzilla/show_bug.cgi?id=14771#c2
1488 https://austingroupbugs.net/view.php?id=761
1489 https://austingroupbugs.net/view.php?id=1219
1490 https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87096
1491 The issue was due to a 64-bit size_t converted to a 32-bit int.
1492 Fixed in r11429 (6b8cf3e2bdc285027627281cac230ed932c1b73f) on 2017-04-07.
1493 */
1494 static void
snprintf_size(void)1495 snprintf_size (void)
1496 {
1497 mpfr_t x;
1498 char buf[12];
1499 const char s[] = "17.00000000";
1500 size_t t[] = { 11, 12, 64, INT_MAX, (size_t) INT_MAX + 1,
1501 (size_t) UINT_MAX + 1, (size_t) UINT_MAX + 2,
1502 (size_t) -1 };
1503 int i, r;
1504
1505 mpfr_init2 (x, 64);
1506 mpfr_set_ui (x, 17, MPFR_RNDN);
1507
1508 for (i = 0; i < sizeof (t) / sizeof (*t); i++)
1509 {
1510 memset (buf, 0, sizeof (buf));
1511 /* r = snprintf (buf, t[i], "%.8f", 17.0); */
1512 r = mpfr_snprintf (buf, t[i], "%.8Rf", x);
1513 if (r != 11 || (t[i] > 11 && strcmp (buf, s) != 0))
1514 {
1515 printf ("Error in snprintf_size for i = %d:\n", i);
1516 printf ("expected r = 11, \"%s\"\n", s);
1517 printf ("got r = %d, \"%s\"\n", r, buf);
1518 exit (1);
1519 }
1520 }
1521
1522 mpfr_clear (x);
1523 }
1524
1525 /* With r11516, n2 gets a random value for i = 0 only!
1526 valgrind detects a problem for "nchar = buf.curr - buf.start;"
1527 in the spec.spec == 'n' case. Indeed, there is no buffer when
1528 size is 0. */
1529 static void
percent_n(void)1530 percent_n (void)
1531 {
1532 int err = 0, i, j;
1533
1534 for (i = 0; i < 24; i++)
1535 for (j = 0; j < 3; j++)
1536 {
1537 volatile int n1, n2;
1538 char buffer[64];
1539
1540 memset (buffer, 0, 64);
1541 n2 = -17;
1542 n1 = mpfr_snprintf (buffer, i % 8, "%d%n", 123, &n2);
1543 if (n1 != 3 || n2 != 3)
1544 {
1545 printf ("Error 1 in percent_n: i = %d, n1 = %d, n2 = %d\n",
1546 i, n1, n2);
1547 err = 1;
1548 }
1549 }
1550
1551 if (err)
1552 exit (1);
1553 }
1554
1555 struct clo
1556 {
1557 const char *fmt;
1558 int width, r, e;
1559 };
1560
1561 static void
check_length_overflow(void)1562 check_length_overflow (void)
1563 {
1564 mpfr_t x;
1565 int i, r, e;
1566 struct clo t[] = {
1567 { "%Rg", 0, 1, 0 },
1568 { "%*Rg", 1, 1, 0 },
1569 { "%*Rg", -1, 1, 0 },
1570 { "%5Rg", 0, 5, 0 },
1571 { "%*Rg", 5, 5, 0 },
1572 { "%*Rg", -5, 5, 0 },
1573 #if INT_MAX == 2147483647
1574 { "%2147483647Rg", 0, 2147483647, 0 },
1575 { "%2147483647Rg ", 0, -1, 1 },
1576 { "%2147483648Rg", 0, -1, 1 },
1577 { "%18446744073709551616Rg", 0, -1, 1 },
1578 { "%*Rg", 2147483647, 2147483647, 0 },
1579 { "%*Rg", -2147483647, 2147483647, 0 },
1580 # if INT_MIN < -INT_MAX
1581 { "%*Rg", INT_MIN, -1, 1 },
1582 # endif
1583 #endif
1584 };
1585
1586 mpfr_init2 (x, MPFR_PREC_MIN);
1587 mpfr_set_ui (x, 0, MPFR_RNDN);
1588
1589 for (i = 0; i < numberof (t); i++)
1590 {
1591 errno = 0;
1592 r = t[i].width == 0 ?
1593 mpfr_snprintf (NULL, 0, t[i].fmt, x) :
1594 mpfr_snprintf (NULL, 0, t[i].fmt, t[i].width, x);
1595 e = errno;
1596 if ((t[i].r < 0 ? r >= 0 : r != t[i].r)
1597 #ifdef EOVERFLOW
1598 || (t[i].e && e != EOVERFLOW)
1599 #endif
1600 )
1601 {
1602 printf ("Error in check_length_overflow for i=%d (%s %d)\n",
1603 i, t[i].fmt, t[i].width);
1604 printf ("Expected r=%d, got r=%d\n", t[i].r, r);
1605 #ifdef EOVERFLOW
1606 if (t[i].e && e != EOVERFLOW)
1607 printf ("Expected errno=EOVERFLOW=%d, got errno=%d\n",
1608 EOVERFLOW, e);
1609 #endif
1610 exit (1);
1611 }
1612 }
1613
1614 mpfr_clear (x);
1615 }
1616
1617 /* On 2023-03-22, on a 64-bit Linux machine (thus with 32-bit int),
1618 the case %.2147483648Rg yields an incorrect size computation and
1619 MPFR wants to allocate 18446744071562070545 bytes. With assertion
1620 checking (--enable-assert), one gets:
1621 vasprintf.c:1908: MPFR assertion failed: threshold >= 1
1622 for the 2nd mpfr_snprintf below (the other calls with %.2147483648Rg
1623 have the same issue).
1624
1625 This case should either succeed or fail as reaching an environmental limit
1626 like with glibc (note that the precision does not fit in an int).
1627 For MPFR, once this bug is fixed, this case should actually succeed,
1628 unless mpfr_intmax_t is a 32-bit type[*] (because 2147483648 is not
1629 representable in mpfr_intmax_t and in an int), so let's assume that
1630 in the tests below.
1631 [*] can be tested with
1632 -std=c90 -Werror -pedantic -Wformat -Wno-error=overlength-strings
1633 (this is a way to disable intmax_t).
1634 */
1635 static void
large_prec_for_g(void)1636 large_prec_for_g (void)
1637 {
1638 mpfr_t x;
1639 char buf1[4] = "xxx", buf2[4] = "xxx", buf3[4] = "xxx", buf4[4] = "xxx";
1640 int allow_fail = (mpfr_uintmax_t) -1 == 0xffffffff;
1641 int r;
1642
1643 mpfr_init2 (x, 128);
1644 mpfr_set_ui (x, 1, MPFR_RNDN);
1645
1646 r = mpfr_snprintf (NULL, 0, "%.2147483647Rg\n", x);
1647 MPFR_ASSERTN (r == 2);
1648
1649 r = mpfr_snprintf (NULL, 0, "%.2147483648Rg\n", x);
1650 MPFR_ASSERTN (r == 2 || (allow_fail && r < 0));
1651
1652 r = mpfr_snprintf (buf1, sizeof(buf1), "%.2147483647Rg\n", x);
1653 MPFR_ASSERTN (r == 2);
1654 MPFR_ASSERTN (buf1[0] == '1' && buf1[1] == '\n' && buf1[2] == 0);
1655
1656 r = mpfr_snprintf (buf2, sizeof(buf2), "%.2147483648Rg\n", x);
1657 if (r < 0)
1658 MPFR_ASSERTN (allow_fail);
1659 else
1660 {
1661 MPFR_ASSERTN (r == 2);
1662 MPFR_ASSERTN (buf2[0] == '1' && buf2[1] == '\n' && buf2[2] == 0);
1663 }
1664
1665 r = mpfr_sprintf (buf3, "%.2147483647Rg\n", x);
1666 MPFR_ASSERTN (r == 2);
1667 MPFR_ASSERTN (buf3[0] == '1' && buf3[1] == '\n' && buf3[2] == 0);
1668
1669 r = mpfr_sprintf (buf4, "%.2147483648Rg\n", x);
1670 if (r < 0)
1671 MPFR_ASSERTN (allow_fail);
1672 else
1673 {
1674 MPFR_ASSERTN (r == 2);
1675 MPFR_ASSERTN (buf4[0] == '1' && buf4[1] == '\n' && buf4[2] == 0);
1676 }
1677
1678 mpfr_clear (x);
1679 }
1680
1681 #if defined(HAVE_LOCALE_H) && defined(HAVE_SETLOCALE)
1682
1683 /* The following tests should be equivalent to those from test_locale()
1684 in tprintf.c (remove the \n at the end of the test strings). */
1685
1686 static void
test_locale(void)1687 test_locale (void)
1688 {
1689 const char * const tab_locale[] = {
1690 "en_US",
1691 "en_US.iso88591",
1692 "en_US.iso885915",
1693 "en_US.utf8"
1694 };
1695 int i;
1696 mpfr_t x;
1697 char v[] = "99999999999999999999999.5";
1698
1699 for (i = 0; i < numberof(tab_locale); i++)
1700 {
1701 char *s;
1702
1703 s = setlocale (LC_ALL, tab_locale[i]);
1704
1705 if (s != NULL && MPFR_THOUSANDS_SEPARATOR == ',')
1706 break;
1707 }
1708
1709 if (i == numberof(tab_locale))
1710 {
1711 if (getenv ("MPFR_CHECK_LOCALES") == NULL)
1712 return;
1713
1714 fprintf (stderr, "Cannot find a locale with ',' thousands separator.\n"
1715 "Please install one of the en_US based locales.\n");
1716 exit (1);
1717 }
1718
1719 mpfr_init2 (x, 113);
1720 mpfr_set_ui (x, 10000, MPFR_RNDN);
1721
1722 check_sprintf ("(1) 10000=10,000 ", "(1) 10000=%'Rg ", x);
1723 check_sprintf ("(2) 10000=10,000.000000 ", "(2) 10000=%'Rf ", x);
1724
1725 mpfr_set_ui (x, 1000, MPFR_RNDN);
1726 check_sprintf ("(3) 1000=1,000.000000 ", "(3) 1000=%'Rf ", x);
1727
1728 for (i = 1; i <= sizeof (v) - 3; i++)
1729 {
1730 char buf[64];
1731 int j;
1732
1733 strcpy (buf, "(4) 10^i=1");
1734 for (j = i; j > 0; j--)
1735 strcat (buf, (j % 3 == 0) ? ",0" : "0");
1736 strcat (buf, " ");
1737 mpfr_set_str (x, v + sizeof (v) - 3 - i, 10, MPFR_RNDN);
1738 check_sprintf (buf, "(4) 10^i=%'.0Rf ", x);
1739 }
1740
1741 #define N0 20
1742
1743 for (i = 1; i <= N0; i++)
1744 {
1745 char s[N0+4], buf[64];
1746 int j;
1747
1748 s[0] = '1';
1749 for (j = 1; j <= i; j++)
1750 s[j] = '0';
1751 s[i+1] = '\0';
1752
1753 strcpy (buf, "(5) 10^i=1");
1754 for (j = i; j > 0; j--)
1755 strcat (buf, (j % 3 == 0) ? ",0" : "0");
1756 strcat (buf, " ");
1757
1758 mpfr_set_str (x, s, 10, MPFR_RNDN);
1759
1760 check_sprintf (buf, "(5) 10^i=%'.0RNf ", x);
1761 check_sprintf (buf, "(5) 10^i=%'.0RZf ", x);
1762 check_sprintf (buf, "(5) 10^i=%'.0RUf ", x);
1763 check_sprintf (buf, "(5) 10^i=%'.0RDf ", x);
1764 check_sprintf (buf, "(5) 10^i=%'.0RYf ", x);
1765
1766 strcat (s + (i + 1), ".5");
1767 check_sprintf (buf, "(5) 10^i=%'.0Rf ", x);
1768 }
1769
1770 mpfr_set_str (x, "1000", 10, MPFR_RNDN);
1771 check_sprintf ("00000001e+03", "%'012.3Rg", x);
1772 check_sprintf ("00000001,000", "%'012.4Rg", x);
1773 check_sprintf ("000000001,000", "%'013.4Rg", x);
1774
1775 #ifdef PRINTF_GROUPFLAG
1776 /* Do not test the thousands separator with a precision field larger
1777 than the number of digits (thus needing leading zeros), such as
1778 "%0+ -'13.10Pd:" (used up to MPFR 4.2.0), since the GNU libc is
1779 buggy: https://sourceware.org/bugzilla/show_bug.cgi?id=23432
1780 We don't know about the other implementations.
1781 This new test works fine with glibc up to 2.36, but fails with 2.37
1782 (as reported by Klaus Dittrich in the MPFR mailing-list); this is
1783 actually a bug introduced in glibc 2.37, not in MPFR:
1784 https://sourceware.org/bugzilla/show_bug.cgi?id=30068
1785 Since this bug can yield a buffer overflow (CVE-2023-25139), possibly
1786 affecting MPFR users, let us rather require a fix in glibc. This bug
1787 has been fixed in the 2.37 branch:
1788 https://sourceware.org/git/?p=glibc.git;a=commit;h=07b9521fc6
1789 If we wanted to check that and avoid a failure of the test because of
1790 a buggy C library (while MPFR would be consistent with the C library),
1791 we could compare the MPFR output with both the correct output and the
1792 output from the C library (possibly buggy). But to do that in a clean
1793 way, this would require a change in the check_vsprintf() call. */
1794 check_vsprintf ("+1,234,567 :", "%0+ -'13Pd:", (mpfr_prec_t) 1234567);
1795 #endif
1796
1797 mpfr_clear (x);
1798 }
1799
1800 #else
1801
1802 static void
test_locale(void)1803 test_locale (void)
1804 {
1805 if (getenv ("MPFR_CHECK_LOCALES") != NULL)
1806 {
1807 fprintf (stderr, "Cannot test locales.\n");
1808 exit (1);
1809 }
1810 }
1811
1812 #endif
1813
1814 int
main(int argc,char ** argv)1815 main (int argc, char **argv)
1816 {
1817 int k;
1818
1819 tests_start_mpfr ();
1820
1821 #if defined(HAVE_LOCALE_H) && defined(HAVE_SETLOCALE)
1822 /* currently, we just check with 'C' locale */
1823 setlocale (LC_ALL, "C");
1824 #endif
1825
1826 bug20111102 ();
1827
1828 for (k = 0; k < 40; k++)
1829 {
1830 native_types ();
1831 special ();
1832 decimal ();
1833 hexadecimal ();
1834 binary ();
1835
1836 #if defined(HAVE_LOCALE_H) && defined(HAVE_SETLOCALE) && MPFR_LCONV_DPTS
1837 locale_da_DK ();
1838 #else
1839 if (getenv ("MPFR_CHECK_LOCALES") != NULL)
1840 {
1841 fprintf (stderr, "Cannot test locales.\n");
1842 exit (1);
1843 }
1844 #endif
1845 }
1846
1847 check_emax ();
1848 check_emin ();
1849 test20161214 ();
1850 bug21056 ();
1851 snprintf_size ();
1852 percent_n ();
1853 mixed ();
1854 check_length_overflow ();
1855 large_prec_for_g ();
1856 test_locale ();
1857
1858 if (getenv ("MPFR_CHECK_LIBC_PRINTF"))
1859 {
1860 /* check against libc */
1861 random_double ();
1862 bug20081214 ();
1863 bug20080610 ();
1864 }
1865
1866 tests_end_mpfr ();
1867 return 0;
1868 }
1869
1870 #else /* HAVE_STDARG */
1871
1872 int
main(void)1873 main (void)
1874 {
1875 /* We have nothing to test. */
1876 return 77;
1877 }
1878
1879 #endif /* HAVE_STDARG */
1880