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