xref: /netbsd-src/external/lgpl3/mpfr/dist/tests/trint.c (revision ec6772edaf0cdcb5f52a48f4aca5e33a8fb8ecfd)
1 /* Test file for mpfr_rint, mpfr_trunc, mpfr_floor, mpfr_ceil, mpfr_round,
2    mpfr_rint_trunc, mpfr_rint_floor, mpfr_rint_ceil, mpfr_rint_round.
3 
4 Copyright 2002-2023 Free Software Foundation, Inc.
5 Contributed by the AriC and Caramba projects, INRIA.
6 
7 This file is part of the GNU MPFR Library.
8 
9 The GNU MPFR Library is free software; you can redistribute it and/or modify
10 it under the terms of the GNU Lesser General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or (at your
12 option) any later version.
13 
14 The GNU MPFR Library is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16 or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
17 License for more details.
18 
19 You should have received a copy of the GNU Lesser General Public License
20 along with the GNU MPFR Library; see the file COPYING.LESSER.  If not, see
21 https://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
22 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
23 
24 #include "mpfr-test.h"
25 
26 #if __MPFR_STDC (199901L)
27 # include <math.h>
28 #endif
29 
30 static void
special(void)31 special (void)
32 {
33   mpfr_t x, y;
34   mpfr_exp_t emax;
35 
36   mpfr_init (x);
37   mpfr_init (y);
38 
39   mpfr_set_nan (x);
40   mpfr_rint (y, x, MPFR_RNDN);
41   MPFR_ASSERTN(mpfr_nan_p (y));
42 
43   mpfr_set_inf (x, 1);
44   mpfr_rint (y, x, MPFR_RNDN);
45   MPFR_ASSERTN(mpfr_inf_p (y) && mpfr_sgn (y) > 0);
46 
47   mpfr_set_inf (x, -1);
48   mpfr_rint (y, x, MPFR_RNDN);
49   MPFR_ASSERTN(mpfr_inf_p (y) && mpfr_sgn (y) < 0);
50 
51   mpfr_set_ui (x, 0, MPFR_RNDN);
52   mpfr_rint (y, x, MPFR_RNDN);
53   MPFR_ASSERTN(mpfr_cmp_ui (y, 0) == 0 && MPFR_IS_POS(y));
54 
55   mpfr_set_ui (x, 0, MPFR_RNDN);
56   mpfr_neg (x, x, MPFR_RNDN);
57   mpfr_rint (y, x, MPFR_RNDN);
58   MPFR_ASSERTN(mpfr_cmp_ui (y, 0) == 0 && MPFR_IS_NEG(y));
59 
60   /* coverage test */
61   mpfr_set_prec (x, 2);
62   mpfr_set_ui (x, 1, MPFR_RNDN);
63   mpfr_mul_2ui (x, x, mp_bits_per_limb, MPFR_RNDN);
64   mpfr_rint (y, x, MPFR_RNDN);
65   MPFR_ASSERTN(mpfr_cmp (y, x) == 0);
66 
67   /* another coverage test */
68   emax = mpfr_get_emax ();
69   set_emax (1);
70   mpfr_set_prec (x, 3);
71   mpfr_set_str_binary (x, "1.11E0");
72   mpfr_set_prec (y, 2);
73   mpfr_rint (y, x, MPFR_RNDU); /* x rounds to 1.0E1=0.1E2 which overflows */
74   MPFR_ASSERTN(mpfr_inf_p (y) && mpfr_sgn (y) > 0);
75   set_emax (emax);
76 
77   /* yet another */
78   mpfr_set_prec (x, 97);
79   mpfr_set_prec (y, 96);
80   mpfr_set_str_binary (x, "-0.1011111001101111000111011100011100000110110110110000000111010001000101001111101010101011010111100E97");
81   mpfr_rint (y, x, MPFR_RNDN);
82   MPFR_ASSERTN(mpfr_cmp (y, x) == 0);
83 
84   mpfr_set_prec (x, 53);
85   mpfr_set_prec (y, 53);
86   mpfr_set_str_binary (x, "0.10101100000000101001010101111111000000011111010000010E-1");
87   mpfr_rint (y, x, MPFR_RNDU);
88   MPFR_ASSERTN(mpfr_cmp_ui (y, 1) == 0);
89   mpfr_rint (y, x, MPFR_RNDD);
90   MPFR_ASSERTN(mpfr_cmp_ui (y, 0) == 0 && MPFR_IS_POS(y));
91 
92   mpfr_set_prec (x, 36);
93   mpfr_set_prec (y, 2);
94   mpfr_set_str_binary (x, "-11000110101010111111110111001.0000100");
95   mpfr_rint (y, x, MPFR_RNDN);
96   mpfr_set_str_binary (x, "-11E27");
97   MPFR_ASSERTN(mpfr_cmp (y, x) == 0);
98 
99   mpfr_set_prec (x, 39);
100   mpfr_set_prec (y, 29);
101   mpfr_set_str_binary (x, "-0.100010110100011010001111001001001100111E39");
102   mpfr_rint (y, x, MPFR_RNDN);
103   mpfr_set_str_binary (x, "-0.10001011010001101000111100101E39");
104   MPFR_ASSERTN(mpfr_cmp (y, x) == 0);
105 
106   mpfr_set_prec (x, 46);
107   mpfr_set_prec (y, 32);
108   mpfr_set_str_binary (x, "-0.1011100110100101000001011111101011001001101001E32");
109   mpfr_rint (y, x, MPFR_RNDN);
110   mpfr_set_str_binary (x, "-0.10111001101001010000010111111011E32");
111   MPFR_ASSERTN(mpfr_cmp (y, x) == 0);
112 
113   /* coverage test for mpfr_round */
114   mpfr_set_prec (x, 3);
115   mpfr_set_str_binary (x, "1.01E1"); /* 2.5 */
116   mpfr_set_prec (y, 2);
117   mpfr_round (y, x);
118   /* since mpfr_round breaks ties away, should give 3 and not 2 as with
119      the "round to even" rule */
120   MPFR_ASSERTN(mpfr_cmp_ui (y, 3) == 0);
121   /* same test for the function */
122   (mpfr_round) (y, x);
123   MPFR_ASSERTN(mpfr_cmp_ui (y, 3) == 0);
124 
125   mpfr_set_prec (x, 6);
126   mpfr_set_prec (y, 3);
127   mpfr_set_str_binary (x, "110.111");
128   mpfr_round (y, x);
129   if (mpfr_cmp_ui (y, 7))
130     {
131       printf ("Error in round(110.111)\n");
132       exit (1);
133     }
134 
135   /* Bug found by  Mark J Watkins */
136   mpfr_set_prec (x, 84);
137   mpfr_set_str_binary (x,
138    "0.110011010010001000000111101101001111111100101110010000000000000" \
139                        "000000000000000000000E32");
140   mpfr_round (x, x);
141   if (mpfr_cmp_str (x, "0.1100110100100010000001111011010100000000000000" \
142                     "00000000000000000000000000000000000000E32", 2, MPFR_RNDN))
143     {
144       printf ("Rounding error when dest=src\n");
145       exit (1);
146     }
147 
148   mpfr_clear (x);
149   mpfr_clear (y);
150 }
151 
152 #define BASIC_TEST(F,J)                                                 \
153   do                                                                    \
154     {                                                                   \
155       int red;                                                          \
156       for (red = 0; red <= 1; red++)                                    \
157         {                                                               \
158           int inex1, inex2;                                             \
159           unsigned int ex_flags, flags;                                 \
160                                                                         \
161           if (red)                                                      \
162             {                                                           \
163               set_emin (e);                                             \
164               set_emax (e);                                             \
165             }                                                           \
166                                                                         \
167           mpfr_clear_flags ();                                          \
168           inex1 = mpfr_set_si (y, J, (mpfr_rnd_t) r);                   \
169           ex_flags = __gmpfr_flags;                                     \
170           mpfr_clear_flags ();                                          \
171           inex2 = mpfr_rint_##F (z, x, (mpfr_rnd_t) r);                 \
172           flags = __gmpfr_flags;                                        \
173           if (! (mpfr_equal_p (y, z) &&                                 \
174                  SAME_SIGN (inex1, inex2) &&                            \
175                  flags == ex_flags))                                    \
176             {                                                           \
177               printf ("Basic test failed on mpfr_rint_" #F              \
178                       ", prec = %d, i = %d, %s\n", prec, s * i,         \
179                       mpfr_print_rnd_mode ((mpfr_rnd_t) r));            \
180               printf ("i.e. x = ");                                     \
181               mpfr_dump (x);                                            \
182               if (red)                                                  \
183                 printf ("with emin = emax = %d\n", e);                  \
184               printf ("Expected ");                                     \
185               mpfr_dump (y);                                            \
186               printf ("with inex = %d (or equivalent)\n", inex1);       \
187               printf ("     flags:");                                   \
188               flags_out (ex_flags);                                     \
189               printf ("Got      ");                                     \
190               mpfr_dump (z);                                            \
191               printf ("with inex = %d (or equivalent)\n", inex2);       \
192               printf ("     flags:");                                   \
193               flags_out (flags);                                        \
194               exit (1);                                                 \
195             }                                                           \
196         }                                                               \
197       set_emin (emin);                                                  \
198       set_emax (emax);                                                  \
199     }                                                                   \
200   while (0)
201 
202 #define BASIC_TEST2(F,J,INEX)                                   \
203   do                                                            \
204     {                                                           \
205       int red;                                                  \
206       for (red = 0; red <= 1; red++)                            \
207         {                                                       \
208           int inex;                                             \
209           unsigned int ex_flags, flags;                         \
210                                                                 \
211           if (red)                                              \
212             {                                                   \
213               set_emin (e);                                     \
214               set_emax (e);                                     \
215             }                                                   \
216                                                                 \
217           mpfr_clear_flags ();                                  \
218           inex = mpfr_set_si (y, J, MPFR_RNDN);                 \
219           MPFR_ASSERTN (inex == 0 || mpfr_overflow_p ());       \
220           ex_flags = __gmpfr_flags;                             \
221           mpfr_clear_flags ();                                  \
222           inex = mpfr_##F (z, x);                               \
223           if (inex != 0)                                        \
224             ex_flags |= MPFR_FLAGS_INEXACT;                     \
225           flags = __gmpfr_flags;                                \
226           if (! (mpfr_equal_p (y, z) &&                         \
227                  inex == (INEX) &&                              \
228                  flags == ex_flags))                            \
229             {                                                   \
230               printf ("Basic test failed on mpfr_" #F           \
231                       ", prec = %d, i = %d\n", prec, s * i);    \
232               printf ("i.e. x = ");                             \
233               mpfr_dump (x);                                    \
234               if (red)                                          \
235                 printf ("with emin = emax = %d\n", e);          \
236               printf ("Expected ");                             \
237               mpfr_dump (y);                                    \
238               printf ("with inex = %d\n", (INEX));              \
239               printf ("     flags:");                           \
240               flags_out (ex_flags);                             \
241               printf ("Got      ");                             \
242               mpfr_dump (z);                                    \
243               printf ("with inex = %d\n", inex);                \
244               printf ("     flags:");                           \
245               flags_out (flags);                                \
246               exit (1);                                         \
247             }                                                   \
248         }                                                       \
249       set_emin (emin);                                          \
250       set_emax (emax);                                          \
251     }                                                           \
252   while (0)
253 
254 /* Test mpfr_rint_* on i/4 with |i| between 1 and 72. */
255 static void
basic_tests(void)256 basic_tests (void)
257 {
258   mpfr_t x, y, z;
259   int prec, s, i, r;
260   mpfr_exp_t emin, emax;
261 
262   emin = mpfr_get_emin ();
263   emax = mpfr_get_emax ();
264 
265   mpfr_init2 (x, 16);
266   for (prec = MPFR_PREC_MIN; prec <= 7; prec++)
267     {
268       mpfr_inits2 (prec, y, z, (mpfr_ptr) 0);
269       for (s = 1; s >= -1; s -= 2)
270         for (i = 1; i <= 72; i++)
271           {
272             int k, t, u, v, f, e, b;
273 
274             for (t = i/4, k = 0; t >= 1 << prec; t >>= 1, k++)
275               ;
276             b = !(t & 1);
277             t <<= k;
278             for (u = (i+3)/4, k = 0; u >= 1 << prec; u = (u+1)/2, k++)
279               ;
280             u <<= k;
281             v = i < (t+u) << 1 ? t : u;
282             if (b)
283               b = i == (t+u) << 1;
284             f = t == u ? 0 : i % 4 == 0 ? 1 : 2;
285 
286             mpfr_set_si_2exp (x, s * i, -2, MPFR_RNDN);
287             e = mpfr_get_exp (x);
288             RND_LOOP_NO_RNDF (r)
289               {
290                 BASIC_TEST (trunc, s * (i/4));
291                 BASIC_TEST (floor, s > 0 ? i/4 : - ((i+3)/4));
292                 BASIC_TEST (ceil, s > 0 ? (i+3)/4 : - (i/4));
293                 BASIC_TEST (round, s * ((i+2)/4));
294                 BASIC_TEST (roundeven, s * (i % 8 == 2 ? i/4 : (i+2)/4));
295               }
296             BASIC_TEST2 (trunc, s * t, - s * f);
297             BASIC_TEST2 (floor, s > 0 ? t : - u, - f);
298             BASIC_TEST2 (ceil, s > 0 ? u : - t, f);
299             BASIC_TEST2 (round, s * v, v == t ? - s * f : s * f);
300             BASIC_TEST2 (roundeven, s * (b ? t : v),
301                          b || v == t ? - s * f : s * f);
302           }
303       mpfr_clears (y, z, (mpfr_ptr) 0);
304     }
305   mpfr_clear (x);
306 }
307 
308 #if __MPFR_STDC (199901L)
309 
310 typedef int (*F2)(mpfr_ptr, mpfr_srcptr);
311 
312 /* The argument g below will be of type F2 with args (mpfr_ptr, mpfr_srcptr),
313    except for mpfr_rint, with args (mpfr_ptr, mpfr_srcptr, mpfr_rnd_t). So,
314    when passing mpfr_rint, we need a cast: "(F2) &mpfr_rint". The cast will
315    also be needed to compare the pointers: "g == (F2) &mpfr_rint", and that's
316    all. */
317 
318 #if defined(__GNUC__)
319 #pragma GCC diagnostic push
320 #if __GNUC__ >= 8 || __clang_major__ >= 13
321 #pragma GCC diagnostic ignored "-Wcast-function-type"
322 #endif
323 #endif
324 
325 static void
test_fct(double (* f)(double),F2 g,const char * s,mpfr_rnd_t r)326 test_fct (double (*f)(double), F2 g, const char *s, mpfr_rnd_t r)
327 {
328   double d, y;
329   mpfr_t dd, yy;
330 
331   mpfr_init2 (dd, 53);
332   mpfr_init2 (yy, 53);
333   for (d = -5.0; d <= 5.0; d += 0.25)
334     {
335       mpfr_set_d (dd, d, r);
336       y = (*f)(d);
337       if (g == (F2) &mpfr_rint)
338         mpfr_rint (yy, dd, r);
339       else
340         (*g)(yy, dd);
341       mpfr_set_d (dd, y, r);
342       if (mpfr_cmp (yy, dd))
343         {
344           printf ("test_against_libc: incorrect result for %s, rnd = %s,"
345                   " d = %g\ngot ", s, mpfr_print_rnd_mode (r), d);
346           mpfr_out_str (stdout, 10, 0, yy, MPFR_RNDN);
347           printf (" instead of %g\n", y);
348           exit (1);
349         }
350     }
351   mpfr_clear (dd);
352   mpfr_clear (yy);
353 }
354 
355 #define TEST_FCT(F) test_fct (&F, &mpfr_##F, #F, (mpfr_rnd_t) r)
356 
357 static void
test_against_libc(void)358 test_against_libc (void)
359 {
360   int r = MPFR_RNDN;
361 
362   (void) r;  /* avoid a warning by using r */
363 #if HAVE_ROUND
364   TEST_FCT (round);
365 #endif
366 #if HAVE_TRUNC
367   TEST_FCT (trunc);
368 #endif
369 #if HAVE_FLOOR
370   TEST_FCT (floor);
371 #endif
372 #if HAVE_CEIL
373   TEST_FCT (ceil);
374 #endif
375 #if HAVE_NEARBYINT
376   RND_LOOP (r)
377     if (mpfr_set_machine_rnd_mode ((mpfr_rnd_t) r) == 0)
378       test_fct (&nearbyint, (F2) &mpfr_rint, "rint", (mpfr_rnd_t) r);
379 #endif
380 }
381 
382 #if defined(__GNUC__)
383 #pragma GCC diagnostic pop
384 #endif
385 
386 #endif
387 
388 static void
err(const char * str,mp_size_t s,mpfr_ptr x,mpfr_ptr y,mpfr_prec_t p,mpfr_rnd_t r,int trint,int inexact)389 err (const char *str, mp_size_t s, mpfr_ptr x, mpfr_ptr y, mpfr_prec_t p,
390      mpfr_rnd_t r, int trint, int inexact)
391 {
392   printf ("Error: %s\ns = %u, p = %u, r = %s, trint = %d, inexact = %d\nx = ",
393           str, (unsigned int) s, (unsigned int) p, mpfr_print_rnd_mode (r),
394           trint, inexact);
395   mpfr_dump (x);
396   printf ("y = ");
397   mpfr_dump (y);
398   exit (1);
399 }
400 
401 static void
coverage_03032011(void)402 coverage_03032011 (void)
403 {
404   mpfr_t in, out, cmp;
405   int status;
406   int precIn;
407   char strData[(GMP_NUMB_BITS * 4)+256];
408 
409   precIn = GMP_NUMB_BITS * 4;
410 
411   mpfr_init2 (in, precIn);
412   mpfr_init2 (out, GMP_NUMB_BITS);
413   mpfr_init2 (cmp, GMP_NUMB_BITS);
414 
415   /* cmp = "0.1EprecIn+2" */
416   /* The buffer size is sufficient, as precIn is small in practice. */
417   sprintf (strData, "0.1E%d", precIn+2);
418   mpfr_set_str_binary (cmp, strData);
419 
420   /* in = "0.10...01EprecIn+2" use all (precIn) significand bits */
421   memset ((void *)strData, '0', precIn+2);
422   strData[1] = '.';
423   strData[2] = '1';
424   sprintf (&strData[precIn+1], "1E%d", precIn+2);
425   mpfr_set_str_binary (in, strData);
426 
427   status = mpfr_rint (out, in, MPFR_RNDN);
428   if ((mpfr_cmp (out, cmp) != 0) || (status >= 0))
429     {
430       printf("mpfr_rint error :\n status is %d instead of 0\n", status);
431       printf(" out value is ");
432       mpfr_dump(out);
433       printf(" instead of   ");
434       mpfr_dump(cmp);
435       exit (1);
436     }
437 
438   mpfr_clear (cmp);
439   mpfr_clear (out);
440 
441   mpfr_init2 (out, GMP_NUMB_BITS);
442   mpfr_init2 (cmp, GMP_NUMB_BITS);
443 
444   /* cmp = "0.10...01EprecIn+2" use all (GMP_NUMB_BITS) significand bits */
445   strcpy (&strData[GMP_NUMB_BITS+1], &strData[precIn+1]);
446   mpfr_set_str_binary (cmp, strData);
447 
448   (MPFR_MANT(in))[2] = MPFR_LIMB_HIGHBIT;
449   status = mpfr_rint (out, in, MPFR_RNDN);
450 
451   if ((mpfr_cmp (out, cmp) != 0) || (status <= 0))
452     {
453       printf("mpfr_rint error :\n status is %d instead of 0\n", status);
454       printf(" out value is\n");
455       mpfr_dump(out);
456       printf(" instead of\n");
457       mpfr_dump(cmp);
458       exit (1);
459     }
460 
461   mpfr_clear (cmp);
462   mpfr_clear (out);
463   mpfr_clear (in);
464 }
465 
466 #define TEST_FUNCTION mpfr_rint_trunc
467 #define TEST_RANDOM_EMIN -20
468 #define TEST_RANDOM_ALWAYS_SCALE 1
469 #define test_generic test_generic_trunc
470 #include "tgeneric.c"
471 
472 #define TEST_FUNCTION mpfr_rint_floor
473 #define TEST_RANDOM_EMIN -20
474 #define TEST_RANDOM_ALWAYS_SCALE 1
475 #define test_generic test_generic_floor
476 #include "tgeneric.c"
477 
478 #define TEST_FUNCTION mpfr_rint_ceil
479 #define TEST_RANDOM_EMIN -20
480 #define TEST_RANDOM_ALWAYS_SCALE 1
481 #define test_generic test_generic_ceil
482 #include "tgeneric.c"
483 
484 #define TEST_FUNCTION mpfr_rint_round
485 #define TEST_RANDOM_EMIN -20
486 #define TEST_RANDOM_ALWAYS_SCALE 1
487 #define test_generic test_generic_round
488 #include "tgeneric.c"
489 
490 #define TEST_FUNCTION mpfr_rint_roundeven
491 #define TEST_RANDOM_EMIN -20
492 #define TEST_RANDOM_ALWAYS_SCALE 1
493 #define test_generic test_generic_roundeven
494 #include "tgeneric.c"
495 
496 int
main(int argc,char * argv[])497 main (int argc, char *argv[])
498 {
499   mp_size_t s;
500   mpz_t z;
501   mpfr_prec_t p;
502   mpfr_t x, y, t, u, v;
503   int r;
504   int inexact, sign_t;
505 
506   tests_start_mpfr ();
507 
508   mpfr_init (x);
509   mpfr_init (y);
510   mpz_init (z);
511   mpfr_init (t);
512   mpfr_init (u);
513   mpfr_init (v);
514   mpz_set_ui (z, 1);
515   /* the code below works for 1 <= MPFR_PREC_MIN <= 2 */
516   MPFR_ASSERTN(1 <= MPFR_PREC_MIN && MPFR_PREC_MIN <= 2);
517   for (s = MPFR_PREC_MIN; s < 100; s++)
518     {
519       if (s > 1)
520         {
521           mpz_mul_2exp (z, z, 1);
522           if (RAND_BOOL ())
523             mpz_add_ui (z, z, 1);
524         }
525       /* now 2^(s-1) <= z < 2^s */
526       mpfr_set_prec (x, s);
527       mpfr_set_prec (t, s);
528       mpfr_set_prec (u, s);
529       if (mpfr_set_z (x, z, MPFR_RNDN))
530         {
531 #ifndef MPFR_USE_MINI_GMP
532           gmp_printf ("Error: mpfr_set_z should be exact (z = %Zd, s = %u)\n",
533                       z, (unsigned int) s);
534 #else /* mini-gmp has no gmp_printf (at least in gmp-6.1.2) */
535           printf ("mpfr_set_z should be exact\n");
536 #endif
537           exit (1);
538         }
539       if (RAND_BOOL ())
540         mpfr_neg (x, x, MPFR_RNDN);
541       if (RAND_BOOL ())
542         mpfr_div_2ui (x, x, randlimb () % s, MPFR_RNDN);
543       for (p = MPFR_PREC_MIN; p < 100; p++)
544         {
545           int trint;
546           mpfr_set_prec (y, p);
547           mpfr_set_prec (v, p);
548           RND_LOOP (r)
549             for (trint = 0; trint < 4; trint++)
550               {
551                 if (trint == 2)
552                   inexact = mpfr_rint (y, x, (mpfr_rnd_t) r);
553                 else if (trint == 3)
554                   {
555                     if (r != MPFR_RNDN)
556                       continue;
557                     inexact = mpfr_round (y, x);
558                   }
559                 else if (r == MPFR_RNDN)
560                   inexact = (trint ? mpfr_roundeven (y, x) :
561                              mpfr_rint_roundeven (y, x, MPFR_RNDZ));
562                 else if (r == MPFR_RNDZ)
563                   inexact = (trint ? mpfr_trunc (y, x) :
564                              mpfr_rint_trunc (y, x, MPFR_RNDZ));
565                 else if (r == MPFR_RNDU)
566                   inexact = (trint ? mpfr_ceil (y, x) :
567                              mpfr_rint_ceil (y, x, MPFR_RNDU));
568                 else if (r == MPFR_RNDD)
569                   inexact = (trint ? mpfr_floor (y, x) :
570                              mpfr_rint_floor (y, x, MPFR_RNDD));
571                 else
572                   {
573                     MPFR_ASSERTN (r == MPFR_RNDA || r == MPFR_RNDF);
574                     continue;
575                   }
576                 if (mpfr_sub (t, y, x, MPFR_RNDN))
577                   err ("subtraction 1 should be exact", s, x, y, p,
578                        (mpfr_rnd_t) r, trint, inexact);
579                 sign_t = mpfr_cmp_ui (t, 0);
580                 if (trint != 0 &&
581                     (((inexact == 0) && (sign_t != 0)) ||
582                      ((inexact < 0) && (sign_t >= 0)) ||
583                      ((inexact > 0) && (sign_t <= 0))))
584                   err ("wrong inexact flag", s, x, y, p,
585                        (mpfr_rnd_t) r, trint, inexact);
586                 if (inexact == 0)
587                   continue; /* end of the test for exact results */
588 
589                 if (((r == MPFR_RNDD || (r == MPFR_RNDZ && MPFR_IS_POS (x)))
590                      && inexact > 0) ||
591                     ((r == MPFR_RNDU || (r == MPFR_RNDZ && MPFR_IS_NEG (x)))
592                      && inexact < 0))
593                   err ("wrong rounding direction", s, x, y, p,
594                        (mpfr_rnd_t) r, trint, inexact);
595                 if (inexact < 0)
596                   {
597                     mpfr_add_ui (v, y, 1, MPFR_RNDU);
598                     if (mpfr_cmp (v, x) <= 0)
599                       err ("representable integer between x and "
600                            "its rounded value", s, x, y, p,
601                            (mpfr_rnd_t) r, trint, inexact);
602                   }
603                 else
604                   {
605                     mpfr_sub_ui (v, y, 1, MPFR_RNDD);
606                     if (mpfr_cmp (v, x) >= 0)
607                       err ("representable integer between x and "
608                            "its rounded value", s, x, y, p,
609                            (mpfr_rnd_t) r, trint, inexact);
610                   }
611                 if (r == MPFR_RNDN && trint != 0)
612                   {
613                     int cmp;
614                     if (mpfr_sub (u, v, x, MPFR_RNDN))
615                       err ("subtraction 2 should be exact", s, x, y, p,
616                            (mpfr_rnd_t) r, trint, inexact);
617                     cmp = mpfr_cmpabs (t, u);
618                     if (cmp > 0)
619                       err ("faithful rounding, but not the nearest integer",
620                            s, x, y, p, (mpfr_rnd_t) r, trint, inexact);
621                     if (cmp < 0)
622                       continue;
623                     /* |t| = |u|: x is the middle of two consecutive
624                        representable integers. */
625                     if (trint == 2)
626                       {
627                         /* halfway case for mpfr_rint in MPFR_RNDN rounding
628                            mode: round to an even integer or significand. */
629                         mpfr_div_2ui (y, y, 1, MPFR_RNDZ);
630                         if (!mpfr_integer_p (y))
631                           err ("halfway case for mpfr_rint, result isn't "
632                                "an even integer", s, x, y, p,
633                                (mpfr_rnd_t) r, trint, inexact);
634                         if (p > 1)
635                           {
636                             /* For p > 1, if floor(x) and ceil(x) aren't
637                                both representable integers, the significand
638                                must be even. */
639                             mpfr_sub (v, v, y, MPFR_RNDN);
640                             mpfr_abs (v, v, MPFR_RNDN);
641                             if (mpfr_cmp_ui (v, 1) != 0)
642                               {
643                                 mpfr_div_2si (y, y, MPFR_EXP (y) -
644                                               MPFR_PREC (y) + 1, MPFR_RNDN);
645                                 if (!mpfr_integer_p (y))
646                                   err ("halfway case for mpfr_rint, "
647                                        "significand isn't even", s, x, y, p,
648                                        (mpfr_rnd_t) r, trint, inexact);
649                               }
650                           }
651                       }
652                     else if (trint == 3)
653                       { /* halfway case for mpfr_round: x must have been
654                            rounded away from zero. */
655                         if ((MPFR_IS_POS (x) && inexact < 0) ||
656                             (MPFR_IS_NEG (x) && inexact > 0))
657                           err ("halfway case for mpfr_round, "
658                                "bad rounding direction", s, x, y, p,
659                                (mpfr_rnd_t) r, trint, inexact);
660                       }
661                   }
662               }
663         }
664     }
665   mpfr_clear (x);
666   mpfr_clear (y);
667   mpz_clear (z);
668   mpfr_clear (t);
669   mpfr_clear (u);
670   mpfr_clear (v);
671 
672   special ();
673   basic_tests ();
674   coverage_03032011 ();
675 
676   test_generic_trunc (MPFR_PREC_MIN, 300, 20);
677   test_generic_floor (MPFR_PREC_MIN, 300, 20);
678   test_generic_ceil (MPFR_PREC_MIN, 300, 20);
679   test_generic_round (MPFR_PREC_MIN, 300, 20);
680   test_generic_roundeven (MPFR_PREC_MIN, 300, 20);
681 
682 #if __MPFR_STDC (199901L)
683   if (argc > 1 && strcmp (argv[1], "-s") == 0)
684     test_against_libc ();
685 #endif
686 
687   tests_end_mpfr ();
688   return 0;
689 }
690