tcan_round.c revision 1.1.1.3 1 /* Test file for mpfr_can_round and mpfr_round_p.
2
3 Copyright 1999, 2001-2016 Free Software Foundation, Inc.
4 Contributed by the AriC and Caramba projects, INRIA.
5
6 This file is part of the GNU MPFR Library.
7
8 The GNU MPFR Library is free software; you can redistribute it and/or modify
9 it under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or (at your
11 option) any later version.
12
13 The GNU MPFR Library is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
16 License for more details.
17
18 You should have received a copy of the GNU Lesser General Public License
19 along with the GNU MPFR Library; see the file COPYING.LESSER. If not, see
20 http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
21 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
22
23 #include <stdio.h>
24 #include <stdlib.h>
25
26 #include "mpfr-test.h"
27
28 /* Simple cases where err - prec is large enough.
29 One can get failures as a consequence of r9883. */
30 static void
31 test_simple (void)
32 {
33 int t[4] = { 2, 3, -2, -3 }; /* test powers of 2 and non-powers of 2 */
34 int i;
35 int r1, r2;
36
37 for (i = 0; i < 4; i++)
38 RND_LOOP (r1)
39 RND_LOOP (r2)
40 {
41 mpfr_t b;
42 int p, err, prec, inex, c;
43
44 p = 12 + (randlimb() % (2 * GMP_NUMB_BITS));
45 err = p - 3;
46 prec = 4;
47 mpfr_init2 (b, p);
48 inex = mpfr_set_si (b, t[i], MPFR_RNDN);
49 MPFR_ASSERTN (inex == 0);
50 c = mpfr_can_round (b, err, (mpfr_rnd_t) r1, (mpfr_rnd_t) r2, prec);
51 /* If r1 == r2, we can round.
52 TODO: complete this test for r1 != r2. */
53 if (r1 == r2 && !c)
54 {
55 printf ("Error in test_simple for i=%d,"
56 " err=%d r1=%s, r2=%s, p=%d\n", i, err,
57 mpfr_print_rnd_mode ((mpfr_rnd_t) r1),
58 mpfr_print_rnd_mode ((mpfr_rnd_t) r2), p);
59 printf ("b="); mpfr_dump (b);
60 exit (1);
61 }
62 mpfr_clear (b);
63 }
64 }
65
66 #define MAX_LIMB_SIZE 100
67
68 static void
69 check_round_p (void)
70 {
71 mp_limb_t buf[MAX_LIMB_SIZE];
72 mp_size_t n, i;
73 mpfr_prec_t p;
74 mpfr_exp_t err;
75 int r1, r2;
76
77 for (n = 2 ; n <= MAX_LIMB_SIZE ; n++)
78 {
79 /* avoid mpn_random which leaks memory */
80 for (i = 0; i < n; i++)
81 buf[i] = randlimb ();
82 /* force the number to be normalized */
83 buf[n - 1] |= MPFR_LIMB_HIGHBIT;
84 p = randlimb() % ((n-1) * GMP_NUMB_BITS) + MPFR_PREC_MIN;
85 err = p + randlimb () % GMP_NUMB_BITS;
86 r1 = mpfr_round_p (buf, n, err, p);
87 r2 = mpfr_can_round_raw (buf, n, MPFR_SIGN_POS, err,
88 MPFR_RNDN, MPFR_RNDZ, p);
89 if (r1 != r2)
90 {
91 printf ("mpfr_round_p(%d) != mpfr_can_round(%d)!\n"
92 "bn = %ld, err0 = %ld, prec = %lu\nbp = ",
93 r1, r2, n, (long) err, (unsigned long) p);
94 gmp_printf ("%NX\n", buf, n);
95 exit (1);
96 }
97 }
98 }
99
100 /* check x=2^i with precision px, error at most 1, and target precision prec */
101 static void
102 test_pow2 (mpfr_exp_t i, mpfr_prec_t px, mpfr_rnd_t r1, mpfr_rnd_t r2,
103 mpfr_prec_t prec)
104 {
105 mpfr_t x;
106 int b, expected_b, b2;
107
108 mpfr_init2 (x, px);
109 mpfr_set_ui_2exp (x, 1, i, MPFR_RNDN);
110 b = !!mpfr_can_round (x, i+1, r1, r2, prec);
111 /* Note: If mpfr_can_round succeeds for both
112 (r1,r2) = (MPFR_RNDD,MPFR_RNDN) and
113 (r1,r2) = (MPFR_RNDU,MPFR_RNDN), then it should succeed for
114 (r1,r2) = (MPFR_RNDN,MPFR_RNDN). So, the condition on prec below
115 for r1 = MPFR_RNDN should be the most restrictive between those
116 for r1 = any directed rounding mode.
117 For r1 like MPFR_RNDA, the unrounded, unknown number may be anyone
118 in [2^i-1,i]. As both 2^i-1 and 2^i fit on i bits, one cannot round
119 in any precision >= i bits, hence the condition prec < i; prec = i-1
120 will work here for r2 = MPFR_RNDN thanks to the even-rounding rule
121 (and also with rounding ties away from zero). */
122 expected_b =
123 MPFR_IS_LIKE_RNDD (r1, MPFR_SIGN_POS) ?
124 (MPFR_IS_LIKE_RNDU (r2, MPFR_SIGN_POS) ? 0 : prec <= i) :
125 MPFR_IS_LIKE_RNDU (r1, MPFR_SIGN_POS) ?
126 (MPFR_IS_LIKE_RNDD (r2, MPFR_SIGN_POS) ? 0 : prec < i) :
127 (r2 != MPFR_RNDN ? 0 : prec < i);
128 if (b != expected_b)
129 {
130 printf ("Error for x=2^%d, px=%lu, err=%d, r1=%s, r2=%s, prec=%d\n",
131 (int) i, (unsigned long) px, (int) i + 1,
132 mpfr_print_rnd_mode (r1), mpfr_print_rnd_mode (r2), (int) prec);
133 printf ("Expected %d, got %d\n", expected_b, b);
134 exit (1);
135 }
136
137 if (r1 == MPFR_RNDN && r2 == MPFR_RNDZ)
138 {
139 /* Similar test to the one done in src/round_p.c
140 for MPFR_WANT_ASSERT >= 2. */
141 b2 = !!mpfr_round_p (MPFR_MANT(x), MPFR_LIMB_SIZE(x), i+1, prec);
142 if (b2 != b)
143 {
144 printf ("Error for x=2^%d, px=%lu, err=%d, prec=%d\n",
145 (int) i, (unsigned long) px, (int) i + 1, (int) prec);
146 printf ("mpfr_can_round gave %d, mpfr_round_p gave %d\n", b, b2);
147 exit (1);
148 }
149 }
150
151 mpfr_clear (x);
152 }
153
154 static void
155 check_can_round (void)
156 {
157 mpfr_t x, xinf, xsup, yinf, ysup;
158 int precx, precy, err;
159 int rnd1, rnd2;
160 int i, u[3] = { 0, 1, 256 };
161 int inex;
162 int expected, got;
163
164 mpfr_inits2 (4 * GMP_NUMB_BITS, x, xinf, xsup, yinf, ysup, (mpfr_ptr) 0);
165
166 for (precx = 3 * GMP_NUMB_BITS - 3; precx <= 3 * GMP_NUMB_BITS + 3; precx++)
167 {
168 mpfr_set_prec (x, precx);
169 for (precy = precx - 4; precy <= precx + 4; precy++)
170 {
171 mpfr_set_prec (yinf, precy);
172 mpfr_set_prec (ysup, precy);
173
174 for (i = 0; i <= 3; i++)
175 {
176 if (i <= 2)
177 {
178 /* Test x = 2^(precx - 1) + u */
179 mpfr_set_ui_2exp (x, 1, precx - 1, MPFR_RNDN);
180 mpfr_add_ui (x, x, u[i], MPFR_RNDN);
181 }
182 else
183 {
184 /* Test x = 2^precx - 1 */
185 mpfr_set_ui_2exp (x, 1, precx, MPFR_RNDN);
186 mpfr_sub_ui (x, x, 1, MPFR_RNDN);
187 }
188 MPFR_ASSERTN (mpfr_get_exp (x) == precx);
189
190 for (err = precy; err <= precy + 3; err++)
191 {
192 mpfr_set_ui_2exp (xinf, 1, precx - err, MPFR_RNDN);
193 inex = mpfr_add (xsup, x, xinf, MPFR_RNDN);
194 MPFR_ASSERTN (inex == 0);
195 inex = mpfr_sub (xinf, x, xinf, MPFR_RNDN);
196 MPFR_ASSERTN (inex == 0);
197 RND_LOOP (rnd1)
198 RND_LOOP (rnd2)
199 {
200 mpfr_set (yinf, MPFR_IS_LIKE_RNDD (rnd1, 1) ?
201 x : xinf, (mpfr_rnd_t) rnd2);
202 mpfr_set (ysup, MPFR_IS_LIKE_RNDU (rnd1, 1) ?
203 x : xsup, (mpfr_rnd_t) rnd2);
204 expected = !! mpfr_equal_p (yinf, ysup);
205 got = !! mpfr_can_round (x, err, (mpfr_rnd_t) rnd1,
206 (mpfr_rnd_t) rnd2, precy);
207 if (got != expected)
208 {
209 printf ("Error in check_can_round on:\n"
210 "precx=%d, precy=%d, i=%d, err=%d, "
211 "rnd1=%s, rnd2=%s: got %d\n",
212 precx, precy, i, err,
213 mpfr_print_rnd_mode ((mpfr_rnd_t) rnd1),
214 mpfr_print_rnd_mode ((mpfr_rnd_t) rnd2),
215 got);
216 printf ("x="); mpfr_dump (x);
217 exit (1);
218 }
219 }
220 }
221 }
222 }
223 }
224
225 mpfr_clears (x, xinf, xsup, yinf, ysup, (mpfr_ptr) 0);
226 }
227
228 int
229 main (void)
230 {
231 mpfr_t x;
232 mpfr_prec_t i, j, k;
233 int r1, r2;
234 int n;
235
236 tests_start_mpfr ();
237
238 test_simple ();
239
240 /* checks that rounds to nearest sets the last
241 bit to zero in case of equal distance */
242 mpfr_init2 (x, 59);
243 mpfr_set_str_binary (x, "-0.10010001010111000011110010111010111110000000111101100111111E663");
244 if (mpfr_can_round (x, 54, MPFR_RNDZ, MPFR_RNDZ, 53) != 0)
245 {
246 printf ("Error (1) in mpfr_can_round\n");
247 exit (1);
248 }
249
250 mpfr_set_str_binary (x, "-Inf");
251 if (mpfr_can_round (x, 2000, MPFR_RNDZ, MPFR_RNDZ, 2000) != 0)
252 {
253 printf ("Error (2) in mpfr_can_round\n");
254 exit (1);
255 }
256
257 mpfr_set_prec (x, 64);
258 mpfr_set_str_binary (x, "0.1011001000011110000110000110001111101011000010001110011000000000");
259 if (mpfr_can_round (x, 65, MPFR_RNDN, MPFR_RNDN, 54))
260 {
261 printf ("Error (3) in mpfr_can_round\n");
262 exit (1);
263 }
264
265 mpfr_set_prec (x, 137);
266 mpfr_set_str_binary (x, "-0.10111001101001010110011000110100111010011101101010010100101100001110000100111111011101010110001010111100100101110111100001000010000000000E-97");
267 if (mpfr_can_round (x, 132, MPFR_RNDU, MPFR_RNDZ, 128) == 0)
268 {
269 printf ("Error (4) in mpfr_can_round\n");
270 exit (1);
271 }
272
273 /* in the following, we can round but cannot determine the inexact flag */
274 mpfr_set_prec (x, 86);
275 mpfr_set_str_binary (x, "-0.11100100010011001111011010100111101010011000000000000000000000000000000000000000000000E-80");
276 if (mpfr_can_round (x, 81, MPFR_RNDU, MPFR_RNDZ, 44) == 0)
277 {
278 printf ("Error (5) in mpfr_can_round\n");
279 exit (1);
280 }
281
282 mpfr_set_prec (x, 62);
283 mpfr_set_str (x, "0.ff4ca619c76ba69", 16, MPFR_RNDZ);
284 for (i = 30; i < 99; i++)
285 for (j = 30; j < 99; j++)
286 for (r1 = 0; r1 < MPFR_RND_MAX; r1++)
287 for (r2 = 0; r2 < MPFR_RND_MAX; r2++)
288 {
289 /* test for assertions */
290 mpfr_can_round (x, i, (mpfr_rnd_t) r1, (mpfr_rnd_t) r2, j);
291 }
292
293 test_pow2 (32, 32, MPFR_RNDN, MPFR_RNDN, 32);
294 test_pow2 (174, 174, MPFR_RNDN, MPFR_RNDN, 174);
295 test_pow2 (174, 174, MPFR_RNDU, MPFR_RNDN, 174);
296 test_pow2 (176, 129, MPFR_RNDU, MPFR_RNDU, 174);
297 test_pow2 (176, 2, MPFR_RNDZ, MPFR_RNDZ, 174);
298 test_pow2 (176, 2, MPFR_RNDU, MPFR_RNDU, 176);
299
300 /* Tests for x = 2^i (E(x) = i+1) with error at most 1 = 2^0. */
301 for (n = 0; n < 100; n++)
302 {
303 i = (randlimb() % 200) + 4;
304 for (j = i - 2; j < i + 2; j++)
305 for (r1 = 0; r1 < MPFR_RND_MAX; r1++)
306 for (r2 = 0; r2 < MPFR_RND_MAX; r2++)
307 for (k = MPFR_PREC_MIN; k <= i + 2; k++)
308 test_pow2 (i, k, (mpfr_rnd_t) r1, (mpfr_rnd_t) r2, j);
309 }
310
311 mpfr_clear (x);
312
313 check_can_round ();
314
315 check_round_p ();
316
317 tests_end_mpfr ();
318 return 0;
319 }
320