(root)/
mpfr-4.2.1/
tests/
tsprintf.c
       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
      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
     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
     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
     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
     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
     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
     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
     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
     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
    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
    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
    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
    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
    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
    1348  check_emax (void)
    1349  {
    1350    check_emax_aux (15);
    1351    check_emax_aux (MPFR_EMAX_MAX);
    1352  }
    1353  
    1354  static void
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    1873  main (void)
    1874  {
    1875    /* We have nothing to test. */
    1876    return 77;
    1877  }
    1878  
    1879  #endif  /* HAVE_STDARG */