xref: /netbsd-src/external/lgpl3/mpfr/dist/tests/tsprintf.c (revision ec6772edaf0cdcb5f52a48f4aca5e33a8fb8ecfd)
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