recipes: devel/gcc: tune GCC on compilation (optimized for size), since the strip...
[dragora.git] / patches / mpfr / allpatches
blob173e142c0ff1200cc32ed22cfda5c75be9946a05
1 diff -Naurd mpfr-4.0.1-a/PATCHES mpfr-4.0.1-b/PATCHES
2 --- mpfr-4.0.1-a/PATCHES        2018-04-27 12:40:46.838268769 +0000
3 +++ mpfr-4.0.1-b/PATCHES        2018-04-27 12:40:46.870268475 +0000
4 @@ -0,0 +1 @@
5 +sub1sp1n-reuse
6 diff -Naurd mpfr-4.0.1-a/VERSION mpfr-4.0.1-b/VERSION
7 --- mpfr-4.0.1-a/VERSION        2018-02-07 12:50:31.000000000 +0000
8 +++ mpfr-4.0.1-b/VERSION        2018-04-27 12:40:46.870268475 +0000
9 @@ -1 +1 @@
10 -4.0.1
11 +4.0.1-p1
12 diff -Naurd mpfr-4.0.1-a/src/mpfr.h mpfr-4.0.1-b/src/mpfr.h
13 --- mpfr-4.0.1-a/src/mpfr.h     2018-02-07 12:50:31.000000000 +0000
14 +++ mpfr-4.0.1-b/src/mpfr.h     2018-04-27 12:40:46.870268475 +0000
15 @@ -27,7 +27,7 @@
16  #define MPFR_VERSION_MAJOR 4
17  #define MPFR_VERSION_MINOR 0
18  #define MPFR_VERSION_PATCHLEVEL 1
19 -#define MPFR_VERSION_STRING "4.0.1"
20 +#define MPFR_VERSION_STRING "4.0.1-p1"
22  /* User macros:
23     MPFR_USE_FILE:        Define it to make MPFR define functions dealing
24 diff -Naurd mpfr-4.0.1-a/src/sub1sp.c mpfr-4.0.1-b/src/sub1sp.c
25 --- mpfr-4.0.1-a/src/sub1sp.c   2018-01-09 12:30:58.000000000 +0000
26 +++ mpfr-4.0.1-b/src/sub1sp.c   2018-04-27 12:40:46.858268585 +0000
27 @@ -375,13 +375,15 @@
28                  }
29                else /* cases (a), (c), (d) and (e) */
30                  {
31 -                  ap[0] = -MPFR_LIMB_ONE;
32                    /* rb=1 in case (e) and case (c) */
33                    rb = d > GMP_NUMB_BITS + 1
34                      || (d == GMP_NUMB_BITS + 1 && cp[0] == MPFR_LIMB_HIGHBIT);
35                    /* sb = 1 in case (d) and (e) */
36                    sb = d > GMP_NUMB_BITS + 1
37                      || (d == GMP_NUMB_BITS + 1 && cp[0] > MPFR_LIMB_HIGHBIT);
38 +                  /* Warning: only set ap[0] last, otherwise in case ap=cp,
39 +                     the above comparisons involving cp[0] would be wrong */
40 +                  ap[0] = -MPFR_LIMB_ONE;
41                  }
42              }
43          }
44 diff -Naurd mpfr-4.0.1-a/src/version.c mpfr-4.0.1-b/src/version.c
45 --- mpfr-4.0.1-a/src/version.c  2018-02-07 12:50:31.000000000 +0000
46 +++ mpfr-4.0.1-b/src/version.c  2018-04-27 12:40:46.870268475 +0000
47 @@ -25,5 +25,5 @@
48  const char *
49  mpfr_get_version (void)
50  {
51 -  return "4.0.1";
52 +  return "4.0.1-p1";
53  }
54 diff -Naurd mpfr-4.0.1-a/tests/tsub.c mpfr-4.0.1-b/tests/tsub.c
55 --- mpfr-4.0.1-a/tests/tsub.c   2018-01-09 12:30:58.000000000 +0000
56 +++ mpfr-4.0.1-b/tests/tsub.c   2018-04-27 12:40:46.858268585 +0000
57 @@ -22,12 +22,13 @@
59  #include "mpfr-test.h"
61 -#ifdef CHECK_EXTERNAL
62  static int
63  test_sub (mpfr_ptr a, mpfr_srcptr b, mpfr_srcptr c, mpfr_rnd_t rnd_mode)
64  {
65 +#ifdef CHECK_EXTERNAL
66    int res;
67    int ok = rnd_mode == MPFR_RNDN && mpfr_number_p (b) && mpfr_number_p (c);
69    if (ok)
70      {
71        mpfr_print_raw (b);
72 @@ -42,10 +43,69 @@
73        printf ("\n");
74      }
75    return res;
77 -#else
78 -#define test_sub mpfr_sub
79 +#else  /* reuse test */
80 +  int inex;
82 +  inex = mpfr_sub (a, b, c, rnd_mode);
84 +  if (a != b && a != c && ! MPFR_IS_NAN (a))
85 +    {
86 +      mpfr_t t;
87 +      int reuse_b, reuse_c, inex_r;
89 +      reuse_b = MPFR_PREC (a) == MPFR_PREC (b);
90 +      reuse_c = MPFR_PREC (a) == MPFR_PREC (c);
92 +      if (reuse_b || reuse_c)
93 +        mpfr_init2 (t, MPFR_PREC (a));
95 +      if (reuse_b)
96 +        {
97 +          mpfr_set (t, b, MPFR_RNDN);
98 +          inex_r = mpfr_sub (t, t, c, rnd_mode);
99 +          if (!(mpfr_equal_p (t, a) && SAME_SIGN (inex_r, inex)))
100 +            {
101 +              printf ("reuse of b error in b - c in %s for\n",
102 +                      mpfr_print_rnd_mode (rnd_mode));
103 +              printf ("b = ");
104 +              mpfr_dump (b);
105 +              printf ("c = ");
106 +              mpfr_dump (c);
107 +              printf ("Expected "); mpfr_dump (a);
108 +              printf ("  with inex = %d\n", inex);
109 +              printf ("Got      "); mpfr_dump (t);
110 +              printf ("  with inex = %d\n", inex_r);
111 +              exit (1);
112 +            }
113 +        }
115 +      if (reuse_c)
116 +        {
117 +          mpfr_set (t, c, MPFR_RNDN);
118 +          inex_r = mpfr_sub (t, b, t, rnd_mode);
119 +          if (!(mpfr_equal_p (t, a) && SAME_SIGN (inex_r, inex)))
120 +            {
121 +              printf ("reuse of c error in b - c in %s for\n",
122 +                      mpfr_print_rnd_mode (rnd_mode));
123 +              printf ("b = ");
124 +              mpfr_dump (b);
125 +              printf ("c = ");
126 +              mpfr_dump (c);
127 +              printf ("Expected "); mpfr_dump (a);
128 +              printf ("  with inex = %d\n", inex);
129 +              printf ("Got      "); mpfr_dump (t);
130 +              printf ("  with inex = %d\n", inex_r);
131 +              exit (1);
132 +            }
133 +        }
135 +      if (reuse_b || reuse_c)
136 +        mpfr_clear (t);
137 +    }
139 +  return inex;
140  #endif
143  static void
144  check_diverse (void)
145 @@ -940,6 +1000,80 @@
146      }
149 +/* Fails with r12281: "reuse of c error in b - c in MPFR_RNDN". */
150 +static void
151 +bug20180217 (void)
153 +  mpfr_t x, y, z1, z2;
154 +  int r, p, d, i, inex1, inex2;
156 +  for (p = 3; p <= 3 + 4 * GMP_NUMB_BITS; p++)
157 +    {
158 +      mpfr_inits2 (p, x, y, z1, z2, (mpfr_ptr) 0);
159 +      for (d = p; d <= p+4; d++)
160 +        {
161 +          mpfr_set_ui (x, 1, MPFR_RNDN);
162 +          mpfr_set_ui_2exp (y, 1, -d, MPFR_RNDN);
163 +          for (i = 0; i < 3; i++)
164 +            {
165 +              RND_LOOP_NO_RNDF (r)
166 +                {
167 +                  mpfr_set (z1, x, MPFR_RNDN);
168 +                  if (d == p)
169 +                    {
170 +                      mpfr_nextbelow (z1);
171 +                      if (i == 0)
172 +                        inex1 = 0;
173 +                      else if (r == MPFR_RNDD || r == MPFR_RNDZ ||
174 +                               (r == MPFR_RNDN && i > 1))
175 +                        {
176 +                          mpfr_nextbelow (z1);
177 +                          inex1 = -1;
178 +                        }
179 +                      else
180 +                        inex1 = 1;
181 +                    }
182 +                  else if (r == MPFR_RNDD || r == MPFR_RNDZ ||
183 +                           (r == MPFR_RNDN && d == p+1 && i > 0))
184 +                    {
185 +                      mpfr_nextbelow (z1);
186 +                      inex1 = -1;
187 +                    }
188 +                  else
189 +                    inex1 = 1;
190 +                  inex2 = test_sub (z2, x, y, (mpfr_rnd_t) r);
191 +                  if (!(mpfr_equal_p (z1, z2) && SAME_SIGN (inex1, inex2)))
192 +                    {
193 +                      printf ("Error in bug20180217 with "
194 +                              "p=%d, d=%d, i=%d, %s\n", p, d, i,
195 +                              mpfr_print_rnd_mode ((mpfr_rnd_t) r));
196 +                      printf ("x = ");
197 +                      mpfr_dump (x);
198 +                      printf ("y = ");
199 +                      mpfr_dump (y);
200 +                      printf ("Expected "); mpfr_dump (z1);
201 +                      printf ("  with inex = %d\n", inex1);
202 +                      printf ("Got      "); mpfr_dump (z2);
203 +                      printf ("  with inex = %d\n", inex2);
204 +                      exit (1);
205 +                    }
206 +                }
207 +              if (i == 0)
208 +                mpfr_nextabove (y);
209 +              else
210 +                {
211 +                  if (p < 6)
212 +                    break;
213 +                  mpfr_nextbelow (y);
214 +                  mpfr_mul_ui (y, y, 25, MPFR_RNDD);
215 +                  mpfr_div_2ui (y, y, 4, MPFR_RNDN);
216 +                }
217 +            }
218 +        }
219 +      mpfr_clears (x, y, z1, z2, (mpfr_ptr) 0);
220 +    }
223  #define TEST_FUNCTION test_sub
224  #define TWO_ARGS
225  #define RAND_FUNCTION(x) mpfr_random2(x, MPFR_LIMB_SIZE (x), randlimb () % 100, RANDS)
226 @@ -962,6 +1096,7 @@
227    check_inexact ();
228    check_max_almosteven ();
229    bug_ddefour ();
230 +  bug20180217 ();
231    for (p=2; p<200; p++)
232      for (i=0; i<50; i++)
233        check_two_sum (p);
234 diff -Naurd mpfr-4.0.1-a/tests/tsub1sp.c mpfr-4.0.1-b/tests/tsub1sp.c
235 --- mpfr-4.0.1-a/tests/tsub1sp.c        2018-01-09 12:30:58.000000000 +0000
236 +++ mpfr-4.0.1-b/tests/tsub1sp.c        2018-04-27 12:40:46.858268585 +0000
237 @@ -284,6 +284,91 @@
238      }
241 +static void
242 +coverage (void)
244 +  mpfr_t a, b, c, d, u;
245 +  int inex;
247 +  /* coverage test in mpfr_sub1sp: case d=1, limb > MPFR_LIMB_HIGHBIT, RNDF
248 +     and also RNDZ */
249 +  mpfr_init2 (a, 3 * GMP_NUMB_BITS);
250 +  mpfr_init2 (b, 3 * GMP_NUMB_BITS);
251 +  mpfr_init2 (c, 3 * GMP_NUMB_BITS);
252 +  mpfr_init2 (d, 3 * GMP_NUMB_BITS);
253 +  mpfr_init2 (u, 3 * GMP_NUMB_BITS);
254 +  mpfr_set_ui (b, 1, MPFR_RNDN);
255 +  mpfr_nextbelow (b); /* b = 1 - 2^(-p) */
256 +  mpfr_set_prec (c, GMP_NUMB_BITS);
257 +  mpfr_set_ui_2exp (c, 1, -1, MPFR_RNDN);
258 +  mpfr_nextbelow (c);
259 +  mpfr_nextbelow (c); /* c = 1/2 - 2*2^(-GMP_NUMB_BITS-1) */
260 +  mpfr_prec_round (c, 3 * GMP_NUMB_BITS, MPFR_RNDN);
261 +  mpfr_nextbelow (c); /* c = 1/2 - 2*2^(-GMP_NUMB_BITS-1) - 2^(-p-1) */
262 +  /* b-c = c */
263 +  mpfr_sub (a, b, c, MPFR_RNDF);
264 +  mpfr_sub (d, b, c, MPFR_RNDD);
265 +  mpfr_sub (u, b, c, MPFR_RNDU);
266 +  /* check a = d or u */
267 +  MPFR_ASSERTN(mpfr_equal_p (a, d) || mpfr_equal_p (a, u));
269 +  /* coverage test in mpfr_sub1sp: case d=p, RNDN, sb = 0, significand of b
270 +     is even but b<>2^e, (case 1e) */
271 +  mpfr_set_prec (a, 3 * GMP_NUMB_BITS);
272 +  mpfr_set_prec (b, 3 * GMP_NUMB_BITS);
273 +  mpfr_set_prec (c, 3 * GMP_NUMB_BITS);
274 +  mpfr_set_ui (b, 1, MPFR_RNDN);
275 +  mpfr_nextabove (b);
276 +  mpfr_nextabove (b);
277 +  mpfr_set_ui_2exp (c, 1, -3 * GMP_NUMB_BITS, MPFR_RNDN);
278 +  inex = mpfr_sub (a, b, c, MPFR_RNDN);
279 +  MPFR_ASSERTN(inex > 0);
280 +  MPFR_ASSERTN(mpfr_equal_p (a, b));
282 +  mpfr_clear (a);
283 +  mpfr_clear (b);
284 +  mpfr_clear (c);
285 +  mpfr_clear (d);
286 +  mpfr_clear (u);
289 +/* bug in mpfr_sub1sp1n, made generic */
290 +static void
291 +bug20180217 (mpfr_prec_t pmax)
293 +  mpfr_t a, b, c;
294 +  int inex;
295 +  mpfr_prec_t p;
297 +  for (p = MPFR_PREC_MIN; p <= pmax; p++)
298 +    {
299 +      mpfr_init2 (a, p);
300 +      mpfr_init2 (b, p);
301 +      mpfr_init2 (c, p);
302 +      mpfr_set_ui (b, 1, MPFR_RNDN); /* b = 1 */
303 +      mpfr_set_ui_2exp (c, 1, -p-1, MPFR_RNDN); /* c = 2^(-p-1) */
304 +      /* a - b = 1 - 2^(-p-1) and should be rounded to 1 (case 2f of
305 +         mpfr_sub1sp) */
306 +      inex = mpfr_sub (a, b, c, MPFR_RNDN);
307 +      MPFR_ASSERTN(inex > 0);
308 +      MPFR_ASSERTN(mpfr_cmp_ui (a, 1) == 0);
309 +      /* check also when a=b */
310 +      mpfr_set_ui (a, 1, MPFR_RNDN);
311 +      inex = mpfr_sub (a, a, c, MPFR_RNDN);
312 +      MPFR_ASSERTN(inex > 0);
313 +      MPFR_ASSERTN(mpfr_cmp_ui (a, 1) == 0);
314 +      /* and when a=c */
315 +      mpfr_set_ui (b, 1, MPFR_RNDN); /* b = 1 */
316 +      mpfr_set_ui_2exp (a, 1, -p-1, MPFR_RNDN);
317 +      inex = mpfr_sub (a, b, a, MPFR_RNDN);
318 +      MPFR_ASSERTN(inex > 0);
319 +      MPFR_ASSERTN(mpfr_cmp_ui (a, 1) == 0);
320 +      mpfr_clear (a);
321 +      mpfr_clear (b);
322 +      mpfr_clear (c);
323 +    }
326  int
327  main (void)
329 @@ -291,6 +376,8 @@
331    tests_start_mpfr ();
333 +  bug20180217 (1024);
334 +  coverage ();
335    compare_sub_sub1sp ();
336    test20170208 ();
337    bug20170109 ();
338 diff -Naurd mpfr-4.0.1-a/PATCHES mpfr-4.0.1-b/PATCHES
339 --- mpfr-4.0.1-a/PATCHES        2018-04-27 12:45:53.139452673 +0000
340 +++ mpfr-4.0.1-b/PATCHES        2018-04-27 12:45:53.171452379 +0000
341 @@ -0,0 +1 @@
342 +fma
343 diff -Naurd mpfr-4.0.1-a/VERSION mpfr-4.0.1-b/VERSION
344 --- mpfr-4.0.1-a/VERSION        2018-04-27 12:40:46.870268475 +0000
345 +++ mpfr-4.0.1-b/VERSION        2018-04-27 12:45:53.171452379 +0000
346 @@ -1 +1 @@
347 -4.0.1-p1
348 +4.0.1-p2
349 diff -Naurd mpfr-4.0.1-a/src/fma.c mpfr-4.0.1-b/src/fma.c
350 --- mpfr-4.0.1-a/src/fma.c      2018-01-09 12:30:58.000000000 +0000
351 +++ mpfr-4.0.1-b/src/fma.c      2018-04-27 12:45:53.159452489 +0000
352 @@ -225,194 +225,73 @@
354        if (MPFR_IS_INF (u))  /* overflow */
355          {
356 +          int sign_u = MPFR_SIGN (u);
358            MPFR_LOG_MSG (("Overflow on x*y\n", 0));
359 +          MPFR_GROUP_CLEAR (group);  /* we no longer need u */
361            /* Let's eliminate the obvious case where x*y and z have the
362               same sign. No possible cancellation -> real overflow.
363               Also, we know that |z| < 2^emax. If E(x) + E(y) >= emax+3,
364 -             then |x*y| >= 2^(emax+1), and |x*y + z| >= 2^emax. This case
365 +             then |x*y| >= 2^(emax+1), and |x*y + z| > 2^emax. This case
366               is also an overflow. */
367 -          if (MPFR_SIGN (u) == MPFR_SIGN (z) || e >= __gmpfr_emax + 3)
368 +          if (sign_u == MPFR_SIGN (z) || e >= __gmpfr_emax + 3)
369              {
370 -              MPFR_GROUP_CLEAR (group);
371                MPFR_SAVE_EXPO_FREE (expo);
372 -              return mpfr_overflow (s, rnd_mode, MPFR_SIGN (z));
373 +              return mpfr_overflow (s, rnd_mode, sign_u);
374              }
376 -          /* E(x) + E(y) <= emax+2, therefore |x*y| < 2^(emax+2), and
377 -             (x/4)*y does not overflow (let's recall that the result
378 -             is exact with an unbounded exponent range). It does not
379 -             underflow either, because x*y overflows and the exponent
380 -             range is large enough. */
381 -          inexact = mpfr_div_2ui (u, x, 2, MPFR_RNDN);
382 -          MPFR_ASSERTN (inexact == 0);
383 -          inexact = mpfr_mul (u, u, y, MPFR_RNDN);
384 -          MPFR_ASSERTN (inexact == 0);
386 -          /* Now, we need to add z/4... But it may underflow! */
387 -          {
388 -            mpfr_t zo4;
389 -            mpfr_srcptr zz;
390 -            MPFR_BLOCK_DECL (flags);
392 -            if (MPFR_GET_EXP (u) > MPFR_GET_EXP (z) &&
393 -                MPFR_GET_EXP (u) - MPFR_GET_EXP (z) > MPFR_PREC (u))
394 -              {
395 -                /* |z| < ulp(u)/2, therefore one can use z instead of z/4. */
396 -                zz = z;
397 -              }
398 -            else
399 -              {
400 -                mpfr_init2 (zo4, MPFR_PREC (z));
401 -                if (mpfr_div_2ui (zo4, z, 2, MPFR_RNDZ))
402 -                  {
403 -                    /* The division by 4 underflowed! */
404 -                    MPFR_ASSERTN (0); /* TODO... */
405 -                  }
406 -                zz = zo4;
407 -              }
409 -            /* Let's recall that u = x*y/4 and zz = z/4 (or z if the
410 -               following addition would give the same result). */
411 -            MPFR_BLOCK (flags, inexact = mpfr_add (s, u, zz, rnd_mode));
412 -            /* u and zz have different signs, so that an overflow
413 -               is not possible. But an underflow is theoretically
414 -               possible! */
415 -            if (MPFR_UNDERFLOW (flags))
416 -              {
417 -                MPFR_ASSERTN (zz != z);
418 -                MPFR_ASSERTN (0); /* TODO... */
419 -                mpfr_clears (zo4, u, (mpfr_ptr) 0);
420 -              }
421 -            else
422 -              {
423 -                int inex2;
425 -                if (zz != z)
426 -                  mpfr_clear (zo4);
427 -                MPFR_GROUP_CLEAR (group);
428 -                MPFR_ASSERTN (! MPFR_OVERFLOW (flags));
429 -                inex2 = mpfr_mul_2ui (s, s, 2, rnd_mode);
430 -                if (inex2)  /* overflow */
431 -                  {
432 -                    inexact = inex2;
433 -                    MPFR_SAVE_EXPO_UPDATE_FLAGS (expo, __gmpfr_flags);
434 -                  }
435 -                goto end;
436 -              }
437 -          }
438          }
439 -      else  /* underflow: one has |xy| < 2^(emin-1). */
440 +      else  /* underflow: one has |x*y| < 2^(emin-1). */
441          {
442 -          unsigned long scale = 0;
443 -          mpfr_t scaled_z;
444 -          mpfr_srcptr new_z;
445 -          mpfr_exp_t diffexp;
446 -          mpfr_prec_t pzs;
447 -          int xy_underflows;
449            MPFR_LOG_MSG (("Underflow on x*y\n", 0));
451 -          /* Let's scale z so that ulp(z) > 2^emin and ulp(s) > 2^emin
452 -             (the + 1 on MPFR_PREC (s) is necessary because the exponent
453 -             of the result can be EXP(z) - 1). */
454 -          diffexp = MPFR_GET_EXP (z) - __gmpfr_emin;
455 -          pzs = MAX (MPFR_PREC (z), MPFR_PREC (s) + 1);
456 -          MPFR_LOG_MSG (("diffexp=%" MPFR_EXP_FSPEC "d pzs=%Pd\n",
457 -                         diffexp, pzs));
458 -          if (diffexp <= pzs)
459 -            {
460 -              mpfr_uexp_t uscale;
461 -              mpfr_t scaled_v;
462 -              MPFR_BLOCK_DECL (flags);
464 -              uscale = (mpfr_uexp_t) pzs - diffexp + 1;
465 -              MPFR_ASSERTN (uscale > 0);
466 -              MPFR_ASSERTN (uscale <= ULONG_MAX);
467 -              scale = uscale;
468 -              mpfr_init2 (scaled_z, MPFR_PREC (z));
469 -              inexact = mpfr_mul_2ui (scaled_z, z, scale, MPFR_RNDN);
470 -              MPFR_ASSERTN (inexact == 0);  /* TODO: overflow case */
471 -              new_z = scaled_z;
472 -              /* Now we need to recompute u = xy * 2^scale. */
473 -              MPFR_BLOCK (flags,
474 -                          if (MPFR_GET_EXP (x) < MPFR_GET_EXP (y))
475 -                            {
476 -                              mpfr_init2 (scaled_v, precx);
477 -                              mpfr_mul_2ui (scaled_v, x, scale, MPFR_RNDN);
478 -                              mpfr_mul (u, scaled_v, y, MPFR_RNDN);
479 -                            }
480 -                          else
481 -                            {
482 -                              mpfr_init2 (scaled_v, precy);
483 -                              mpfr_mul_2ui (scaled_v, y, scale, MPFR_RNDN);
484 -                              mpfr_mul (u, x, scaled_v, MPFR_RNDN);
485 -                            });
486 -              mpfr_clear (scaled_v);
487 -              MPFR_ASSERTN (! MPFR_OVERFLOW (flags));
488 -              xy_underflows = MPFR_UNDERFLOW (flags);
489 -            }
490 -          else
491 -            {
492 -              new_z = z;
493 -              xy_underflows = 1;
494 -            }
496 -          MPFR_LOG_MSG (("scale=%lu xy_underflows=%d\n",
497 -                         scale, xy_underflows));
499 -          if (xy_underflows)
500 +          /* Easy cases: when 2^(emin-1) <= 1/2 * min(ulp(z),ulp(s)),
501 +             one can replace x*y by sign(x*y) * 2^(emin-1). Note that
502 +             this is even true in case of equality for MPFR_RNDN thanks
503 +             to the even-rounding rule.
504 +             The + 1 on MPFR_PREC (s) is necessary because the exponent
505 +             of the result can be EXP(z) - 1. */
506 +          if (MPFR_GET_EXP (z) - __gmpfr_emin >=
507 +              MAX (MPFR_PREC (z), MPFR_PREC (s) + 1))
508              {
509 -              /* Let's replace xy by sign(xy) * 2^(emin-1). */
510                MPFR_PREC (u) = MPFR_PREC_MIN;
511                mpfr_setmin (u, __gmpfr_emin);
512                MPFR_SET_SIGN (u, MPFR_MULT_SIGN (MPFR_SIGN (x),
513                                                  MPFR_SIGN (y)));
514 +              mpfr_clear_flags ();
515 +              goto add;
516              }
518 -          {
519 -            MPFR_BLOCK_DECL (flags);
520 +          MPFR_GROUP_CLEAR (group);  /* we no longer need u */
521 +        }
523 -            MPFR_BLOCK (flags, inexact = mpfr_add (s, u, new_z, rnd_mode));
524 -            MPFR_LOG_MSG (("inexact=%d\n", inexact));
525 -            MPFR_GROUP_CLEAR (group);
526 -            if (scale != 0)
527 -              {
528 -                int inex2;
529 +      /* Let's use UBF to resolve the overflow/underflow issues. */
530 +      {
531 +        mpfr_ubf_t uu;
532 +        mp_size_t un;
533 +        mpfr_limb_ptr up;
534 +        MPFR_TMP_DECL(marker);
536 -                mpfr_clear (scaled_z);
537 -                /* Here an overflow is theoretically possible, in which case
538 -                   the result may be wrong, hence the assert. An underflow
539 -                   is not possible, but let's check that anyway. */
540 -                MPFR_ASSERTN (! MPFR_OVERFLOW (flags));  /* TODO... */
541 -                MPFR_ASSERTN (! MPFR_UNDERFLOW (flags));  /* not possible */
542 -                if (rnd_mode == MPFR_RNDN &&
543 -                    MPFR_GET_EXP (s) == __gmpfr_emin - 1 + scale &&
544 -                    mpfr_powerof2_raw (s))
545 -                  {
546 -                    MPFR_LOG_MSG (("Double rounding\n", 0));
547 -                    rnd_mode = (MPFR_IS_NEG (s) ? inexact <= 0 : inexact >= 0)
548 -                      ? MPFR_RNDZ : MPFR_RNDA;
549 -                  }
550 -                inex2 = mpfr_div_2ui (s, s, scale, rnd_mode);
551 -                MPFR_LOG_MSG (("inex2=%d\n", inex2));
552 -                if (inex2)  /* underflow */
553 -                  inexact = inex2;
554 -              }
555 -          }
556 +        MPFR_LOG_MSG (("Use UBF\n", 0));
558 -          /* FIXME/TODO: I'm not sure that the following is correct.
559 -             Check for possible spurious exceptions due to intermediate
560 -             computations. */
561 -          MPFR_SAVE_EXPO_UPDATE_FLAGS (expo, __gmpfr_flags);
562 -          goto end;
563 -        }
564 +        MPFR_TMP_MARK (marker);
565 +        un = MPFR_LIMB_SIZE (x) + MPFR_LIMB_SIZE (y);
566 +        MPFR_TMP_INIT (up, uu, (mpfr_prec_t) un * GMP_NUMB_BITS, un);
567 +        mpfr_ubf_mul_exact (uu, x, y);
568 +        mpfr_clear_flags ();
569 +        inexact = mpfr_add (s, (mpfr_srcptr) uu, z, rnd_mode);
570 +        MPFR_UBF_CLEAR_EXP (uu);
571 +        MPFR_TMP_FREE (marker);
572 +      }
573 +    }
574 +  else
575 +    {
576 +    add:
577 +      inexact = mpfr_add (s, u, z, rnd_mode);
578 +      MPFR_GROUP_CLEAR (group);
579      }
581 -  inexact = mpfr_add (s, u, z, rnd_mode);
582 -  MPFR_GROUP_CLEAR (group);
583    MPFR_SAVE_EXPO_UPDATE_FLAGS (expo, __gmpfr_flags);
584 - end:
585    MPFR_SAVE_EXPO_FREE (expo);
586    return mpfr_check_range (s, inexact, rnd_mode);
588 diff -Naurd mpfr-4.0.1-a/src/mpfr.h mpfr-4.0.1-b/src/mpfr.h
589 --- mpfr-4.0.1-a/src/mpfr.h     2018-04-27 12:40:46.870268475 +0000
590 +++ mpfr-4.0.1-b/src/mpfr.h     2018-04-27 12:45:53.171452379 +0000
591 @@ -27,7 +27,7 @@
592  #define MPFR_VERSION_MAJOR 4
593  #define MPFR_VERSION_MINOR 0
594  #define MPFR_VERSION_PATCHLEVEL 1
595 -#define MPFR_VERSION_STRING "4.0.1-p1"
596 +#define MPFR_VERSION_STRING "4.0.1-p2"
598  /* User macros:
599     MPFR_USE_FILE:        Define it to make MPFR define functions dealing
600 diff -Naurd mpfr-4.0.1-a/src/version.c mpfr-4.0.1-b/src/version.c
601 --- mpfr-4.0.1-a/src/version.c  2018-04-27 12:40:46.870268475 +0000
602 +++ mpfr-4.0.1-b/src/version.c  2018-04-27 12:45:53.171452379 +0000
603 @@ -25,5 +25,5 @@
604  const char *
605  mpfr_get_version (void)
607 -  return "4.0.1-p1";
608 +  return "4.0.1-p2";
610 diff -Naurd mpfr-4.0.1-a/tests/tfma.c mpfr-4.0.1-b/tests/tfma.c
611 --- mpfr-4.0.1-a/tests/tfma.c   2018-01-09 12:30:58.000000000 +0000
612 +++ mpfr-4.0.1-b/tests/tfma.c   2018-04-27 12:45:53.163452452 +0000
613 @@ -196,6 +196,238 @@
616  static void
617 +test_overflow3 (void)
619 +  mpfr_t x, y, z, r;
620 +  int inex;
621 +  mpfr_prec_t p = 8;
622 +  mpfr_flags_t ex_flags = MPFR_FLAGS_OVERFLOW | MPFR_FLAGS_INEXACT, flags;
623 +  int i, j, k;
624 +  unsigned int neg;
626 +  mpfr_inits2 (p, x, y, z, (mpfr_ptr) 0);
627 +  for (i = 0; i < 2; i++)
628 +    {
629 +      mpfr_init2 (r, 2 * p + i);
630 +      mpfr_set_ui_2exp (x, 1, mpfr_get_emax () - 1, MPFR_RNDN);
631 +      mpfr_set_ui (y, 2, MPFR_RNDN);       /* y = 2 */
632 +      for (j = 1; j <= 2; j++)
633 +        for (k = 0; k <= 1; k++)
634 +          {
635 +            mpfr_set_si_2exp (z, -1, mpfr_get_emax () - mpfr_get_prec (r) - j,
636 +                              MPFR_RNDN);
637 +            if (k)
638 +              mpfr_nextabove (z);
639 +            for (neg = 0; neg <= 3; neg++)
640 +              {
641 +                mpfr_clear_flags ();
642 +                /* (The following applies for neg = 0 or 2, all the signs
643 +                   need to be reversed for neg = 1 or 3.)
644 +                   We have x*y = 2^emax and
645 +                   z = - 2^(emax-2p-i-j) * (1-k*2^(-p)), thus
646 +                   x*y+z = 2^emax - 2^(emax-2p-i-j) + k*2^(emax-3p-i-j)
647 +                   should overflow. Indeed it is >= the midpoint of
648 +                   2^emax - 2^(emax-2p-i) and 2^emax, the midpoint
649 +                   being obtained for j = 1 and k = 0. */
650 +                inex = mpfr_fma (r, x, y, z, MPFR_RNDN);
651 +                flags = __gmpfr_flags;
652 +                if (! mpfr_inf_p (r) || flags != ex_flags ||
653 +                    ((neg & 1) == 0 ?
654 +                     (inex <= 0 || MPFR_IS_NEG (r)) :
655 +                     (inex >= 0 || MPFR_IS_POS (r))))
656 +                  {
657 +                    printf ("Error in test_overflow3 for "
658 +                            "i=%d j=%d k=%d neg=%u\n", i, j, k, neg);
659 +                    printf ("Expected %c@Inf@\n  with inex %c 0 and flags:",
660 +                            (neg & 1) == 0 ? '+' : '-',
661 +                            (neg & 1) == 0 ? '>' : '<');
662 +                    flags_out (ex_flags);
663 +                    printf ("Got      ");
664 +                    mpfr_dump (r);
665 +                    printf ("  with inex = %d and flags:", inex);
666 +                    flags_out (flags);
667 +                    exit (1);
668 +                  }
669 +                if (neg == 0 || neg == 2)
670 +                  mpfr_neg (x, x, MPFR_RNDN);
671 +                if (neg == 1 || neg == 3)
672 +                  mpfr_neg (y, y, MPFR_RNDN);
673 +                mpfr_neg (z, z, MPFR_RNDN);
674 +              }  /* neg */
675 +          }  /* k */
676 +      mpfr_clear (r);
677 +    }  /* i */
678 +  mpfr_clears (x, y, z, (mpfr_ptr) 0);
681 +static void
682 +test_overflow4 (void)
684 +  mpfr_t x, y, z, r1, r2;
685 +  mpfr_exp_t emax, e;
686 +  mpfr_prec_t px;
687 +  mpfr_flags_t flags1, flags2;
688 +  int inex1, inex2;
689 +  int ei, i, j;
690 +  int below;
691 +  unsigned int neg;
693 +  emax = mpfr_get_emax ();
695 +  mpfr_init2 (y, MPFR_PREC_MIN);
696 +  mpfr_set_ui (y, 2, MPFR_RNDN);  /* y = 2 */
698 +  mpfr_init2 (z, 8);
700 +  for (px = 17; px < 256; px *= 2)
701 +    {
702 +      mpfr_init2 (x, px);
703 +      mpfr_inits2 (px - 8, r1, r2, (mpfr_ptr) 0);
704 +      for (ei = 0; ei <= 1; ei++)
705 +        {
706 +          e = ei ? emax : 0;
707 +          mpfr_set_ui_2exp (x, 1, e - 1, MPFR_RNDN);
708 +          mpfr_nextabove (x);  /* x = 2^(e - 1) + 2^(e - px) */
709 +          /* x*y = 2^e + 2^(e - px + 1), which internally overflows
710 +             when e = emax. */
711 +          for (i = -4; i <= 4; i++)
712 +            for (j = 2; j <= 3; j++)
713 +              {
714 +                mpfr_set_si_2exp (z, -j, e - px + i, MPFR_RNDN);
715 +                /* If |z| <= 2^(e - px + 1), then x*y + z >= 2^e and
716 +                   RZ(x*y + z) = 2^e with an unbounded exponent range.
717 +                   If |z| > 2^(e - px + 1), then RZ(x*y + z) is the
718 +                   predecessor of 2^e (since |z| < ulp(r)/2); this
719 +                   occurs when i > 0 and when i = 0 and j > 2 */
720 +                mpfr_set_ui_2exp (r1, 1, e - 1, MPFR_RNDN);
721 +                below = i > 0 || (i == 0 && j > 2);
722 +                if (below)
723 +                  mpfr_nextbelow (r1);
724 +                mpfr_clear_flags ();
725 +                inex1 = mpfr_mul_2ui (r1, r1, 1, MPFR_RNDZ);
726 +                if (below || e < emax)
727 +                  {
728 +                    inex1 = i == 0 && j == 2 ? 0 : -1;
729 +                    flags1 = inex1 ? MPFR_FLAGS_INEXACT : 0;
730 +                  }
731 +                else
732 +                  {
733 +                    MPFR_ASSERTN (inex1 < 0);
734 +                    flags1 = MPFR_FLAGS_INEXACT | MPFR_FLAGS_OVERFLOW;
735 +                    MPFR_ASSERTN (flags1 == __gmpfr_flags);
736 +                  }
737 +                for (neg = 0; neg <= 3; neg++)
738 +                  {
739 +                    mpfr_clear_flags ();
740 +                    inex2 = mpfr_fma (r2, x, y, z, MPFR_RNDZ);
741 +                    flags2 = __gmpfr_flags;
742 +                    if (! (mpfr_equal_p (r1, r2) &&
743 +                           SAME_SIGN (inex1, inex2) &&
744 +                           flags1 == flags2))
745 +                      {
746 +                        printf ("Error in test_overflow4 for "
747 +                                "px=%d ei=%d i=%d j=%d neg=%u\n",
748 +                                (int) px, ei, i, j, neg);
749 +                        printf ("Expected ");
750 +                        mpfr_dump (r1);
751 +                        printf ("with inex = %d and flags:", inex1);
752 +                        flags_out (flags1);
753 +                        printf ("Got      ");
754 +                        mpfr_dump (r2);
755 +                        printf ("with inex = %d and flags:", inex2);
756 +                        flags_out (flags2);
757 +                        exit (1);
758 +                      }
759 +                    if (neg == 0 || neg == 2)
760 +                      mpfr_neg (x, x, MPFR_RNDN);
761 +                    if (neg == 1 || neg == 3)
762 +                      mpfr_neg (y, y, MPFR_RNDN);
763 +                    mpfr_neg (z, z, MPFR_RNDN);
764 +                    mpfr_neg (r1, r1, MPFR_RNDN);
765 +                    inex1 = - inex1;
766 +                  }
767 +              }
768 +        }
769 +      mpfr_clears (x, r1, r2, (mpfr_ptr) 0);
770 +    }
772 +  mpfr_clears (y, z, (mpfr_ptr) 0);
775 +static void
776 +test_overflow5 (void)
778 +  mpfr_t x, y, z, r1, r2;
779 +  mpfr_exp_t emax;
780 +  int inex1, inex2;
781 +  int i, rnd;
782 +  unsigned int neg, negr;
784 +  emax = mpfr_get_emax ();
786 +  mpfr_init2 (x, 123);
787 +  mpfr_init2 (y, 45);
788 +  mpfr_init2 (z, 67);
789 +  mpfr_inits2 (89, r1, r2, (mpfr_ptr) 0);
791 +  mpfr_set_ui_2exp (x, 1, emax - 1, MPFR_RNDN);
793 +  for (i = 3; i <= 17; i++)
794 +    {
795 +      mpfr_set_ui (y, i, MPFR_RNDN);
796 +      mpfr_set_ui_2exp (z, 1, emax - 1, MPFR_RNDN);
797 +      for (neg = 0; neg < 8; neg++)
798 +        {
799 +          mpfr_setsign (x, x, neg & 1, MPFR_RNDN);
800 +          mpfr_setsign (y, y, neg & 2, MPFR_RNDN);
801 +          mpfr_setsign (z, z, neg & 4, MPFR_RNDN);
803 +          /* |x*y + z| = (i +/- 1) * 2^(emax - 1) >= 2^emax (overflow)
804 +             and x*y + z has the same sign as x*y. */
805 +          negr = (neg ^ (neg >> 1)) & 1;
807 +          RND_LOOP (rnd)
808 +            {
809 +              mpfr_set_inf (r1, 1);
810 +              if (MPFR_IS_LIKE_RNDZ ((mpfr_rnd_t) rnd, negr))
811 +                {
812 +                  mpfr_nextbelow (r1);
813 +                  inex1 = -1;
814 +                }
815 +              else
816 +                inex1 = 1;
818 +              if (negr)
819 +                {
820 +                  mpfr_neg (r1, r1, MPFR_RNDN);
821 +                  inex1 = - inex1;
822 +                }
824 +              mpfr_clear_flags ();
825 +              inex2 = mpfr_fma (r2, x, y, z, (mpfr_rnd_t) rnd);
826 +              MPFR_ASSERTN (__gmpfr_flags ==
827 +                            (MPFR_FLAGS_INEXACT | MPFR_FLAGS_OVERFLOW));
829 +              if (! (mpfr_equal_p (r1, r2) && SAME_SIGN (inex1, inex2)))
830 +                {
831 +                  printf ("Error in test_overflow5 for i=%d neg=%u %s\n",
832 +                          i, neg, mpfr_print_rnd_mode ((mpfr_rnd_t) rnd));
833 +                  printf ("Expected ");
834 +                  mpfr_dump (r1);
835 +                  printf ("with inex = %d\n", inex1);
836 +                  printf ("Got      ");
837 +                  mpfr_dump (r2);
838 +                  printf ("with inex = %d\n", inex2);
839 +                  exit (1);
840 +                }
841 +            }  /* rnd */
842 +        }  /* neg */
843 +    }  /* i */
845 +  mpfr_clears (x, y, z, r1, r2, (mpfr_ptr) 0);
848 +static void
849  test_underflow1 (void)
851    mpfr_t x, y, z, r;
852 @@ -281,59 +513,128 @@
853  static void
854  test_underflow2 (void)
856 -  mpfr_t x, y, z, r;
857 -  int b, i, inex, same, err = 0;
858 +  mpfr_t x, y, z, r1, r2;
859 +  int e, b, i, prec = 32, pz, inex;
860 +  unsigned int neg;
862 -  mpfr_inits2 (32, x, y, z, r, (mpfr_ptr) 0);
863 +  mpfr_init2 (x, MPFR_PREC_MIN);
864 +  mpfr_inits2 (prec, y, z, r1, r2, (mpfr_ptr) 0);
866 -  mpfr_set_si_2exp (z, 1, mpfr_get_emin (), MPFR_RNDN);   /* z = 2^emin */
867 -  mpfr_set_si_2exp (x, 1, mpfr_get_emin (), MPFR_RNDN);   /* x = 2^emin */
868 +  mpfr_set_si_2exp (x, 1, mpfr_get_emin () - 1, MPFR_RNDN);
869 +  /* x = 2^(emin-1) */
871 -  for (b = 0; b <= 1; b++)
872 +  for (e = -1; e <= prec + 2; e++)
873      {
874 -      for (i = 15; i <= 17; i++)
875 +      mpfr_set (z, x, MPFR_RNDN);
876 +      /* z = x = 2^(emin+e) */
877 +      for (b = 0; b <= 1; b++)
878          {
879 -          mpfr_set_si_2exp (y, i, -4 - MPFR_PREC (z), MPFR_RNDN);
880 -          /*  z = 1.000...00b
881 -           * xy =            01111
882 -           *   or            10000
883 -           *   or            10001
884 -           */
885 -          mpfr_clear_flags ();
886 -          inex = mpfr_fma (r, x, y, z, MPFR_RNDN);
887 -#define STRTU2 "Error in test_underflow2 (b = %d, i = %d)\n  "
888 -          if (__gmpfr_flags != MPFR_FLAGS_INEXACT)
889 -            {
890 -              printf (STRTU2 "flags = %u instead of %u\n", b, i,
891 -                      (unsigned int) __gmpfr_flags,
892 -                      (unsigned int) MPFR_FLAGS_INEXACT);
893 -              err = 1;
894 -            }
895 -          same = i == 15 || (i == 16 && b == 0);
896 -          if (same ? (inex >= 0) : (inex <= 0))
897 -            {
898 -              printf (STRTU2 "incorrect ternary value (%d instead of %c 0)\n",
899 -                      b, i, inex, same ? '<' : '>');
900 -              err = 1;
901 -            }
902 -          mpfr_set (y, z, MPFR_RNDN);
903 -          if (!same)
904 -            mpfr_nextabove (y);
905 -          if (! mpfr_equal_p (r, y))
906 +          for (pz = prec - 4 * (b == 0); pz <= prec + 4; pz++)
907              {
908 -              printf (STRTU2 "expected ", b, i);
909 -              mpfr_dump (y);
910 -              printf ("  got      ");
911 -              mpfr_dump (r);
912 -              err = 1;
913 -            }
914 -        }
915 -      mpfr_nextabove (z);
916 -    }
917 +              inex = mpfr_prec_round (z, pz, MPFR_RNDZ);
918 +              MPFR_ASSERTN (inex == 0);
919 +              for (i = 15; i <= 17; i++)
920 +                {
921 +                  mpfr_flags_t flags1, flags2;
922 +                  int inex1, inex2;
924 -  if (err)
925 -    exit (1);
926 -  mpfr_clears (x, y, z, r, (mpfr_ptr) 0);
927 +                  mpfr_set_si_2exp (y, i, -4 - prec, MPFR_RNDN);
929 +                  /*      <--- r --->
930 +                   *  z = 1.000...00b   with b = 0 or 1
931 +                   * xy =            01111  (i = 15)
932 +                   *   or            10000  (i = 16)
933 +                   *   or            10001  (i = 17)
934 +                   *
935 +                   * x, y, and z will be modified to test the different sign
936 +                   * combinations. In the case b = 0 (i.e. |z| is a power of
937 +                   * 2) and x*y has a different sign from z, then y will be
938 +                   * divided by 2, so that i = 16 corresponds to a midpoint.
939 +                   */
941 +                  for (neg = 0; neg < 8; neg++)
942 +                    {
943 +                      int xyneg, prev_binade;
945 +                      mpfr_setsign (x, x, neg & 1, MPFR_RNDN);
946 +                      mpfr_setsign (y, y, neg & 2, MPFR_RNDN);
947 +                      mpfr_setsign (z, z, neg & 4, MPFR_RNDN);
949 +                      xyneg = (neg ^ (neg >> 1)) & 1;  /* true iff x*y < 0 */
951 +                      /* If a change of binade occurs by adding x*y to z
952 +                         exactly, then take into account the fact that the
953 +                         midpoint has a different exponent. */
954 +                      prev_binade = b == 0 && (xyneg ^ MPFR_IS_NEG (z));
955 +                      if (prev_binade)
956 +                        mpfr_div_2ui (y, y, 1, MPFR_RNDN);
958 +                      mpfr_set (r1, z, MPFR_RNDN);
959 +                      flags1 = MPFR_FLAGS_INEXACT;
961 +                      if (e == -1 && i == 17 && b == 0 &&
962 +                          (xyneg ^ (neg >> 2)) != 0)
963 +                        {
964 +                          /* Special underflow case. */
965 +                          flags1 |= MPFR_FLAGS_UNDERFLOW;
966 +                          inex1 = xyneg ? 1 : -1;
967 +                        }
968 +                      else if (i == 15 || (i == 16 && b == 0))
969 +                        {
970 +                          /* round toward z */
971 +                          inex1 = xyneg ? 1 : -1;
972 +                        }
973 +                      else if (xyneg)
974 +                        {
975 +                          /* round away from z, with x*y < 0 */
976 +                          mpfr_nextbelow (r1);
977 +                          inex1 = -1;
978 +                        }
979 +                      else
980 +                        {
981 +                          /* round away from z, with x*y > 0 */
982 +                          mpfr_nextabove (r1);
983 +                          inex1 = 1;
984 +                        }
986 +                      mpfr_clear_flags ();
987 +                      inex2 = mpfr_fma (r2, x, y, z, MPFR_RNDN);
988 +                      flags2 = __gmpfr_flags;
990 +                      if (! (mpfr_equal_p (r1, r2) &&
991 +                             SAME_SIGN (inex1, inex2) &&
992 +                             flags1 == flags2))
993 +                        {
994 +                          printf ("Error in test_underflow2 for "
995 +                                  "e=%d b=%d pz=%d i=%d neg=%u\n",
996 +                                  e, b, pz, i, neg);
997 +                          printf ("Expected ");
998 +                          mpfr_dump (r1);
999 +                          printf ("with inex = %d and flags:", inex1);
1000 +                          flags_out (flags1);
1001 +                          printf ("Got      ");
1002 +                          mpfr_dump (r2);
1003 +                          printf ("with inex = %d and flags:", inex2);
1004 +                          flags_out (flags2);
1005 +                          exit (1);
1006 +                        }
1008 +                      /* Restore y. */
1009 +                      if (prev_binade)
1010 +                        mpfr_mul_2ui (y, y, 1, MPFR_RNDN);
1011 +                    }  /* neg */
1012 +                }  /* i */
1013 +            }  /* pz */
1015 +          inex = mpfr_prec_round (z, prec, MPFR_RNDZ);
1016 +          MPFR_ASSERTN (inex == 0);
1017 +          MPFR_SET_POS (z);
1018 +          mpfr_nextabove (z);
1019 +        }  /* b */
1020 +      mpfr_mul_2ui (x, x, 1, MPFR_RNDN);
1021 +    }  /* e */
1023 +  mpfr_clears (x, y, z, r1, r2, (mpfr_ptr) 0);
1026  static void
1027 @@ -397,6 +698,185 @@
1028    mpfr_clears (x, y, z, t1, t2, (mpfr_ptr) 0);
1031 +/* Test s = x*y + z with PREC(z) > PREC(s) + 1, x*y underflows, where
1032 +   z + x*y and z + sign(x*y) * 2^(emin-1) do not give the same result.
1033 +     x = 2^emin
1034 +     y = 2^(-8)
1035 +     z = 2^emin * (2^PREC(s) + k - 2^(-1))
1036 +   with k = 3 for MPFR_RNDN and k = 2 for the directed rounding modes.
1037 +   Also test the opposite versions with neg != 0.
1039 +static void
1040 +test_underflow4 (void)
1042 +  mpfr_t x, y, z, s1, s2;
1043 +  mpfr_prec_t ps = 32;
1044 +  int inex, rnd;
1046 +  mpfr_inits2 (MPFR_PREC_MIN, x, y, (mpfr_ptr) 0);
1047 +  mpfr_inits2 (ps, s1, s2, (mpfr_ptr) 0);
1048 +  mpfr_init2 (z, ps + 2);
1050 +  inex = mpfr_set_si_2exp (x, 1, mpfr_get_emin (), MPFR_RNDN);
1051 +  MPFR_ASSERTN (inex == 0);
1052 +  inex = mpfr_set_si_2exp (y, 1, -8, MPFR_RNDN);
1053 +  MPFR_ASSERTN (inex == 0);
1055 +  RND_LOOP_NO_RNDF (rnd)
1056 +    {
1057 +      mpfr_flags_t flags1, flags2;
1058 +      int inex1, inex2;
1059 +      unsigned int neg;
1061 +      inex = mpfr_set_si_2exp (z, 1 << 1, ps, MPFR_RNDN);
1062 +      MPFR_ASSERTN (inex == 0);
1063 +      inex = mpfr_sub_ui (z, z, 1, MPFR_RNDN);
1064 +      MPFR_ASSERTN (inex == 0);
1065 +      inex = mpfr_div_2ui (z, z, 1, MPFR_RNDN);
1066 +      MPFR_ASSERTN (inex == 0);
1067 +      inex = mpfr_add_ui (z, z, rnd == MPFR_RNDN ? 3 : 2, MPFR_RNDN);
1068 +      MPFR_ASSERTN (inex == 0);
1069 +      inex = mpfr_mul (z, z, x, MPFR_RNDN);
1070 +      MPFR_ASSERTN (inex == 0);
1072 +      for (neg = 0; neg <= 3; neg++)
1073 +        {
1074 +          inex1 = mpfr_set (s1, z, (mpfr_rnd_t) rnd);
1075 +          flags1 = MPFR_FLAGS_INEXACT;
1077 +          mpfr_clear_flags ();
1078 +          inex2 = mpfr_fma (s2, x, y, z, (mpfr_rnd_t) rnd);
1079 +          flags2 = __gmpfr_flags;
1081 +          if (! (mpfr_equal_p (s1, s2) &&
1082 +                 SAME_SIGN (inex1, inex2) &&
1083 +                 flags1 == flags2))
1084 +            {
1085 +              printf ("Error in test_underflow4 for neg=%u %s\n",
1086 +                      neg, mpfr_print_rnd_mode ((mpfr_rnd_t) rnd));
1087 +              printf ("Expected ");
1088 +              mpfr_dump (s1);
1089 +              printf ("  with inex ~ %d, flags =", inex1);
1090 +              flags_out (flags1);
1091 +              printf ("Got      ");
1092 +              mpfr_dump (s2);
1093 +              printf ("  with inex ~ %d, flags =", inex2);
1094 +              flags_out (flags2);
1095 +              exit (1);
1096 +            }
1098 +          if (neg == 0 || neg == 2)
1099 +            mpfr_neg (x, x, MPFR_RNDN);
1100 +          if (neg == 1 || neg == 3)
1101 +            mpfr_neg (y, y, MPFR_RNDN);
1102 +          mpfr_neg (z, z, MPFR_RNDN);
1103 +        }
1104 +    }
1106 +  mpfr_clears (x, y, z, s1, s2, (mpfr_ptr) 0);
1109 +/* Test s = x*y + z on:
1110 +     x = +/- 2^emin
1111 +     y = +/- 2^(-3)
1112 +     z = +/- 2^(emin + PREC(s)) and MPFR numbers close to this value.
1113 +   with PREC(z) from PREC(s) - 2 to PREC(s) + 8.
1115 +static void
1116 +test_underflow5 (void)
1118 +  mpfr_t w, x, y, z, s1, s2, t;
1119 +  mpfr_exp_t emin;
1120 +  mpfr_prec_t ps = 32;
1121 +  int inex, i, j, rnd;
1122 +  unsigned int neg;
1124 +  mpfr_inits2 (MPFR_PREC_MIN, w, x, y, (mpfr_ptr) 0);
1125 +  mpfr_inits2 (ps, s1, s2, (mpfr_ptr) 0);
1126 +  mpfr_init2 (t, ps + 9);
1128 +  emin = mpfr_get_emin ();
1130 +  inex = mpfr_set_si_2exp (w, 1, emin, MPFR_RNDN);  /* w = 2^emin */
1131 +  MPFR_ASSERTN (inex == 0);
1132 +  inex = mpfr_set_si (x, 1, MPFR_RNDN);
1133 +  MPFR_ASSERTN (inex == 0);
1134 +  inex = mpfr_set_si_2exp (y, 1, -3, MPFR_RNDN);
1135 +  MPFR_ASSERTN (inex == 0);
1137 +  for (i = -2; i <= 8; i++)
1138 +    {
1139 +      mpfr_init2 (z, ps + i);
1140 +      inex = mpfr_set_si_2exp (z, 1, ps, MPFR_RNDN);
1141 +      MPFR_ASSERTN (inex == 0);
1143 +      for (j = 1; j <= 32; j++)
1144 +        mpfr_nextbelow (z);
1146 +      for (j = -32; j <= 32; j++)
1147 +        {
1148 +          for (neg = 0; neg < 8; neg++)
1149 +            {
1150 +              mpfr_setsign (x, x, neg & 1, MPFR_RNDN);
1151 +              mpfr_setsign (y, y, neg & 2, MPFR_RNDN);
1152 +              mpfr_setsign (z, z, neg & 4, MPFR_RNDN);
1154 +              inex = mpfr_fma (t, x, y, z, MPFR_RNDN);
1155 +              MPFR_ASSERTN (inex == 0);
1157 +              inex = mpfr_mul (x, x, w, MPFR_RNDN);
1158 +              MPFR_ASSERTN (inex == 0);
1159 +              inex = mpfr_mul (z, z, w, MPFR_RNDN);
1160 +              MPFR_ASSERTN (inex == 0);
1162 +              RND_LOOP_NO_RNDF (rnd)
1163 +                {
1164 +                  mpfr_flags_t flags1, flags2;
1165 +                  int inex1, inex2;
1167 +                  mpfr_clear_flags ();
1168 +                  inex1 = mpfr_mul (s1, w, t, (mpfr_rnd_t) rnd);
1169 +                  flags1 = __gmpfr_flags;
1171 +                  mpfr_clear_flags ();
1172 +                  inex2 = mpfr_fma (s2, x, y, z, (mpfr_rnd_t) rnd);
1173 +                  flags2 = __gmpfr_flags;
1175 +                  if (! (mpfr_equal_p (s1, s2) &&
1176 +                         SAME_SIGN (inex1, inex2) &&
1177 +                         flags1 == flags2))
1178 +                    {
1179 +                      printf ("Error in test_underflow5 on "
1180 +                              "i=%d j=%d neg=%u %s\n", i, j, neg,
1181 +                              mpfr_print_rnd_mode ((mpfr_rnd_t) rnd));
1182 +                      printf ("Expected ");
1183 +                      mpfr_dump (s1);
1184 +                      printf ("  with inex ~ %d, flags =", inex1);
1185 +                      flags_out (flags1);
1186 +                      printf ("Got      ");
1187 +                      mpfr_dump (s2);
1188 +                      printf ("  with inex ~ %d, flags =", inex2);
1189 +                      flags_out (flags2);
1190 +                      exit (1);
1191 +                    }
1192 +                }  /* rnd */
1194 +              inex = mpfr_div (x, x, w, MPFR_RNDN);
1195 +              MPFR_ASSERTN (inex == 0);
1196 +              inex = mpfr_div (z, z, w, MPFR_RNDN);
1197 +              MPFR_ASSERTN (inex == 0);
1198 +            }  /* neg */
1200 +          MPFR_SET_POS (z);  /* restore the value before the loop on neg */
1201 +          mpfr_nextabove (z);
1202 +        }  /* j */
1204 +      mpfr_clear (z);
1205 +    }  /* i */
1207 +  mpfr_clears (w, x, y, s1, s2, t, (mpfr_ptr) 0);
1210  static void
1211  bug20101018 (void)
1213 @@ -533,6 +1013,7 @@
1215    mpfr_t x, y, z, s;
1216    mpfr_exp_t emin, emax;
1217 +  int i;
1219    tests_start_mpfr ();
1221 @@ -823,21 +1304,39 @@
1223    test_exact ();
1225 -  test_overflow1 ();
1226 -  test_overflow2 ();
1227 -  test_underflow1 ();
1228 -  test_underflow2 ();
1229 -  test_underflow3 (1);
1230 +  for (i = 0; i <= 2; i++)
1231 +    {
1232 +      if (i == 0)
1233 +        {
1234 +          /* corresponds to the generic code + mpfr_check_range */
1235 +          set_emin (-1024);
1236 +          set_emax (1024);
1237 +        }
1238 +      else if (i == 1)
1239 +        {
1240 +          set_emin (MPFR_EMIN_MIN);
1241 +          set_emax (MPFR_EMAX_MAX);
1242 +        }
1243 +      else
1244 +        {
1245 +          MPFR_ASSERTN (i == 2);
1246 +          if (emin == MPFR_EMIN_MIN && emax == MPFR_EMAX_MAX)
1247 +            break;
1248 +          set_emin (emin);
1249 +          set_emax (emax);
1250 +        }
1252 -  set_emin (MPFR_EMIN_MIN);
1253 -  set_emax (MPFR_EMAX_MAX);
1254 -  test_overflow1 ();
1255 -  test_overflow2 ();
1256 -  test_underflow1 ();
1257 -  test_underflow2 ();
1258 -  test_underflow3 (2);
1259 -  set_emin (emin);
1260 -  set_emax (emax);
1261 +      test_overflow1 ();
1262 +      test_overflow2 ();
1263 +      test_overflow3 ();
1264 +      test_overflow4 ();
1265 +      test_overflow5 ();
1266 +      test_underflow1 ();
1267 +      test_underflow2 ();
1268 +      test_underflow3 (i);
1269 +      test_underflow4 ();
1270 +      test_underflow5 ();
1271 +    }
1273    tests_end_mpfr ();
1274    return 0;
1275 diff -Naurd mpfr-4.0.1-a/PATCHES mpfr-4.0.1-b/PATCHES
1276 --- mpfr-4.0.1-a/PATCHES        2018-04-27 12:47:54.194308761 +0000
1277 +++ mpfr-4.0.1-b/PATCHES        2018-04-27 12:47:54.230308407 +0000
1278 @@ -0,0 +1 @@
1279 +sqr_1n-underflow
1280 diff -Naurd mpfr-4.0.1-a/VERSION mpfr-4.0.1-b/VERSION
1281 --- mpfr-4.0.1-a/VERSION        2018-04-27 12:45:53.171452379 +0000
1282 +++ mpfr-4.0.1-b/VERSION        2018-04-27 12:47:54.226308446 +0000
1283 @@ -1 +1 @@
1284 -4.0.1-p2
1285 +4.0.1-p3
1286 diff -Naurd mpfr-4.0.1-a/src/mpfr.h mpfr-4.0.1-b/src/mpfr.h
1287 --- mpfr-4.0.1-a/src/mpfr.h     2018-04-27 12:45:53.171452379 +0000
1288 +++ mpfr-4.0.1-b/src/mpfr.h     2018-04-27 12:47:54.226308446 +0000
1289 @@ -27,7 +27,7 @@
1290  #define MPFR_VERSION_MAJOR 4
1291  #define MPFR_VERSION_MINOR 0
1292  #define MPFR_VERSION_PATCHLEVEL 1
1293 -#define MPFR_VERSION_STRING "4.0.1-p2"
1294 +#define MPFR_VERSION_STRING "4.0.1-p3"
1296  /* User macros:
1297     MPFR_USE_FILE:        Define it to make MPFR define functions dealing
1298 diff -Naurd mpfr-4.0.1-a/src/sqr.c mpfr-4.0.1-b/src/sqr.c
1299 --- mpfr-4.0.1-a/src/sqr.c      2018-01-09 12:30:58.000000000 +0000
1300 +++ mpfr-4.0.1-b/src/sqr.c      2018-04-27 12:47:54.218308525 +0000
1301 @@ -161,15 +161,18 @@
1302    if (MPFR_UNLIKELY(ax < __gmpfr_emin))
1303      {
1304        /* As seen in mpfr_mul_1, we cannot have a0 = 111...111 here if there
1305 -         was not exponent decrease (ax--) above.
1306 -         In the case of an exponent decrease, it is not possible for
1307 -         GMP_NUMB_BITS=32 since the largest b0 such that b0^2 < 2^(2*32-1)
1308 -         is b0=3037000499, but its square has only 30 leading ones.
1309 -         For GMP_NUMB_BITS=64 it is possible: the largest b0 is
1310 -         13043817825332782212, and its square has 64 leading ones. */
1311 -      if ((ax == __gmpfr_emin - 1) && (ap[0] == ~MPFR_LIMB_HIGHBIT) &&
1312 -          ((rnd_mode == MPFR_RNDN && rb) ||
1313 -           (MPFR_IS_LIKE_RNDA(rnd_mode, MPFR_IS_NEG (a)) && (rb | sb))))
1314 +         was not an exponent decrease (ax--) above.
1315 +         In the case of an exponent decrease:
1316 +         - For GMP_NUMB_BITS=32, a0 = 111...111 is not possible since the
1317 +           largest b0 such that b0^2 < 2^(2*32-1) is b0=3037000499, but
1318 +           its square has only 30 leading ones.
1319 +         - For GMP_NUMB_BITS=64, a0 = 111...111 is possible: the largest b0
1320 +           is 13043817825332782212, and its square has 64 leading ones; but
1321 +           since the next bit is rb=0, for RNDN, we always have an underflow.
1322 +         For the test below, note that a is positive.
1323 +      */
1324 +      if (ax == __gmpfr_emin - 1 && ap[0] == MPFR_LIMB_MAX &&
1325 +          MPFR_IS_LIKE_RNDA (rnd_mode, 0))
1326          goto rounding; /* no underflow */
1327        /* For RNDN, mpfr_underflow always rounds away, thus for |a| <= 2^(emin-2)
1328           we have to change to RNDZ. This corresponds to:
1329 diff -Naurd mpfr-4.0.1-a/src/version.c mpfr-4.0.1-b/src/version.c
1330 --- mpfr-4.0.1-a/src/version.c  2018-04-27 12:45:53.171452379 +0000
1331 +++ mpfr-4.0.1-b/src/version.c  2018-04-27 12:47:54.226308446 +0000
1332 @@ -25,5 +25,5 @@
1333  const char *
1334  mpfr_get_version (void)
1336 -  return "4.0.1-p2";
1337 +  return "4.0.1-p3";
1339 diff -Naurd mpfr-4.0.1-a/tests/tsqr.c mpfr-4.0.1-b/tests/tsqr.c
1340 --- mpfr-4.0.1-a/tests/tsqr.c   2018-01-09 12:30:58.000000000 +0000
1341 +++ mpfr-4.0.1-b/tests/tsqr.c   2018-04-27 12:47:54.218308525 +0000
1342 @@ -188,6 +188,156 @@
1343  #endif
1346 +static void
1347 +coverage (mpfr_prec_t pmax)
1349 +  mpfr_prec_t p;
1351 +  for (p = MPFR_PREC_MIN; p <= pmax; p++)
1352 +    {
1353 +      mpfr_t a, b, c;
1354 +      int inex;
1355 +      mpfr_exp_t emin;
1357 +      mpfr_init2 (a, p);
1358 +      mpfr_init2 (b, p);
1359 +      mpfr_init2 (c, p);
1361 +      /* exercise carry in most significant bits of a, with overflow */
1362 +      mpfr_set_ui_2exp (b, 1, mpfr_get_emax (), MPFR_RNDZ);
1363 +      mpfr_sqrt (b, b, MPFR_RNDU);
1364 +      mpfr_div_2exp (c, b, 1, MPFR_RNDN);
1365 +      mpfr_sqr (c, c, MPFR_RNDN);
1366 +      mpfr_clear_flags ();
1367 +      inex = mpfr_sqr (a, b, MPFR_RNDN);
1368 +      /* if EXP(c) > emax-2, there is overflow */
1369 +      if (mpfr_get_exp (c) > mpfr_get_emax () - 2)
1370 +        {
1371 +          MPFR_ASSERTN(inex > 0);
1372 +          MPFR_ASSERTN(mpfr_inf_p (a) && mpfr_sgn (a) > 0);
1373 +          MPFR_ASSERTN(mpfr_overflow_p ());
1374 +        }
1375 +      else /* no overflow */
1376 +        {
1377 +          /* 2^p-1 is a square only for p=1 */
1378 +          MPFR_ASSERTN((p == 1 && inex == 0) || (p > 1 && inex < 0));
1379 +          MPFR_ASSERTN(!mpfr_overflow_p ());
1380 +          mpfr_set_ui_2exp (c, 1, mpfr_get_emax (), MPFR_RNDZ);
1381 +          MPFR_ASSERTN(mpfr_equal_p (a, c));
1382 +        }
1384 +      /* same as above, with RNDU */
1385 +      mpfr_set_ui_2exp (b, 1, mpfr_get_emax (), MPFR_RNDZ);
1386 +      mpfr_sqrt (b, b, MPFR_RNDU);
1387 +      mpfr_div_2exp (c, b, 1, MPFR_RNDN);
1388 +      mpfr_sqr (c, c, MPFR_RNDU);
1389 +      mpfr_clear_flags ();
1390 +      inex = mpfr_sqr (a, b, MPFR_RNDU);
1391 +      /* if EXP(c) > emax-2, there is overflow */
1392 +      if (mpfr_get_exp (c) > mpfr_get_emax () - 2)
1393 +        {
1394 +          MPFR_ASSERTN(inex > 0);
1395 +          MPFR_ASSERTN(mpfr_inf_p (a) && mpfr_sgn (a) > 0);
1396 +          MPFR_ASSERTN(mpfr_overflow_p ());
1397 +        }
1398 +      else /* no overflow */
1399 +        {
1400 +          /* 2^p-1 is a square only for p=1 */
1401 +          MPFR_ASSERTN((p == 1 && inex == 0) || (p > 1 && inex < 0));
1402 +          MPFR_ASSERTN(!mpfr_overflow_p ());
1403 +          mpfr_set_ui_2exp (c, 1, mpfr_get_emax (), MPFR_RNDZ);
1404 +          MPFR_ASSERTN(mpfr_equal_p (a, c));
1405 +        }
1407 +      /* exercise trivial overflow */
1408 +      mpfr_set_ui_2exp (b, 1, mpfr_get_emax (), MPFR_RNDZ);
1409 +      mpfr_sqrt (b, b, MPFR_RNDU);
1410 +      mpfr_mul_2exp (b, b, 1, MPFR_RNDN);
1411 +      mpfr_clear_flags ();
1412 +      inex = mpfr_sqr (a, b, MPFR_RNDN);
1413 +      MPFR_ASSERTN(inex > 0);
1414 +      MPFR_ASSERTN(mpfr_inf_p (a) && mpfr_sgn (a) > 0);
1415 +      MPFR_ASSERTN(mpfr_overflow_p ());
1417 +      /* exercise trivial underflow */
1418 +      mpfr_set_ui_2exp (b, 1, mpfr_get_emin () - 1, MPFR_RNDZ);
1419 +      mpfr_sqrt (b, b, MPFR_RNDU);
1420 +      mpfr_div_2exp (b, b, 1, MPFR_RNDN);
1421 +      mpfr_clear_flags ();
1422 +      inex = mpfr_sqr (a, b, MPFR_RNDN);
1423 +      MPFR_ASSERTN(inex < 0);
1424 +      MPFR_ASSERTN(mpfr_zero_p (a) && mpfr_signbit (a) == 0);
1425 +      MPFR_ASSERTN(mpfr_underflow_p ());
1427 +      /* exercise square between 0.5*2^emin and its predecessor (emin even) */
1428 +      emin = mpfr_get_emin ();
1429 +      mpfr_set_emin (emin + (emin & 1)); /* now emin is even */
1430 +      mpfr_set_ui_2exp (b, 1, mpfr_get_emin () - 1, MPFR_RNDN);
1431 +      inex = mpfr_sqrt (b, b, MPFR_RNDZ);
1432 +      MPFR_ASSERTN(inex != 0); /* sqrt(2) is not exact */
1433 +      mpfr_mul_2exp (c, b, 1, MPFR_RNDN);
1434 +      mpfr_sqr (c, c, MPFR_RNDN);
1435 +      mpfr_clear_flags ();
1436 +      inex = mpfr_sqr (a, b, MPFR_RNDN);
1437 +      if (mpfr_get_exp (c) < mpfr_get_emin () + 2) /* underflow */
1438 +        {
1439 +          /* if c > 0.5*2^(emin+1), we should round to 0.5*2^emin */
1440 +          if (mpfr_cmp_ui_2exp (c, 1, mpfr_get_emin ()) > 0)
1441 +            {
1442 +              MPFR_ASSERTN(inex > 0);
1443 +              MPFR_ASSERTN(mpfr_cmp_ui_2exp (a, 1, mpfr_get_emin () - 1) == 0);
1444 +              MPFR_ASSERTN(mpfr_underflow_p ());
1445 +            }
1446 +          else /* we should round to 0 */
1447 +            {
1448 +              MPFR_ASSERTN(inex < 0);
1449 +              MPFR_ASSERTN(mpfr_zero_p (a) && mpfr_signbit (a) == 0);
1450 +              MPFR_ASSERTN(mpfr_underflow_p ());
1451 +            }
1452 +        }
1453 +      else
1454 +        {
1455 +          MPFR_ASSERTN(inex > 0);
1456 +          MPFR_ASSERTN(mpfr_cmp_ui_2exp (a, 1, mpfr_get_emin () - 1) == 0);
1457 +          MPFR_ASSERTN(!mpfr_underflow_p ());
1458 +        }
1459 +      mpfr_set_emin (emin);
1461 +      /* exercise exact square root 2^(emin-2) for emin even */
1462 +      emin = mpfr_get_emin ();
1463 +      mpfr_set_emin (emin + (emin & 1)); /* now emin is even */
1464 +      mpfr_set_ui_2exp (b, 1, (mpfr_get_emin () - 2) / 2, MPFR_RNDN);
1465 +      inex = mpfr_sqr (a, b, MPFR_RNDN);
1466 +      MPFR_ASSERTN(inex < 0);
1467 +      MPFR_ASSERTN(mpfr_zero_p (a) && mpfr_signbit (a) == 0);
1468 +      MPFR_ASSERTN(mpfr_underflow_p ());
1469 +      mpfr_set_emin (emin);
1471 +      /* same as above, for RNDU */
1472 +      emin = mpfr_get_emin ();
1473 +      mpfr_set_emin (emin + (emin & 1)); /* now emin is even */
1474 +      mpfr_set_ui_2exp (b, 1, mpfr_get_emin () - 1, MPFR_RNDN);
1475 +      inex = mpfr_sqrt (b, b, MPFR_RNDZ);
1476 +      MPFR_ASSERTN(inex != 0); /* sqrt(2) is not exact */
1477 +      mpfr_mul_2exp (c, b, 1, MPFR_RNDN);
1478 +      mpfr_sqr (c, c, MPFR_RNDU);
1479 +      mpfr_clear_flags ();
1480 +      inex = mpfr_sqr (a, b, MPFR_RNDU);
1481 +      MPFR_ASSERTN(inex > 0);
1482 +      MPFR_ASSERTN(mpfr_cmp_ui_2exp (a, 1, mpfr_get_emin () - 1) == 0);
1483 +      /* we have underflow if c < 2^(emin+1) */
1484 +      if (mpfr_cmp_ui_2exp (c, 1, mpfr_get_emin () + 1) < 0)
1485 +        MPFR_ASSERTN(mpfr_underflow_p ());
1486 +      else
1487 +        MPFR_ASSERTN(!mpfr_underflow_p ());
1488 +      mpfr_set_emin (emin);
1490 +      mpfr_clear (a);
1491 +      mpfr_clear (b);
1492 +      mpfr_clear (c);
1493 +    }
1496  int
1497  main (void)
1499 @@ -195,6 +345,7 @@
1501    tests_start_mpfr ();
1503 +  coverage (1024);
1504    check_mpn_sqr ();
1505    check_special ();
1506    test_underflow ();
1507 diff -Naurd mpfr-4.0.1-a/PATCHES mpfr-4.0.1-b/PATCHES
1508 --- mpfr-4.0.1-a/PATCHES        2018-04-27 12:50:10.592974822 +0000
1509 +++ mpfr-4.0.1-b/PATCHES        2018-04-27 12:50:10.624974512 +0000
1510 @@ -0,0 +1 @@
1511 +get_str
1512 diff -Naurd mpfr-4.0.1-a/VERSION mpfr-4.0.1-b/VERSION
1513 --- mpfr-4.0.1-a/VERSION        2018-04-27 12:47:54.226308446 +0000
1514 +++ mpfr-4.0.1-b/VERSION        2018-04-27 12:50:10.624974512 +0000
1515 @@ -1 +1 @@
1516 -4.0.1-p3
1517 +4.0.1-p4
1518 diff -Naurd mpfr-4.0.1-a/doc/mpfr.info mpfr-4.0.1-b/doc/mpfr.info
1519 --- mpfr-4.0.1-a/doc/mpfr.info  2018-02-07 12:58:03.000000000 +0000
1520 +++ mpfr-4.0.1-b/doc/mpfr.info  2018-04-27 12:50:17.128911341 +0000
1521 @@ -1321,10 +1321,9 @@
1522            size_t N, mpfr_t OP, mpfr_rnd_t RND)
1523       Convert OP to a string of digits in base B, with rounding in the
1524       direction RND, where N is either zero (see below) or the number of
1525 -     significant digits output in the string; in the latter case, N must
1526 -     be greater or equal to 2.  The base may vary from 2 to 62;
1527 -     otherwise the function does nothing and immediately returns a null
1528 -     pointer.
1529 +     significant digits output in the string.  The base may vary from 2
1530 +     to 62; otherwise the function does nothing and immediately returns
1531 +     a null pointer.
1533       If the input is NaN, then the returned string is â€˜@NaN@’ and the
1534       NaN flag is set.  If the input is +Inf (resp. âˆ’Inf), then the
1535 @@ -4471,21 +4470,21 @@
1536  * mpfr_expm1:                            Special Functions.   (line  40)
1537  * mpfr_fac_ui:                           Special Functions.   (line 136)
1538  * mpfr_fits_intmax_p:                    Conversion Functions.
1539 -                                                              (line 168)
1540 +                                                              (line 167)
1541  * mpfr_fits_sint_p:                      Conversion Functions.
1542 -                                                              (line 164)
1543 +                                                              (line 163)
1544  * mpfr_fits_slong_p:                     Conversion Functions.
1545 -                                                              (line 162)
1546 +                                                              (line 161)
1547  * mpfr_fits_sshort_p:                    Conversion Functions.
1548 -                                                              (line 166)
1549 +                                                              (line 165)
1550  * mpfr_fits_uintmax_p:                   Conversion Functions.
1551 -                                                              (line 167)
1552 +                                                              (line 166)
1553  * mpfr_fits_uint_p:                      Conversion Functions.
1554 -                                                              (line 163)
1555 +                                                              (line 162)
1556  * mpfr_fits_ulong_p:                     Conversion Functions.
1557 -                                                              (line 161)
1558 +                                                              (line 160)
1559  * mpfr_fits_ushort_p:                    Conversion Functions.
1560 -                                                              (line 165)
1561 +                                                              (line 164)
1562  * mpfr_flags_clear:                      Exception Related Functions.
1563                                                                (line 190)
1564  * mpfr_flags_restore:                    Exception Related Functions.
1565 @@ -4520,7 +4519,7 @@
1566  * mpfr_free_cache2:                      Special Functions.   (line 295)
1567  * mpfr_free_pool:                        Special Functions.   (line 309)
1568  * mpfr_free_str:                         Conversion Functions.
1569 -                                                              (line 156)
1570 +                                                              (line 155)
1571  * mpfr_frexp:                            Conversion Functions.
1572                                                                (line  49)
1573  * mpfr_gamma:                            Special Functions.   (line 155)
1574 @@ -4928,30 +4927,30 @@
1575  Node: Assignment Functions\x7f47553
1576  Node: Combined Initialization and Assignment Functions\x7f57499
1577  Node: Conversion Functions\x7f58800
1578 -Node: Basic Arithmetic Functions\x7f69381
1579 -Node: Comparison Functions\x7f80277
1580 -Node: Special Functions\x7f83765
1581 -Node: Input and Output Functions\x7f101974
1582 -Node: Formatted Output Functions\x7f106751
1583 -Node: Integer and Remainder Related Functions\x7f116956
1584 -Node: Rounding-Related Functions\x7f124484
1585 -Node: Miscellaneous Functions\x7f131001
1586 -Node: Exception Related Functions\x7f141493
1587 -Node: Compatibility with MPF\x7f151733
1588 -Node: Custom Interface\x7f154679
1589 -Node: Internals\x7f159310
1590 -Node: API Compatibility\x7f160854
1591 -Node: Type and Macro Changes\x7f162802
1592 -Node: Added Functions\x7f165985
1593 -Node: Changed Functions\x7f170499
1594 -Node: Removed Functions\x7f177095
1595 -Node: Other Changes\x7f177825
1596 -Node: MPFR and the IEEE 754 Standard\x7f179526
1597 -Node: Contributors\x7f182143
1598 -Node: References\x7f185200
1599 -Node: GNU Free Documentation License\x7f187084
1600 -Node: Concept Index\x7f209677
1601 -Node: Function and Type Index\x7f216049
1602 +Node: Basic Arithmetic Functions\x7f69323
1603 +Node: Comparison Functions\x7f80219
1604 +Node: Special Functions\x7f83707
1605 +Node: Input and Output Functions\x7f101916
1606 +Node: Formatted Output Functions\x7f106693
1607 +Node: Integer and Remainder Related Functions\x7f116898
1608 +Node: Rounding-Related Functions\x7f124426
1609 +Node: Miscellaneous Functions\x7f130943
1610 +Node: Exception Related Functions\x7f141435
1611 +Node: Compatibility with MPF\x7f151675
1612 +Node: Custom Interface\x7f154621
1613 +Node: Internals\x7f159252
1614 +Node: API Compatibility\x7f160796
1615 +Node: Type and Macro Changes\x7f162744
1616 +Node: Added Functions\x7f165927
1617 +Node: Changed Functions\x7f170441
1618 +Node: Removed Functions\x7f177037
1619 +Node: Other Changes\x7f177767
1620 +Node: MPFR and the IEEE 754 Standard\x7f179468
1621 +Node: Contributors\x7f182085
1622 +Node: References\x7f185142
1623 +Node: GNU Free Documentation License\x7f187026
1624 +Node: Concept Index\x7f209619
1625 +Node: Function and Type Index\x7f215991
1626  \x1f
1627  End Tag Table
1629 diff -Naurd mpfr-4.0.1-a/doc/mpfr.texi mpfr-4.0.1-b/doc/mpfr.texi
1630 --- mpfr-4.0.1-a/doc/mpfr.texi  2018-02-07 12:50:31.000000000 +0000
1631 +++ mpfr-4.0.1-b/doc/mpfr.texi  2018-04-27 12:50:10.612974628 +0000
1632 @@ -1655,8 +1655,8 @@
1633  @deftypefun {char *} mpfr_get_str (char *@var{str}, mpfr_exp_t *@var{expptr}, int @var{b}, size_t @var{n}, mpfr_t @var{op}, mpfr_rnd_t @var{rnd})
1634  Convert @var{op} to a string of digits in base @var{b}, with rounding in
1635  the direction @var{rnd}, where @var{n} is either zero (see below) or the
1636 -number of significant digits output in the string; in the latter case,
1637 -@var{n} must be greater or equal to 2. The base may vary from 2 to 62;
1638 +number of significant digits output in the string.
1639 +The base may vary from 2 to 62;
1640  otherwise the function does nothing and immediately returns a null pointer.
1642  If the input is NaN, then the returned string is @samp{@@NaN@@} and the
1643 @@ -1699,8 +1699,7 @@
1644  but in some very rare cases, it might be @math{m+1}
1645  (the smallest case for bases up to 62 is when @var{p} equals 186564318007
1646  for bases 7 and 49).
1647 -@c In the source src/get_str.c, this is due to the approximate mpfr_ceil_mul,
1648 -@c but also m = 1 is changed to 2.
1649 +@c In the source src/get_str.c, this is due to the approximate mpfr_ceil_mul.
1651  If @var{str} is a null pointer, space for the significand is allocated using
1652  the allocation function (@pxref{Memory Handling}) and a pointer to the string
1653 diff -Naurd mpfr-4.0.1-a/src/get_str.c mpfr-4.0.1-b/src/get_str.c
1654 --- mpfr-4.0.1-a/src/get_str.c  2018-01-09 12:30:58.000000000 +0000
1655 +++ mpfr-4.0.1-b/src/get_str.c  2018-04-27 12:50:10.612974628 +0000
1656 @@ -2325,15 +2325,12 @@
1657        */
1658        m = 1 +
1659          mpfr_ceil_mul (IS_POW2(b) ? MPFR_PREC(x) - 1 : MPFR_PREC(x), b, 1);
1660 -      if (m < 2)
1661 -        m = 2;
1662      }
1664    MPFR_LOG_MSG (("m=%zu\n", m));
1666 -  /* The code below for non-power-of-two bases works for m=1;
1667 -     this is important for the internal use of mpfr_get_str. */
1668 -  MPFR_ASSERTN (m >= 2 || (!IS_POW2(b) && m >= 1));
1669 +  /* The code below works for m=1, both for power-of-two and non-power-of-two
1670 +     bases; this is important for the internal use of mpfr_get_str. */
1672    /* x is a floating-point number */
1674 @@ -2376,6 +2373,8 @@
1676        /* the first digit will contain only r bits */
1677        prec = (m - 1) * pow2 + r; /* total number of bits */
1678 +      /* if m=1 then 1 <= prec <= pow2, and since prec=1 is now valid in MPFR,
1679 +         the power-of-two code also works for m=1 */
1680        n = MPFR_PREC2LIMBS (prec);
1682        MPFR_TMP_MARK (marker);
1683 diff -Naurd mpfr-4.0.1-a/src/mpfr.h mpfr-4.0.1-b/src/mpfr.h
1684 --- mpfr-4.0.1-a/src/mpfr.h     2018-04-27 12:47:54.226308446 +0000
1685 +++ mpfr-4.0.1-b/src/mpfr.h     2018-04-27 12:50:10.620974551 +0000
1686 @@ -27,7 +27,7 @@
1687  #define MPFR_VERSION_MAJOR 4
1688  #define MPFR_VERSION_MINOR 0
1689  #define MPFR_VERSION_PATCHLEVEL 1
1690 -#define MPFR_VERSION_STRING "4.0.1-p3"
1691 +#define MPFR_VERSION_STRING "4.0.1-p4"
1693  /* User macros:
1694     MPFR_USE_FILE:        Define it to make MPFR define functions dealing
1695 diff -Naurd mpfr-4.0.1-a/src/version.c mpfr-4.0.1-b/src/version.c
1696 --- mpfr-4.0.1-a/src/version.c  2018-04-27 12:47:54.226308446 +0000
1697 +++ mpfr-4.0.1-b/src/version.c  2018-04-27 12:50:10.624974512 +0000
1698 @@ -25,5 +25,5 @@
1699  const char *
1700  mpfr_get_version (void)
1702 -  return "4.0.1-p3";
1703 +  return "4.0.1-p4";
1705 diff -Naurd mpfr-4.0.1-a/tests/tget_str.c mpfr-4.0.1-b/tests/tget_str.c
1706 --- mpfr-4.0.1-a/tests/tget_str.c       2018-01-09 12:30:58.000000000 +0000
1707 +++ mpfr-4.0.1-b/tests/tget_str.c       2018-04-27 12:50:10.612974628 +0000
1708 @@ -1267,6 +1267,41 @@
1710  #define ITER 1000
1712 +static void
1713 +coverage (void)
1715 +  mpfr_t x;
1716 +  char s[42];
1717 +  mpfr_exp_t e;
1718 +  int b = 3;
1719 +  size_t m = 40;
1721 +  mpfr_init2 (x, 128);
1723 +  /* exercise corner case in mpfr_get_str_aux: exact case (e < 0), where r
1724 +     rounds to a power of 2, and f is a multiple of GMP_NUMB_BITS */
1725 +  mpfr_set_ui_2exp (x, 1, 64, MPFR_RNDU);
1726 +  mpfr_nextbelow (x);
1727 +  /* x = 2^64 - 2^(-64) */
1728 +  mpfr_get_str (s, &e, b, m, x, MPFR_RNDU);
1729 +  /* s is the base-3 string for 6148914691236517206 (in base 10) */
1730 +  MPFR_ASSERTN(strcmp (s, "1111222002212212010121102012021021021200") == 0);
1731 +  MPFR_ASSERTN(e == 41);
1733 +  /* exercise corner case in mpfr_get_str: input is m=0, then it is changed
1734 +     to m=1 */
1735 +  mpfr_set_prec (x, 1);
1736 +  mpfr_set_ui (x, 1, MPFR_RNDN);
1737 +  mpfr_get_str (s, &e, 2, 0, x, MPFR_RNDN);
1738 +  MPFR_ASSERTN(strcmp (s, "1") == 0);
1739 +  MPFR_ASSERTN(e == 1);
1740 +  mpfr_get_str (s, &e, 2, 1, x, MPFR_RNDN);
1741 +  MPFR_ASSERTN(strcmp (s, "1") == 0);
1742 +  MPFR_ASSERTN(e == 1);
1744 +  mpfr_clear (x);
1747  int
1748  main (int argc, char *argv[])
1750 @@ -1281,6 +1316,7 @@
1752    tests_start_mpfr ();
1754 +  coverage ();
1755    check_small ();
1757    check_special (2, 2);
1758 diff -Naurd mpfr-4.0.1-a/PATCHES mpfr-4.0.1-b/PATCHES
1759 --- mpfr-4.0.1-a/PATCHES        2018-04-27 12:52:13.875783093 +0000
1760 +++ mpfr-4.0.1-b/PATCHES        2018-04-27 12:52:13.911782747 +0000
1761 @@ -0,0 +1 @@
1762 +cmp_q-special
1763 diff -Naurd mpfr-4.0.1-a/VERSION mpfr-4.0.1-b/VERSION
1764 --- mpfr-4.0.1-a/VERSION        2018-04-27 12:50:10.624974512 +0000
1765 +++ mpfr-4.0.1-b/VERSION        2018-04-27 12:52:13.911782747 +0000
1766 @@ -1 +1 @@
1767 -4.0.1-p4
1768 +4.0.1-p5
1769 diff -Naurd mpfr-4.0.1-a/src/gmp_op.c mpfr-4.0.1-b/src/gmp_op.c
1770 --- mpfr-4.0.1-a/src/gmp_op.c   2018-01-09 12:30:58.000000000 +0000
1771 +++ mpfr-4.0.1-b/src/gmp_op.c   2018-04-27 12:52:13.899782862 +0000
1772 @@ -452,11 +452,15 @@
1773    mpfr_prec_t p;
1774    MPFR_SAVE_EXPO_DECL (expo);
1776 -  if (MPFR_UNLIKELY (mpq_denref (q) == 0))
1777 +  if (MPFR_UNLIKELY (mpz_sgn (mpq_denref (q)) == 0))
1778      {
1779        /* q is an infinity or NaN */
1780 -      mpfr_init2 (t, 2);
1781 +      mpfr_flags_t old_flags;
1783 +      mpfr_init2 (t, MPFR_PREC_MIN);
1784 +      old_flags = __gmpfr_flags;
1785        mpfr_set_q (t, q, MPFR_RNDN);
1786 +      __gmpfr_flags = old_flags;
1787        res = mpfr_cmp (x, t);
1788        mpfr_clear (t);
1789        return res;
1790 diff -Naurd mpfr-4.0.1-a/src/mpfr.h mpfr-4.0.1-b/src/mpfr.h
1791 --- mpfr-4.0.1-a/src/mpfr.h     2018-04-27 12:50:10.620974551 +0000
1792 +++ mpfr-4.0.1-b/src/mpfr.h     2018-04-27 12:52:13.907782785 +0000
1793 @@ -27,7 +27,7 @@
1794  #define MPFR_VERSION_MAJOR 4
1795  #define MPFR_VERSION_MINOR 0
1796  #define MPFR_VERSION_PATCHLEVEL 1
1797 -#define MPFR_VERSION_STRING "4.0.1-p4"
1798 +#define MPFR_VERSION_STRING "4.0.1-p5"
1800  /* User macros:
1801     MPFR_USE_FILE:        Define it to make MPFR define functions dealing
1802 diff -Naurd mpfr-4.0.1-a/src/version.c mpfr-4.0.1-b/src/version.c
1803 --- mpfr-4.0.1-a/src/version.c  2018-04-27 12:50:10.624974512 +0000
1804 +++ mpfr-4.0.1-b/src/version.c  2018-04-27 12:52:13.911782747 +0000
1805 @@ -25,5 +25,5 @@
1806  const char *
1807  mpfr_get_version (void)
1809 -  return "4.0.1-p4";
1810 +  return "4.0.1-p5";
1812 diff -Naurd mpfr-4.0.1-a/tests/tgmpop.c mpfr-4.0.1-b/tests/tgmpop.c
1813 --- mpfr-4.0.1-a/tests/tgmpop.c 2018-01-09 12:30:58.000000000 +0000
1814 +++ mpfr-4.0.1-b/tests/tgmpop.c 2018-04-27 12:52:13.899782862 +0000
1815 @@ -307,16 +307,39 @@
1816    mpfr_init2 (z, MPFR_PREC_MIN);
1817    mpq_init (y);
1819 -  /* check the erange flag when x is NaN */
1820 +  /* Check the flags when x is NaN: the erange flags must be set, and
1821 +     only this one. */
1822    mpfr_set_nan (x);
1823    mpq_set_ui (y, 17, 1);
1824 -  mpfr_clear_erangeflag ();
1825 +  mpfr_clear_flags ();
1826    res1 = mpfr_cmp_q (x, y);
1827 -  if (res1 != 0 || mpfr_erangeflag_p () == 0)
1828 +  if (res1 != 0 || __gmpfr_flags != MPFR_FLAGS_ERANGE)
1829      {
1830        printf ("Error for mpfr_cmp_q (NaN, 17)\n");
1831        printf ("Return value: expected 0, got %d\n", res1);
1832 -      printf ("Erange flag: expected set, got %d\n", mpfr_erangeflag_p ());
1833 +      printf ("Expected flags:");
1834 +      flags_out (MPFR_FLAGS_ERANGE);
1835 +      printf ("Got flags:     ");
1836 +      flags_out (__gmpfr_flags);
1837 +      exit (1);
1838 +    }
1840 +  /* Check the flags when y is NaN: the erange flags must be set, and
1841 +     only this one. */
1842 +  mpfr_set_ui (x, 42, MPFR_RNDN);
1843 +  /* A NaN rational is represented by 0/0 (MPFR extension). */
1844 +  mpz_set_ui (mpq_numref (y), 0);
1845 +  mpz_set_ui (mpq_denref (y), 0);
1846 +  mpfr_clear_flags ();
1847 +  res1 = mpfr_cmp_q (x, y);
1848 +  if (res1 != 0 || __gmpfr_flags != MPFR_FLAGS_ERANGE)
1849 +    {
1850 +      printf ("Error for mpfr_cmp_q (42, NaN)\n");
1851 +      printf ("Return value: expected 0, got %d\n", res1);
1852 +      printf ("Expected flags:");
1853 +      flags_out (MPFR_FLAGS_ERANGE);
1854 +      printf ("Got flags:     ");
1855 +      flags_out (__gmpfr_flags);
1856        exit (1);
1857      }
1859 @@ -341,6 +364,55 @@
1860              }
1861          }
1862      }
1864 +  /* check for y = 1/0 */
1865 +  mpz_set_ui (mpq_numref (y), 1);
1866 +  mpz_set_ui (mpq_denref (y), 0);
1867 +  mpfr_set_ui (x, 1, MPFR_RNDN);
1868 +  MPFR_ASSERTN(mpfr_cmp_q (x, y) < 0);
1869 +  mpfr_set_inf (x, -1);
1870 +  MPFR_ASSERTN(mpfr_cmp_q (x, y) < 0);
1871 +  mpfr_set_inf (x, +1);
1872 +  MPFR_ASSERTN(mpfr_cmp_q (x, y) == 0);
1873 +  mpfr_set_nan (x);
1874 +  mpfr_clear_erangeflag ();
1875 +  MPFR_ASSERTN(mpfr_cmp_q (x, y) == 0);
1876 +  MPFR_ASSERTN(mpfr_erangeflag_p ());
1878 +  /* check for y = -1/0 */
1879 +  mpz_set_si (mpq_numref (y), -1);
1880 +  mpz_set_ui (mpq_denref (y), 0);
1881 +  mpfr_set_ui (x, 1, MPFR_RNDN);
1882 +  MPFR_ASSERTN(mpfr_cmp_q (x, y) > 0);
1883 +  mpfr_set_inf (x, -1);
1884 +  MPFR_ASSERTN(mpfr_cmp_q (x, y) == 0);
1885 +  mpfr_set_inf (x, +1);
1886 +  MPFR_ASSERTN(mpfr_cmp_q (x, y) > 0);
1887 +  mpfr_set_nan (x);
1888 +  mpfr_clear_erangeflag ();
1889 +  MPFR_ASSERTN(mpfr_cmp_q (x, y) == 0);
1890 +  MPFR_ASSERTN(mpfr_erangeflag_p ());
1892 +  /* check for y = 0/0 */
1893 +  mpz_set_ui (mpq_numref (y), 0);
1894 +  mpz_set_ui (mpq_denref (y), 0);
1895 +  mpfr_set_ui (x, 1, MPFR_RNDN);
1896 +  mpfr_clear_erangeflag ();
1897 +  MPFR_ASSERTN(mpfr_cmp_q (x, y) == 0);
1898 +  MPFR_ASSERTN(mpfr_erangeflag_p ());
1899 +  mpfr_set_inf (x, -1);
1900 +  mpfr_clear_erangeflag ();
1901 +  MPFR_ASSERTN(mpfr_cmp_q (x, y) == 0);
1902 +  MPFR_ASSERTN(mpfr_erangeflag_p ());
1903 +  mpfr_set_inf (x, +1);
1904 +  mpfr_clear_erangeflag ();
1905 +  MPFR_ASSERTN(mpfr_cmp_q (x, y) == 0);
1906 +  MPFR_ASSERTN(mpfr_erangeflag_p ());
1907 +  mpfr_set_nan (x);
1908 +  mpfr_clear_erangeflag ();
1909 +  MPFR_ASSERTN(mpfr_cmp_q (x, y) == 0);
1910 +  MPFR_ASSERTN(mpfr_erangeflag_p ());
1912    mpq_clear (y);
1913    mpfr_clear (x);
1914    mpfr_clear (z);
1915 diff -Naurd mpfr-4.0.1-a/PATCHES mpfr-4.0.1-b/PATCHES
1916 --- mpfr-4.0.1-a/PATCHES        2018-04-27 12:54:17.862594948 +0000
1917 +++ mpfr-4.0.1-b/PATCHES        2018-04-27 12:54:17.894594642 +0000
1918 @@ -0,0 +1 @@
1919 +io-null-stream
1920 diff -Naurd mpfr-4.0.1-a/VERSION mpfr-4.0.1-b/VERSION
1921 --- mpfr-4.0.1-a/VERSION        2018-04-27 12:52:13.911782747 +0000
1922 +++ mpfr-4.0.1-b/VERSION        2018-04-27 12:54:17.894594642 +0000
1923 @@ -1 +1 @@
1924 -4.0.1-p5
1925 +4.0.1-p6
1926 diff -Naurd mpfr-4.0.1-a/src/inp_str.c mpfr-4.0.1-b/src/inp_str.c
1927 --- mpfr-4.0.1-a/src/inp_str.c  2018-01-09 12:30:58.000000000 +0000
1928 +++ mpfr-4.0.1-b/src/inp_str.c  2018-04-27 12:54:17.882594757 +0000
1929 @@ -37,9 +37,6 @@
1930    int retval;
1931    size_t nread;
1933 -  if (stream == NULL)
1934 -    stream = stdin;
1936    alloc_size = 100;
1937    str = (unsigned char *) mpfr_allocate_func (alloc_size);
1938    str_size = 0;
1939 diff -Naurd mpfr-4.0.1-a/src/mpfr.h mpfr-4.0.1-b/src/mpfr.h
1940 --- mpfr-4.0.1-a/src/mpfr.h     2018-04-27 12:52:13.907782785 +0000
1941 +++ mpfr-4.0.1-b/src/mpfr.h     2018-04-27 12:54:17.894594642 +0000
1942 @@ -27,7 +27,7 @@
1943  #define MPFR_VERSION_MAJOR 4
1944  #define MPFR_VERSION_MINOR 0
1945  #define MPFR_VERSION_PATCHLEVEL 1
1946 -#define MPFR_VERSION_STRING "4.0.1-p5"
1947 +#define MPFR_VERSION_STRING "4.0.1-p6"
1949  /* User macros:
1950     MPFR_USE_FILE:        Define it to make MPFR define functions dealing
1951 diff -Naurd mpfr-4.0.1-a/src/out_str.c mpfr-4.0.1-b/src/out_str.c
1952 --- mpfr-4.0.1-a/src/out_str.c  2018-01-09 12:30:58.000000000 +0000
1953 +++ mpfr-4.0.1-b/src/out_str.c  2018-04-27 12:54:17.882594757 +0000
1954 @@ -43,10 +43,6 @@
1956    MPFR_ASSERTN (base >= 2 && base <= 62);
1958 -  /* when stream=NULL, output to stdout */
1959 -  if (stream == NULL)
1960 -    stream = stdout;
1962    if (MPFR_UNLIKELY (MPFR_IS_SINGULAR (op)))
1963      {
1964        if (MPFR_IS_NAN (op))
1965 diff -Naurd mpfr-4.0.1-a/src/version.c mpfr-4.0.1-b/src/version.c
1966 --- mpfr-4.0.1-a/src/version.c  2018-04-27 12:52:13.911782747 +0000
1967 +++ mpfr-4.0.1-b/src/version.c  2018-04-27 12:54:17.894594642 +0000
1968 @@ -25,5 +25,5 @@
1969  const char *
1970  mpfr_get_version (void)
1972 -  return "4.0.1-p5";
1973 +  return "4.0.1-p6";
1975 diff -Naurd mpfr-4.0.1-a/PATCHES mpfr-4.0.1-b/PATCHES
1976 --- mpfr-4.0.1-a/PATCHES        2018-07-10 15:29:07.937776370 +0000
1977 +++ mpfr-4.0.1-b/PATCHES        2018-07-10 15:29:08.017776303 +0000
1978 @@ -0,0 +1 @@
1979 +tstckintc-casts
1980 diff -Naurd mpfr-4.0.1-a/VERSION mpfr-4.0.1-b/VERSION
1981 --- mpfr-4.0.1-a/VERSION        2018-04-27 12:54:17.894594642 +0000
1982 +++ mpfr-4.0.1-b/VERSION        2018-07-10 15:29:08.017776303 +0000
1983 @@ -1 +1 @@
1984 -4.0.1-p6
1985 +4.0.1-p7
1986 diff -Naurd mpfr-4.0.1-a/src/mpfr.h mpfr-4.0.1-b/src/mpfr.h
1987 --- mpfr-4.0.1-a/src/mpfr.h     2018-04-27 12:54:17.894594642 +0000
1988 +++ mpfr-4.0.1-b/src/mpfr.h     2018-07-10 15:29:08.013776307 +0000
1989 @@ -27,7 +27,7 @@
1990  #define MPFR_VERSION_MAJOR 4
1991  #define MPFR_VERSION_MINOR 0
1992  #define MPFR_VERSION_PATCHLEVEL 1
1993 -#define MPFR_VERSION_STRING "4.0.1-p6"
1994 +#define MPFR_VERSION_STRING "4.0.1-p7"
1996  /* User macros:
1997     MPFR_USE_FILE:        Define it to make MPFR define functions dealing
1998 diff -Naurd mpfr-4.0.1-a/src/version.c mpfr-4.0.1-b/src/version.c
1999 --- mpfr-4.0.1-a/src/version.c  2018-04-27 12:54:17.894594642 +0000
2000 +++ mpfr-4.0.1-b/src/version.c  2018-07-10 15:29:08.017776303 +0000
2001 @@ -25,5 +25,5 @@
2002  const char *
2003  mpfr_get_version (void)
2005 -  return "4.0.1-p6";
2006 +  return "4.0.1-p7";
2008 diff -Naurd mpfr-4.0.1-a/tests/tstckintc.c mpfr-4.0.1-b/tests/tstckintc.c
2009 --- mpfr-4.0.1-a/tests/tstckintc.c      2018-01-09 12:30:58.000000000 +0000
2010 +++ mpfr-4.0.1-b/tests/tstckintc.c      2018-07-10 15:29:07.989776327 +0000
2011 @@ -32,6 +32,22 @@
2013  #define ALIGNED(s) (((s) + sizeof (long) - 1) / sizeof (long) * sizeof (long))
2015 +/* This code ensures alignment to "long". However, this might not be
2016 +   sufficient on some platforms. GCC's -Wcast-align=strict option can
2017 +   be useful, but this needs successive casts to help GCC, e.g.
2019 +   newx = (mpfr_ptr) (long *) (void *) old_stack;
2021 +   successively casts old_stack (of type char *) to
2022 +   - void *: avoid a false positive for the following cast to long *
2023 +     (as the code takes care of alignment to "long");
2024 +   - long *: this corresponds to the alignment checked by MPFR; coming
2025 +     from void *, it will not trigger a warning (even if incorrect);
2026 +   - mpfr_ptr: -Wcast-align=strict will emit a warning if mpfr_ptr has
2027 +     an alignment requirement stronger than long *. In such a case,
2028 +     the code will have to be fixed.
2031  static void *
2032  new_st (size_t s)
2034 @@ -94,12 +110,14 @@
2035    void *mantissa       = mpfr_custom_get_significand (x);
2036    size_t size_mantissa = mpfr_custom_get_size (mpfr_get_prec (x));
2037    mpfr_ptr newx;
2038 +  long *newx2;
2040    memmove (old_stack, x, sizeof (mpfr_t));
2041    memmove (old_stack + ALIGNED (sizeof (mpfr_t)), mantissa, size_mantissa);
2042 -  newx = (mpfr_ptr) old_stack;
2043 -  mpfr_custom_move (newx, old_stack + ALIGNED (sizeof (mpfr_t)));
2044 -  stack = old_stack + ALIGNED (sizeof (mpfr_t)) + ALIGNED (size_mantissa);
2045 +  newx = (mpfr_ptr) (long *) (void *) old_stack;
2046 +  newx2 = (long *) (void *) (old_stack + ALIGNED (sizeof (mpfr_t)));
2047 +  mpfr_custom_move (newx, newx2);
2048 +  stack = (char *) newx2 + ALIGNED (size_mantissa);
2049    return newx;
2052 @@ -113,7 +131,7 @@
2054    memmove (old_stack, x, sizeof (mpfr_t));
2055    memmove (old_stack + ALIGNED (sizeof (mpfr_t)), mantissa, size_mantissa);
2056 -  newx = (mpfr_ptr) old_stack;
2057 +  newx = (mpfr_ptr) (long *) (void *) old_stack;
2058    (mpfr_custom_move) (newx, old_stack + ALIGNED (sizeof (mpfr_t)));
2059    stack = old_stack + ALIGNED (sizeof (mpfr_t)) + ALIGNED (size_mantissa);
2060    return newx;
2061 @@ -127,7 +145,7 @@
2062    mpfr_ptr x, y;
2064    reset_stack ();
2065 -  org = (long *) stack;
2066 +  org = (long *) (void *) stack;
2068    x = new_mpfr (p);
2069    y = new_mpfr (p);
2070 @@ -277,7 +295,7 @@
2071    long *a, *b, *c;
2073    reset_stack ();
2074 -  org = (long *) stack;
2075 +  org = (long *) (void *) stack;
2077    a = dummy_set_si (42);
2078    b = dummy_set_si (17);
2079 diff -Naurd mpfr-4.0.1-a/PATCHES mpfr-4.0.1-b/PATCHES
2080 --- mpfr-4.0.1-a/PATCHES        2018-07-10 15:33:45.189532503 +0000
2081 +++ mpfr-4.0.1-b/PATCHES        2018-07-10 15:33:45.265532432 +0000
2082 @@ -0,0 +1 @@
2083 +set_d64-ternary
2084 diff -Naurd mpfr-4.0.1-a/VERSION mpfr-4.0.1-b/VERSION
2085 --- mpfr-4.0.1-a/VERSION        2018-07-10 15:29:08.017776303 +0000
2086 +++ mpfr-4.0.1-b/VERSION        2018-07-10 15:33:45.261532435 +0000
2087 @@ -1 +1 @@
2088 -4.0.1-p7
2089 +4.0.1-p8
2090 diff -Naurd mpfr-4.0.1-a/src/mpfr.h mpfr-4.0.1-b/src/mpfr.h
2091 --- mpfr-4.0.1-a/src/mpfr.h     2018-07-10 15:29:08.013776307 +0000
2092 +++ mpfr-4.0.1-b/src/mpfr.h     2018-07-10 15:33:45.261532435 +0000
2093 @@ -27,7 +27,7 @@
2094  #define MPFR_VERSION_MAJOR 4
2095  #define MPFR_VERSION_MINOR 0
2096  #define MPFR_VERSION_PATCHLEVEL 1
2097 -#define MPFR_VERSION_STRING "4.0.1-p7"
2098 +#define MPFR_VERSION_STRING "4.0.1-p8"
2100  /* User macros:
2101     MPFR_USE_FILE:        Define it to make MPFR define functions dealing
2102 diff -Naurd mpfr-4.0.1-a/src/set_d64.c mpfr-4.0.1-b/src/set_d64.c
2103 --- mpfr-4.0.1-a/src/set_d64.c  2018-01-09 12:30:58.000000000 +0000
2104 +++ mpfr-4.0.1-b/src/set_d64.c  2018-07-10 15:33:45.237532458 +0000
2105 @@ -425,7 +425,7 @@
2106                        1 character for terminating \0. */
2108    decimal64_to_string (s, d);
2109 -  return mpfr_set_str (r, s, 10, rnd_mode);
2110 +  return mpfr_strtofr (r, s, NULL, 10, rnd_mode);
2113  #endif /* MPFR_WANT_DECIMAL_FLOATS */
2114 diff -Naurd mpfr-4.0.1-a/src/version.c mpfr-4.0.1-b/src/version.c
2115 --- mpfr-4.0.1-a/src/version.c  2018-07-10 15:29:08.017776303 +0000
2116 +++ mpfr-4.0.1-b/src/version.c  2018-07-10 15:33:45.261532435 +0000
2117 @@ -25,5 +25,5 @@
2118  const char *
2119  mpfr_get_version (void)
2121 -  return "4.0.1-p7";
2122 +  return "4.0.1-p8";
2124 diff -Naurd mpfr-4.0.1-a/tests/tget_set_d64.c mpfr-4.0.1-b/tests/tget_set_d64.c
2125 --- mpfr-4.0.1-a/tests/tget_set_d64.c   2018-01-09 12:30:58.000000000 +0000
2126 +++ mpfr-4.0.1-b/tests/tget_set_d64.c   2018-07-10 15:33:45.237532458 +0000
2127 @@ -381,6 +381,66 @@
2128    mpfr_clear (x);
2131 +static void
2132 +powers_of_10 (void)
2134 +  mpfr_t x1, x2;
2135 +  _Decimal64 d[2];
2136 +  int i, rnd;
2137 +  unsigned int neg;
2139 +  mpfr_inits2 (200, x1, x2, (mpfr_ptr) 0);
2140 +  for (i = 0, d[0] = 1, d[1] = 1; i < 150; i++, d[0] *= 10, d[1] /= 10)
2141 +    for (neg = 0; neg <= 3; neg++)
2142 +      RND_LOOP_NO_RNDF (rnd)
2143 +        {
2144 +          int inex1, inex2;
2145 +          mpfr_flags_t flags1, flags2;
2146 +          mpfr_rnd_t rx1;
2147 +          _Decimal64 dd;
2149 +          inex1 = mpfr_set_si (x1, (neg >> 1) ? -i : i, MPFR_RNDN);
2150 +          MPFR_ASSERTN (inex1 == 0);
2152 +          rx1 = (neg & 1) ?
2153 +            MPFR_INVERT_RND ((mpfr_rnd_t) rnd) : (mpfr_rnd_t) rnd;
2154 +          mpfr_clear_flags ();
2155 +          inex1 = mpfr_exp10 (x1, x1, rx1);
2156 +          flags1 = __gmpfr_flags;
2158 +          dd = d[neg >> 1];
2160 +          if (neg & 1)
2161 +            {
2162 +              MPFR_SET_NEG (x1);
2163 +              inex1 = -inex1;
2164 +              dd = -dd;
2165 +            }
2167 +          mpfr_clear_flags ();
2168 +          inex2 = mpfr_set_decimal64 (x2, dd, (mpfr_rnd_t) rnd);
2169 +          flags2 = __gmpfr_flags;
2171 +          if (!(mpfr_equal_p (x1, x2) &&
2172 +                SAME_SIGN (inex1, inex2) &&
2173 +                flags1 == flags2))
2174 +            {
2175 +              printf ("Error in powers_of_10 for i=%d, neg=%d, %s\n",
2176 +                      i, neg, mpfr_print_rnd_mode ((mpfr_rnd_t) rnd));
2177 +              printf ("Expected ");
2178 +              mpfr_dump (x1);
2179 +              printf ("with inex = %d and flags =", inex1);
2180 +              flags_out (flags1);
2181 +              printf ("Got      ");
2182 +              mpfr_dump (x2);
2183 +              printf ("with inex = %d and flags =", inex2);
2184 +              flags_out (flags2);
2185 +              exit (1);
2186 +            }
2187 +        }
2188 +  mpfr_clears (x1, x2, (mpfr_ptr) 0);
2191  int
2192  main (void)
2194 @@ -401,6 +461,7 @@
2195    check_overflow ();
2196  #endif
2197    check_tiny ();
2198 +  powers_of_10 ();
2200    tests_end_mpfr ();
2201    return 0;
2202 diff -Naurd mpfr-4.0.1-a/PATCHES mpfr-4.0.1-b/PATCHES
2203 --- mpfr-4.0.1-a/PATCHES        2018-07-10 15:46:13.596797032 +0000
2204 +++ mpfr-4.0.1-b/PATCHES        2018-07-10 15:46:13.676796949 +0000
2205 @@ -0,0 +1 @@
2206 +buffer_sandwich
2207 diff -Naurd mpfr-4.0.1-a/VERSION mpfr-4.0.1-b/VERSION
2208 --- mpfr-4.0.1-a/VERSION        2018-07-10 15:33:45.261532435 +0000
2209 +++ mpfr-4.0.1-b/VERSION        2018-07-10 15:46:13.676796949 +0000
2210 @@ -1 +1 @@
2211 -4.0.1-p8
2212 +4.0.1-p9
2213 diff -Naurd mpfr-4.0.1-a/src/mpfr.h mpfr-4.0.1-b/src/mpfr.h
2214 --- mpfr-4.0.1-a/src/mpfr.h     2018-07-10 15:33:45.261532435 +0000
2215 +++ mpfr-4.0.1-b/src/mpfr.h     2018-07-10 15:46:13.672796954 +0000
2216 @@ -27,7 +27,7 @@
2217  #define MPFR_VERSION_MAJOR 4
2218  #define MPFR_VERSION_MINOR 0
2219  #define MPFR_VERSION_PATCHLEVEL 1
2220 -#define MPFR_VERSION_STRING "4.0.1-p8"
2221 +#define MPFR_VERSION_STRING "4.0.1-p9"
2223  /* User macros:
2224     MPFR_USE_FILE:        Define it to make MPFR define functions dealing
2225 diff -Naurd mpfr-4.0.1-a/src/vasprintf.c mpfr-4.0.1-b/src/vasprintf.c
2226 --- mpfr-4.0.1-a/src/vasprintf.c        2018-01-09 12:30:58.000000000 +0000
2227 +++ mpfr-4.0.1-b/src/vasprintf.c        2018-07-10 15:46:13.648796978 +0000
2228 @@ -683,20 +683,31 @@
2229    else
2230      {
2231        const size_t step = 3;
2232 -      const size_t size = len + tz;
2233 -      const size_t r = size % step == 0 ? step : size % step;
2234 -      const size_t q = size % step == 0 ? size / step - 1 : size / step;
2235 -      const size_t fullsize = size + q;
2236 -      size_t i;
2237 +      size_t size, q, r, fullsize;
2239 +      /* check that len + tz does not overflow */
2240 +      if (len > (size_t) -1 - tz)
2241 +        return 1;
2243 +      size = len + tz;              /* number of digits */
2244        MPFR_ASSERTD (size > 0);
2246 +      q = (size - 1) / step;        /* number of separators C */
2247 +      r = ((size - 1) % step) + 1;  /* number of digits in the leftmost block */
2249 +      /* check that size + q does not overflow */
2250 +      if (size > (size_t) -1 - q)
2251 +        return 1;
2253 +      fullsize = size + q;          /* number of digits and separators */
2255        if (buffer_incr_len (b, fullsize))
2256          return 1;
2258        if (b->size != 0)
2259          {
2260            char *oldcurr;
2261 +          size_t i;
2263            MPFR_ASSERTD (*b->curr == '\0');
2264            MPFR_ASSERTN (b->size < ((size_t) -1) - fullsize);
2265 @@ -705,11 +716,21 @@
2267            MPFR_DBGRES (oldcurr = b->curr);
2269 -          /* first R significant digits */
2270 -          memcpy (b->curr, str, r);
2271 +          /* first r significant digits (leftmost block) */
2272 +          if (r <= len)
2273 +            {
2274 +              memcpy (b->curr, str, r);
2275 +              str += r;
2276 +              len -= r;
2277 +            }
2278 +          else
2279 +            {
2280 +              MPFR_ASSERTD (r > len);
2281 +              memcpy (b->curr, str, len);
2282 +              memset (b->curr + len, '0', r - len);
2283 +              len = 0;
2284 +            }
2285            b->curr += r;
2286 -          str += r;
2287 -          len -= r;
2289            /* blocks of thousands. Warning: STR might end in the middle of a block */
2290            for (i = 0; i < q; ++i)
2291 @@ -722,6 +743,7 @@
2292                      {
2293                        memcpy (b->curr, str, step);
2294                        len -= step;
2295 +                      str += step;
2296                      }
2297                    else
2298                      /* last digits in STR, fill up thousand block with zeros */
2299 @@ -736,7 +758,6 @@
2300                  memset (b->curr, '0', step);
2302                b->curr += step;
2303 -              str += step;
2304              }
2306            MPFR_ASSERTD (b->curr - oldcurr == fullsize);
2307 @@ -1920,8 +1941,14 @@
2308    /* integral part (may also be "nan" or "inf") */
2309    MPFR_ASSERTN (np.ip_ptr != NULL); /* never empty */
2310    if (MPFR_UNLIKELY (np.thousands_sep))
2311 -    buffer_sandwich (buf, np.ip_ptr, np.ip_size, np.ip_trailing_zeros,
2312 -                     np.thousands_sep);
2313 +    {
2314 +      if (buffer_sandwich (buf, np.ip_ptr, np.ip_size, np.ip_trailing_zeros,
2315 +                           np.thousands_sep))
2316 +        {
2317 +          buf->len = -1;
2318 +          goto clear_and_exit;
2319 +        }
2320 +    }
2321    else
2322      {
2323        buffer_cat (buf, np.ip_ptr, np.ip_size);
2324 diff -Naurd mpfr-4.0.1-a/src/version.c mpfr-4.0.1-b/src/version.c
2325 --- mpfr-4.0.1-a/src/version.c  2018-07-10 15:33:45.261532435 +0000
2326 +++ mpfr-4.0.1-b/src/version.c  2018-07-10 15:46:13.672796954 +0000
2327 @@ -25,5 +25,5 @@
2328  const char *
2329  mpfr_get_version (void)
2331 -  return "4.0.1-p8";
2332 +  return "4.0.1-p9";
2334 diff -Naurd mpfr-4.0.1-a/tests/tprintf.c mpfr-4.0.1-b/tests/tprintf.c
2335 --- mpfr-4.0.1-a/tests/tprintf.c        2018-01-09 12:30:58.000000000 +0000
2336 +++ mpfr-4.0.1-b/tests/tprintf.c        2018-07-10 15:46:13.648796978 +0000
2337 @@ -31,6 +31,10 @@
2338  #include <stddef.h>
2339  #include <errno.h>
2341 +#ifdef HAVE_LOCALE_H
2342 +#include <locale.h>
2343 +#endif
2345  #include "mpfr-intmax.h"
2346  #include "mpfr-test.h"
2347  #define STDOUT_FILENO 1
2348 @@ -474,30 +478,41 @@
2349    mpfr_clear (x);
2352 -#ifdef HAVE_LOCALE_H
2354 -#include <locale.h>
2356 -const char * const tab_locale[] = {
2357 -  "en_US",
2358 -  "en_US.iso88591",
2359 -  "en_US.iso885915",
2360 -  "en_US.utf8"
2362 +#if defined(HAVE_LOCALE_H) && defined(HAVE_SETLOCALE)
2364  static void
2365  test_locale (void)
2367 +  const char * const tab_locale[] = {
2368 +    "en_US",
2369 +    "en_US.iso88591",
2370 +    "en_US.iso885915",
2371 +    "en_US.utf8"
2372 +  };
2373    int i;
2374 -  char *s = NULL;
2375    mpfr_t x;
2376    int count;
2377 +  char v[] = "99999999999999999999999.5";
2379 -  for(i = 0; i < numberof(tab_locale) && s == NULL; i++)
2380 -    s = setlocale (LC_ALL, tab_locale[i]);
2381 +  for (i = 0; i < numberof(tab_locale); i++)
2382 +    {
2383 +      char *s;
2385 -  if (s == NULL || MPFR_THOUSANDS_SEPARATOR != ',')
2386 -    return;
2387 +      s = setlocale (LC_ALL, tab_locale[i]);
2389 +      if (s != NULL && MPFR_THOUSANDS_SEPARATOR == ',')
2390 +        break;
2391 +    }
2393 +  if (i == numberof(tab_locale))
2394 +    {
2395 +      if (getenv ("MPFR_CHECK_LOCALES") == NULL)
2396 +        return;
2398 +      fprintf (stderr, "Cannot find a locale with ',' thousands separator.\n"
2399 +               "Please install one of the en_US based locales.\n");
2400 +      exit (1);
2401 +    }
2403    mpfr_init2 (x, 113);
2404    mpfr_set_ui (x, 10000, MPFR_RNDN);
2405 @@ -507,6 +522,50 @@
2406    count = mpfr_printf ("(2) 10000=%'Rf \n", x);
2407    check_length (10001, count, 25, d);
2409 +  mpfr_set_ui (x, 1000, MPFR_RNDN);
2410 +  count = mpfr_printf ("(3) 1000=%'Rf \n", x);
2411 +  check_length (10002, count, 23, d);
2413 +  for (i = 1; i <= sizeof (v) - 3; i++)
2414 +    {
2415 +      mpfr_set_str (x, v + sizeof (v) - 3 - i, 10, MPFR_RNDN);
2416 +      count = mpfr_printf ("(4) 10^i=%'.0Rf \n", x);
2417 +      check_length (10002 + i, count, 12 + i + i/3, d);
2418 +    }
2420 +#define N0 20
2422 +  for (i = 1; i <= N0; i++)
2423 +    {
2424 +      char s[N0+4];
2425 +      int j, rnd;
2427 +      s[0] = '1';
2428 +      for (j = 1; j <= i; j++)
2429 +        s[j] = '0';
2430 +      s[i+1] = '\0';
2432 +      mpfr_set_str (x, s, 10, MPFR_RNDN);
2434 +      RND_LOOP (rnd)
2435 +        {
2436 +          count = mpfr_printf ("(5) 10^i=%'.0R*f \n", (mpfr_rnd_t) rnd, x);
2437 +          check_length (11000 + 10 * i + rnd, count, 12 + i + i/3, d);
2438 +        }
2440 +      strcat (s + (i + 1), ".5");
2441 +      count = mpfr_printf ("(5) 10^i=%'.0Rf \n", x);
2442 +      check_length (11000 + 10 * i + 9, count, 12 + i + i/3, d);
2443 +    }
2445 +  mpfr_set_str (x, "1000", 10, MPFR_RNDN);
2446 +  count = mpfr_printf ("%'012.3Rg\n", x);
2447 +  check_length (12000, count, 13, d);
2448 +  count = mpfr_printf ("%'012.4Rg\n", x);
2449 +  check_length (12001, count, 13, d);
2450 +  count = mpfr_printf ("%'013.4Rg\n", x);
2451 +  check_length (12002, count, 14, d);
2453    mpfr_clear (x);
2456 @@ -515,7 +574,11 @@
2457  static void
2458  test_locale (void)
2460 -  /* Nothing */
2461 +  if (getenv ("MPFR_CHECK_LOCALES") != NULL)
2462 +    {
2463 +      fprintf (stderr, "Cannot test locales.\n");
2464 +      exit (1);
2465 +    }
2468  #endif
2469 diff -Naurd mpfr-4.0.1-a/tests/tsprintf.c mpfr-4.0.1-b/tests/tsprintf.c
2470 --- mpfr-4.0.1-a/tests/tsprintf.c       2018-01-10 10:15:30.000000000 +0000
2471 +++ mpfr-4.0.1-b/tests/tsprintf.c       2018-07-10 15:46:13.648796978 +0000
2472 @@ -380,7 +380,7 @@
2473    check_sprintf ("1.00                ", "%-#20.3RG", x);
2474    check_sprintf ("0.9999              ", "%-#20.4RG", x);
2476 -  /* multiple of 10 */
2477 +  /* powers of 10 */
2478    mpfr_set_str (x, "1e17", 10, MPFR_RNDN);
2479    check_sprintf ("1e+17", "%Re", x);
2480    check_sprintf ("1.000e+17", "%.3Re", x);
2481 @@ -402,7 +402,7 @@
2482    check_sprintf ("1", "%.0RUf", x);
2483    check_sprintf ("1", "%.0RYf", x);
2485 -  /* multiple of 10 with 'g' style */
2486 +  /* powers of 10 with 'g' style */
2487    mpfr_set_str (x, "10", 10, MPFR_RNDN);
2488    check_sprintf ("10", "%Rg", x);
2489    check_sprintf ("1e+01", "%.0Rg", x);
2490 @@ -419,6 +419,12 @@
2491    check_sprintf ("1e+03", "%.0Rg", x);
2492    check_sprintf ("1e+03", "%.3Rg", x);
2493    check_sprintf ("1000", "%.4Rg", x);
2494 +  check_sprintf ("1e+03", "%.3Rg", x);
2495 +  check_sprintf ("1000", "%.4Rg", x);
2496 +  check_sprintf ("    1e+03", "%9.3Rg", x);
2497 +  check_sprintf ("     1000", "%9.4Rg", x);
2498 +  check_sprintf ("00001e+03", "%09.3Rg", x);
2499 +  check_sprintf ("000001000", "%09.4Rg", x);
2501    mpfr_ui_div (x, 1, x, MPFR_RNDN);
2502    check_sprintf ("0.001", "%Rg", x);
2503 @@ -430,6 +436,10 @@
2504    check_sprintf ("1e+05", "%.0Rg", x);
2505    check_sprintf ("1e+05", "%.5Rg", x);
2506    check_sprintf ("100000", "%.6Rg", x);
2507 +  check_sprintf ("            1e+05", "%17.5Rg", x);
2508 +  check_sprintf ("           100000", "%17.6Rg", x);
2509 +  check_sprintf ("0000000000001e+05", "%017.5Rg", x);
2510 +  check_sprintf ("00000000000100000", "%017.6Rg", x);
2512    mpfr_ui_div (x, 1, x, MPFR_RNDN);
2513    check_sprintf ("1e-05", "%Rg", x);
2514 @@ -857,6 +867,12 @@
2515                    "%.*Zi, %R*e, %Lf", 20, mpz, rnd, x, d);
2516  #endif
2518 +  /* check invalid spec.spec */
2519 +  check_vsprintf ("%,", "%,");
2521 +  /* check empty format */
2522 +  check_vsprintf ("%", "%");
2524    mpf_clear (mpf);
2525    mpq_clear (mpq);
2526    mpz_clear (mpz);
2527 @@ -864,12 +880,12 @@
2528    return 0;
2531 -#if MPFR_LCONV_DPTS
2532 +#if defined(HAVE_LOCALE_H) && defined(HAVE_SETLOCALE) && MPFR_LCONV_DPTS
2534  /* Check with locale "da_DK". On most platforms, decimal point is ','
2535     and thousands separator is '.'; the test is not performed if this
2536     is not the case or if the locale doesn't exist. */
2537 -static int
2538 +static void
2539  locale_da_DK (void)
2541    mpfr_prec_t p = 128;
2542 @@ -878,7 +894,16 @@
2543    if (setlocale (LC_ALL, "da_DK") == 0 ||
2544        localeconv()->decimal_point[0] != ',' ||
2545        localeconv()->thousands_sep[0] != '.')
2546 -    return 0;
2547 +    {
2548 +      setlocale (LC_ALL, "C");
2550 +      if (getenv ("MPFR_CHECK_LOCALES") == NULL)
2551 +        return;
2553 +      fprintf (stderr,
2554 +               "Cannot test the da_DK locale (not found or inconsistent).\n");
2555 +      exit (1);
2556 +    }
2558    mpfr_init2 (x, p);
2560 @@ -917,10 +942,11 @@
2561    check_sprintf ("100" S2 "0000", "%'.4Rf", x);
2563    mpfr_clear (x);
2564 -  return 0;
2566 +  setlocale (LC_ALL, "C");
2569 -#endif  /* MPFR_LCONV_DPTS */
2570 +#endif  /* ... && MPFR_LCONV_DPTS */
2572  /* check concordance between mpfr_asprintf result with a regular mpfr float
2573     and with a regular double float */
2574 @@ -1425,6 +1451,117 @@
2575      exit (1);
2578 +#if defined(HAVE_LOCALE_H) && defined(HAVE_SETLOCALE)
2580 +/* The following tests should be equivalent to those from test_locale()
2581 +   in tprintf.c (remove the \n at the end of the test strings). */
2583 +static void
2584 +test_locale (void)
2586 +  const char * const tab_locale[] = {
2587 +    "en_US",
2588 +    "en_US.iso88591",
2589 +    "en_US.iso885915",
2590 +    "en_US.utf8"
2591 +  };
2592 +  int i;
2593 +  mpfr_t x;
2594 +  char v[] = "99999999999999999999999.5";
2596 +  for (i = 0; i < numberof(tab_locale); i++)
2597 +    {
2598 +      char *s;
2600 +      s = setlocale (LC_ALL, tab_locale[i]);
2602 +      if (s != NULL && MPFR_THOUSANDS_SEPARATOR == ',')
2603 +        break;
2604 +    }
2606 +  if (i == numberof(tab_locale))
2607 +    {
2608 +      if (getenv ("MPFR_CHECK_LOCALES") == NULL)
2609 +        return;
2611 +      fprintf (stderr, "Cannot find a locale with ',' thousands separator.\n"
2612 +               "Please install one of the en_US based locales.\n");
2613 +      exit (1);
2614 +    }
2616 +  mpfr_init2 (x, 113);
2617 +  mpfr_set_ui (x, 10000, MPFR_RNDN);
2619 +  check_sprintf ("(1) 10000=10,000 ", "(1) 10000=%'Rg ", x);
2620 +  check_sprintf ("(2) 10000=10,000.000000 ", "(2) 10000=%'Rf ", x);
2622 +  mpfr_set_ui (x, 1000, MPFR_RNDN);
2623 +  check_sprintf ("(3) 1000=1,000.000000 ", "(3) 1000=%'Rf ", x);
2625 +  for (i = 1; i <= sizeof (v) - 3; i++)
2626 +    {
2627 +      char buf[64];
2628 +      int j;
2630 +      strcpy (buf, "(4) 10^i=1");
2631 +      for (j = i; j > 0; j--)
2632 +        strcat (buf, ",0" + (j % 3 != 0));
2633 +      strcat (buf, " ");
2634 +      mpfr_set_str (x, v + sizeof (v) - 3 - i, 10, MPFR_RNDN);
2635 +      check_sprintf (buf, "(4) 10^i=%'.0Rf ", x);
2636 +    }
2638 +#define N0 20
2640 +  for (i = 1; i <= N0; i++)
2641 +    {
2642 +      char s[N0+4], buf[64];
2643 +      int j;
2645 +      s[0] = '1';
2646 +      for (j = 1; j <= i; j++)
2647 +        s[j] = '0';
2648 +      s[i+1] = '\0';
2650 +      strcpy (buf, "(5) 10^i=1");
2651 +      for (j = i; j > 0; j--)
2652 +        strcat (buf, ",0" + (j % 3 != 0));
2653 +      strcat (buf, " ");
2655 +      mpfr_set_str (x, s, 10, MPFR_RNDN);
2657 +      check_sprintf (buf, "(5) 10^i=%'.0RNf ", x);
2658 +      check_sprintf (buf, "(5) 10^i=%'.0RZf ", x);
2659 +      check_sprintf (buf, "(5) 10^i=%'.0RUf ", x);
2660 +      check_sprintf (buf, "(5) 10^i=%'.0RDf ", x);
2661 +      check_sprintf (buf, "(5) 10^i=%'.0RYf ", x);
2663 +      strcat (s + (i + 1), ".5");
2664 +      check_sprintf (buf, "(5) 10^i=%'.0Rf ", x);
2665 +    }
2667 +  mpfr_set_str (x, "1000", 10, MPFR_RNDN);
2668 +  check_sprintf ("00000001e+03", "%'012.3Rg", x);
2669 +  check_sprintf ("00000001,000", "%'012.4Rg", x);
2670 +  check_sprintf ("000000001,000", "%'013.4Rg", x);
2672 +  mpfr_clear (x);
2675 +#else
2677 +static void
2678 +test_locale (void)
2680 +  if (getenv ("MPFR_CHECK_LOCALES") != NULL)
2681 +    {
2682 +      fprintf (stderr, "Cannot test locales.\n");
2683 +      exit (1);
2684 +    }
2687 +#endif
2689  int
2690  main (int argc, char **argv)
2692 @@ -1446,12 +1583,14 @@
2693        binary ();
2694        decimal ();
2696 -#if defined(HAVE_LOCALE_H) && defined(HAVE_SETLOCALE)
2697 -#if MPFR_LCONV_DPTS
2698 +#if defined(HAVE_LOCALE_H) && defined(HAVE_SETLOCALE) && MPFR_LCONV_DPTS
2699        locale_da_DK ();
2700 -  /* Avoid a warning by doing the setlocale outside of this #if */
2701 -#endif
2702 -      setlocale (LC_ALL, "C");
2703 +#else
2704 +      if (getenv ("MPFR_CHECK_LOCALES") != NULL)
2705 +        {
2706 +          fprintf (stderr, "Cannot test locales.\n");
2707 +          exit (1);
2708 +        }
2709  #endif
2710      }
2712 @@ -1462,6 +1601,7 @@
2713    snprintf_size ();
2714    percent_n ();
2715    mixed ();
2716 +  test_locale ();
2718    if (getenv ("MPFR_CHECK_LIBC_PRINTF"))
2719      {