1 /* Test file for mpfr_get_f.
2
3 Copyright 2005-2020 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 https://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 #define MPFR_NEED_MPF_INTERNALS
24 #include "mpfr-test.h"
25
26 #ifndef MPFR_USE_MINI_GMP
27
28 /* Test that there is no lost of accuracy when converting a mpfr_t number
29 into a mpf_t number (test with various precisions and exponents). */
30 static void
prec_test(void)31 prec_test (void)
32 {
33 int px, py;
34
35 for (py = 3; py <= 136; py++)
36 {
37 mpfr_t y1, y2, y3;
38
39 mpfr_init2 (y1, py);
40 mpfr_init2 (y2, py);
41 mpfr_init2 (y3, py);
42
43 for (px = 32; px <= 160; px += 32)
44 {
45 mpf_t x1, x2, x3;
46 int e;
47
48 mpf_init (x1);
49 mpf_init (x2);
50 mpf_init (x3);
51 mpfr_set_ui_2exp (y1, 1, py - 1, MPFR_RNDN);
52 mpfr_get_f (x1, y1, MPFR_RNDN); /* exact (power of 2) */
53 mpf_set (x2, x1);
54 mpfr_set (y2, y1, MPFR_RNDN);
55
56 for (e = py - 2; e >= 0; e--)
57 {
58 int inex;
59 mpf_div_2exp (x2, x2, 1);
60 mpf_add (x1, x1, x2);
61 mpfr_div_2ui (y2, y2, 1, MPFR_RNDN);
62 inex = mpfr_add (y1, y1, y2, MPFR_RNDN);
63 MPFR_ASSERTN (inex == 0);
64 mpfr_set_f (y3, x1, MPFR_RNDN);
65 if (! mpfr_equal_p (y1, y3))
66 break;
67 inex = mpfr_get_f (x3, y3, MPFR_RNDN);
68 if (mpf_cmp (x1, x3) != 0)
69 {
70 printf ("Error in prec_test (px = %d, py = %d, e = %d)\n",
71 px, py, e);
72 printf ("x1 = ");
73 mpf_out_str (stdout, 16, 0, x1);
74 printf ("\nx2 = ");
75 mpf_out_str (stdout, 16, 0, x2);
76 printf ("\n");
77 exit (1);
78 }
79 if (inex != 0)
80 {
81 printf ("Error in prec_test (px = %d, py = %d, e = %d)\n",
82 px, py, e);
83 printf ("wrong ternary value got: %+d, expected: 0\n",
84 inex);
85 exit (1);
86 }
87 }
88
89 mpf_clear (x1);
90 mpf_clear (x2);
91 mpf_clear (x3);
92 }
93
94 mpfr_clear (y1);
95 mpfr_clear (y2);
96 mpfr_clear (y3);
97 }
98 }
99
100 static void
special_test(void)101 special_test (void)
102 {
103 int inex;
104 mpf_t x;
105 mpfr_t y;
106
107 mpfr_init (y);
108 mpf_init (x);
109
110 mpfr_set_nan (y);
111 mpfr_clear_flags ();
112 mpfr_get_f (x, y, MPFR_RNDN);
113 if (! mpfr_erangeflag_p ())
114 {
115 printf ("Error: mpfr_get_f(NaN) should raise erange flag\n");
116 exit (1);
117 }
118
119 mpfr_set_inf (y, +1);
120 mpfr_clear_flags ();
121 inex = mpfr_get_f (x, y, MPFR_RNDN);
122 if (inex >= 0)
123 {
124 printf ("Error: mpfr_get_f(+Inf) should return a negative ternary"
125 "value\n");
126 exit (1);
127 }
128 if (! mpfr_erangeflag_p ())
129 {
130 printf ("Error: mpfr_get_f(+Inf) should raise erange flag\n");
131 exit (1);
132 }
133
134 mpfr_set_inf (y, -1);
135 mpfr_clear_flags ();
136 inex = mpfr_get_f (x, y, MPFR_RNDN);
137 if (inex <= 0)
138 {
139 printf ("Error: mpfr_get_f(-Inf) should return a positive ternary"
140 "value\n");
141 exit (1);
142 }
143 if (! mpfr_erangeflag_p ())
144 {
145 printf ("Error: mpfr_get_f(-Inf) should raise erange flag\n");
146 exit (1);
147 }
148
149 mpfr_set_ui (y, 0, MPFR_RNDN);
150 if (mpfr_get_f (x, y, MPFR_RNDN) != 0 || mpf_cmp_ui (x, 0))
151 {
152 printf ("Error: mpfr_get_f(+0) fails\n");
153 exit (1);
154 }
155
156 mpfr_set_ui (y, 0, MPFR_RNDN);
157 mpfr_neg (y, y, MPFR_RNDN);
158 if (mpfr_get_f (x, y, MPFR_RNDN) != 0 || mpf_cmp_ui (x, 0))
159 {
160 printf ("Error: mpfr_get_f(-0) fails\n");
161 exit (1);
162 }
163
164 mpfr_clear (y);
165 mpf_clear (x);
166 }
167
168 static void
ternary_test(void)169 ternary_test (void)
170 {
171 int prec;
172 int rnd;
173 int inex, expected_inex;
174 mpf_t x;
175 mpfr_t y;
176
177 mpf_init2 (x, 256);
178 mpfr_init2 (y, 256);
179
180 for (prec = MPFR_PREC_MIN; prec <= 256; prec++)
181 {
182
183 mpf_set_prec (x, prec);
184 mpfr_set_prec (y, PREC (x) * GMP_NUMB_BITS + 1);
185
186 /* y == 1 */
187 mpfr_set_ui_2exp (y, 1, prec, MPFR_RNDN);
188
189 RND_LOOP_NO_RNDF (rnd)
190 {
191 inex = mpfr_get_f (x, y, (mpfr_rnd_t) rnd);
192
193 if (inex != 0 || mpfr_cmp_f (y, x) != 0)
194 {
195 printf ("Error (1) in mpfr_get_f (x, y, %s)\nx = ",
196 mpfr_print_rnd_mode ((mpfr_rnd_t) rnd));
197 mpf_out_str (stdout, 2, 0, x);
198 printf ("\ny = ");
199 mpfr_dump (y);
200 if (inex != 0)
201 printf ("got ternary value = %+d, expected: 0\n", inex);
202
203 exit (1);
204 }
205 }
206
207 /* y == 1 + epsilon */
208 mpfr_nextbelow (y);
209
210 RND_LOOP_NO_RNDF (rnd)
211 {
212 switch (rnd)
213 {
214 case MPFR_RNDU: case MPFR_RNDA:
215 case MPFR_RNDN:
216 expected_inex = +1;
217 break;
218 default :
219 expected_inex = -1;
220 }
221
222 inex = mpfr_get_f (x, y, (mpfr_rnd_t) rnd);
223
224 if (! SAME_SIGN (expected_inex, inex)
225 || SAME_SIGN (expected_inex, mpfr_cmp_f (y, x)))
226 {
227 printf ("Error (2) in mpfr_get_f (x, y, %s)\nx = ",
228 mpfr_print_rnd_mode ((mpfr_rnd_t) rnd));
229 mpf_out_str (stdout, 2, 0, x);
230 printf ("\ny = ");
231 mpfr_dump (y);
232 if (! SAME_SIGN (expected_inex, inex))
233 printf ("got ternary value = %+d, expected: %+d\n",
234 inex, expected_inex);
235
236 exit (1);
237 }
238 }
239
240 /* y == positive random float */
241 mpfr_random2 (y, MPFR_LIMB_SIZE (y), 1024, RANDS);
242
243 RND_LOOP_NO_RNDF (rnd)
244 {
245 inex = mpfr_get_f (x, y, (mpfr_rnd_t) rnd);
246
247 if (! SAME_SIGN (inex, -mpfr_cmp_f (y, x)))
248 {
249 printf ("Error (3) in mpfr_get_f (x, y, %s)\nx = ",
250 mpfr_print_rnd_mode ((mpfr_rnd_t) rnd));
251 mpf_out_str (stdout, 2, 0, x);
252 printf ("\ny = ");
253 mpfr_dump (y);
254 printf ("got ternary value = %+d, expected: %+d\n",
255 inex, -mpfr_cmp_f (y, x));
256
257 exit (1);
258 }
259 }
260 }
261
262 mpf_clear (x);
263 mpfr_clear (y);
264 }
265
266 int
main(void)267 main (void)
268 {
269 mpf_t x;
270 mpfr_t y, z;
271 unsigned long i;
272 mpfr_exp_t e;
273 int inex;
274
275 tests_start_mpfr ();
276
277 mpfr_init (y);
278 mpfr_init (z);
279 mpf_init (x);
280
281 i = 1;
282 while (i)
283 {
284 mpfr_set_ui (y, i, MPFR_RNDN);
285 if (mpfr_get_f (x, y, MPFR_RNDN) != 0 || mpf_cmp_ui (x, i))
286 {
287 printf ("Error: mpfr_get_f(%lu) fails\n", i);
288 exit (1);
289 }
290 if (i <= - (unsigned long) LONG_MIN)
291 {
292 long j = i < - (unsigned long) LONG_MIN ? - (long) i : LONG_MIN;
293 mpfr_set_si (y, j, MPFR_RNDN);
294 if (mpfr_get_f (x, y, MPFR_RNDN) != 0 || mpf_cmp_si (x, j))
295 {
296 printf ("Error: mpfr_get_f(-%lu) fails\n", i);
297 exit (1);
298 }
299 }
300 i *= 2;
301 }
302
303 /* same tests, but with a larger precision for y, which requires to
304 round it */
305 mpfr_set_prec (y, 100);
306 i = 1;
307 while (i)
308 {
309 mpfr_set_ui (y, i, MPFR_RNDN);
310 inex = mpfr_get_f (x, y, MPFR_RNDN);
311 if (! SAME_SIGN (inex, - mpfr_cmp_f (y, x)) || mpf_cmp_ui (x, i))
312 {
313 printf ("Error: mpfr_get_f(%lu) fails\n", i);
314 exit (1);
315 }
316 mpfr_set_si (y, (signed long) -i, MPFR_RNDN);
317 inex = mpfr_get_f (x, y, MPFR_RNDN);
318 if (! SAME_SIGN (inex, - mpfr_cmp_f (y, x))
319 || mpf_cmp_si (x, (signed long) -i))
320 {
321 printf ("Error: mpfr_get_f(-%lu) fails\n", i);
322 exit (1);
323 }
324 i *= 2;
325 }
326
327 /* bug reported by Jim White */
328 for (e = 0; e <= 2 * GMP_NUMB_BITS; e++)
329 {
330 /* test with 2^(-e) */
331 mpfr_set_ui (y, 1, MPFR_RNDN);
332 mpfr_div_2ui (y, y, e, MPFR_RNDN);
333 inex = mpfr_get_f (x, y, MPFR_RNDN);
334 mpf_mul_2exp (x, x, e);
335 if (inex != 0 || mpf_cmp_ui (x, 1) != 0)
336 {
337 printf ("Error: mpfr_get_f(x,y,MPFR_RNDN) fails\n");
338 printf ("y=");
339 mpfr_dump (y);
340 printf ("x=");
341 mpf_div_2exp (x, x, e);
342 mpf_out_str (stdout, 2, 0, x);
343 exit (1);
344 }
345
346 /* test with 2^(e) */
347 mpfr_set_ui (y, 1, MPFR_RNDN);
348 mpfr_mul_2ui (y, y, e, MPFR_RNDN);
349 inex = mpfr_get_f (x, y, MPFR_RNDN);
350 mpf_div_2exp (x, x, e);
351 if (inex != 0 || mpf_cmp_ui (x, 1) != 0)
352 {
353 printf ("Error: mpfr_get_f(x,y,MPFR_RNDN) fails\n");
354 printf ("y=");
355 mpfr_dump (y);
356 printf ("x=");
357 mpf_mul_2exp (x, x, e);
358 mpf_out_str (stdout, 2, 0, x);
359 exit (1);
360 }
361 }
362
363 /* Bug reported by Yury Lukach on 2006-04-05 */
364 mpfr_set_prec (y, 32);
365 mpfr_set_prec (z, 32);
366 mpf_set_prec (x, 32);
367 mpfr_set_ui_2exp (y, 0xc1234567, -30, MPFR_RNDN);
368 mpfr_get_f (x, y, MPFR_RNDN);
369 inex = mpfr_set_f (z, x, MPFR_RNDN);
370 if (inex != 0 || ! mpfr_equal_p (y, z))
371 {
372 printf ("Error in mpfr_get_f:\n inex = %d, y = ", inex);
373 mpfr_dump (z);
374 printf ("Expected:\n inex = 0, y = ");
375 mpfr_dump (y);
376 exit (1);
377 }
378
379 mpfr_clear (y);
380 mpfr_clear (z);
381 mpf_clear (x);
382
383 special_test ();
384 prec_test ();
385 ternary_test ();
386
387 tests_end_mpfr ();
388 return 0;
389 }
390
391 #else
392
393 int
main(void)394 main (void)
395 {
396 return 77;
397 }
398
399 #endif
400