1 /* Test file for mpfr_set.
2
3 Copyright 2001-2023 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 #include "mpfr-test.h"
24
25 static int error;
26
27 #define PRINT_ERROR_IF(condition, text) \
28 do { \
29 if (condition) \
30 { \
31 printf ("%s", text); \
32 error = 1; \
33 } \
34 } while (0)
35
36
37 /* Maybe better create its own test file? */
38 static void
check_neg_special(void)39 check_neg_special (void)
40 {
41 mpfr_t x, y;
42 int inexact;
43 int s1, s2, s3;
44
45 mpfr_inits2 (53, x, y, (mpfr_ptr) 0);
46
47 MPFR_SET_NAN (x);
48 s1 = mpfr_signbit (x) != 0;
49
50 mpfr_clear_nanflag ();
51 inexact = mpfr_neg (y, x, MPFR_RNDN);
52 s2 = mpfr_signbit (y) != 0;
53 PRINT_ERROR_IF (!mpfr_nanflag_p (),
54 "ERROR: neg (NaN) doesn't set Nan flag (1).\n");
55 PRINT_ERROR_IF (!mpfr_nan_p (y) || inexact != 0,
56 "ERROR: neg (NaN) failed to set variable to NaN (1).\n");
57 PRINT_ERROR_IF (s1 == s2,
58 "ERROR: neg (NaN) doesn't correctly flip sign bit (1).\n");
59
60 mpfr_clear_nanflag ();
61 inexact = mpfr_neg (x, x, MPFR_RNDN);
62 s2 = mpfr_signbit (x) != 0;
63 PRINT_ERROR_IF (!mpfr_nanflag_p (),
64 "ERROR: neg (NaN) doesn't set Nan flag (2).\n");
65 PRINT_ERROR_IF (!mpfr_nan_p (x) || inexact != 0,
66 "ERROR: neg (NaN) failed to set variable to NaN (2).\n");
67 /* check following "bug" is fixed:
68 https://sympa.inria.fr/sympa/arc/mpfr/2017-11/msg00003.html */
69 PRINT_ERROR_IF (s1 == s2,
70 "ERROR: neg (NaN) doesn't correctly flip sign bit (2).\n");
71
72 mpfr_clear_nanflag ();
73 inexact = mpfr_neg (y, x, MPFR_RNDN);
74 s3 = mpfr_signbit (y) != 0;
75 PRINT_ERROR_IF (!mpfr_nanflag_p (),
76 "ERROR: neg (NaN) doesn't set Nan flag (3).\n");
77 PRINT_ERROR_IF (!mpfr_nan_p (y) || inexact != 0,
78 "ERROR: neg (NaN) failed to set variable to NaN (3).\n");
79 PRINT_ERROR_IF (s2 == s3,
80 "ERROR: neg (NaN) doesn't correctly flip sign bit (3).\n");
81
82 mpfr_clear_nanflag ();
83 inexact = mpfr_neg (x, x, MPFR_RNDN);
84 s3 = mpfr_signbit (x) != 0;
85 PRINT_ERROR_IF (!mpfr_nanflag_p (),
86 "ERROR: neg (NaN) doesn't set Nan flag (4).\n");
87 PRINT_ERROR_IF (!mpfr_nan_p (x) || inexact != 0,
88 "ERROR: neg (NaN) failed to set variable to NaN (4).\n");
89 PRINT_ERROR_IF (s2 == s3,
90 "ERROR: neg (NaN) doesn't correctly flip sign bit (4).\n");
91
92 mpfr_clears (x, y, (mpfr_ptr) 0);
93 }
94
95 static void
check_special(void)96 check_special (void)
97 {
98 mpfr_t x, y;
99 int inexact;
100 int s1, s2;
101
102 mpfr_inits2 (53, x, y, (mpfr_ptr) 0);
103
104 mpfr_set_inf (x, 1);
105 PRINT_ERROR_IF (!mpfr_inf_p (x) || mpfr_sgn (x) < 0,
106 "ERROR: mpfr_set_inf failed to set variable to +inf [1].\n");
107 mpfr_set_inf (x, INT_MAX);
108 PRINT_ERROR_IF (!mpfr_inf_p (x) || mpfr_sgn (x) < 0,
109 "ERROR: mpfr_set_inf failed to set variable to +inf [2].\n");
110 mpfr_set_inf (x, 0);
111 PRINT_ERROR_IF (!mpfr_inf_p (x) || mpfr_sgn (x) < 0,
112 "ERROR: mpfr_set_inf failed to set variable to +inf [3].\n");
113 inexact = mpfr_set (y, x, MPFR_RNDN);
114 PRINT_ERROR_IF (!mpfr_inf_p (y) || mpfr_sgn (y) < 0 || inexact != 0,
115 "ERROR: mpfr_set failed to set variable to +infinity.\n");
116
117 inexact = mpfr_set_ui (y, 0, MPFR_RNDN);
118 PRINT_ERROR_IF (MPFR_NOTZERO (y) || MPFR_IS_NEG (y) || inexact != 0,
119 "ERROR: mpfr_set_ui failed to set variable to +0.\n");
120
121 mpfr_set_inf (x, -1);
122 PRINT_ERROR_IF (!mpfr_inf_p (x) || mpfr_sgn (x) > 0,
123 "ERROR: mpfr_set_inf failed to set variable to -inf [1].\n");
124 mpfr_set_inf (x, INT_MIN);
125 PRINT_ERROR_IF (!mpfr_inf_p (x) || mpfr_sgn (x) > 0,
126 "ERROR: mpfr_set_inf failed to set variable to -inf [2].\n");
127 inexact = mpfr_set (y, x, MPFR_RNDN);
128 PRINT_ERROR_IF (!mpfr_inf_p (y) || mpfr_sgn (y) > 0 || inexact != 0,
129 "ERROR: mpfr_set failed to set variable to -infinity.\n");
130
131 mpfr_set_zero (x, 1);
132 PRINT_ERROR_IF (MPFR_NOTZERO (x) || MPFR_IS_NEG (x),
133 "ERROR: mpfr_set_zero failed to set variable to +0 [1].\n");
134 mpfr_set_zero (x, INT_MAX);
135 PRINT_ERROR_IF (MPFR_NOTZERO (x) || MPFR_IS_NEG (x),
136 "ERROR: mpfr_set_zero failed to set variable to +0 [2].\n");
137 mpfr_set_zero (x, 0);
138 PRINT_ERROR_IF (MPFR_NOTZERO (x) || MPFR_IS_NEG (x),
139 "ERROR: mpfr_set_zero failed to set variable to +0 [3].\n");
140 inexact = mpfr_set (y, x, MPFR_RNDN);
141 PRINT_ERROR_IF (MPFR_NOTZERO (y) || MPFR_IS_NEG (y) || inexact != 0,
142 "ERROR: mpfr_set failed to set variable to +0.\n");
143
144 mpfr_set_zero (x, -1);
145 PRINT_ERROR_IF (MPFR_NOTZERO (x) || MPFR_IS_POS (x),
146 "ERROR: mpfr_set_zero failed to set variable to -0 [1].\n");
147 mpfr_set_zero (x, INT_MIN);
148 PRINT_ERROR_IF (MPFR_NOTZERO (x) || MPFR_IS_POS (x),
149 "ERROR: mpfr_set_zero failed to set variable to -0 [2].\n");
150 inexact = mpfr_set (y, x, MPFR_RNDN);
151 PRINT_ERROR_IF (MPFR_NOTZERO (y) || MPFR_IS_POS (y) || inexact != 0,
152 "ERROR: mpfr_set failed to set variable to -0.\n");
153
154 /* NaN tests */
155
156 mpfr_set_nan (x);
157 PRINT_ERROR_IF (!mpfr_nan_p (x),
158 "ERROR: mpfr_set_nan failed to set variable to NaN.\n");
159 s1 = mpfr_signbit (x) != 0;
160
161 mpfr_clear_nanflag ();
162 inexact = mpfr_set (y, x, MPFR_RNDN);
163 s2 = mpfr_signbit (y) != 0;
164 PRINT_ERROR_IF (!mpfr_nanflag_p (),
165 "ERROR: mpfr_set doesn't set Nan flag (1).\n");
166 PRINT_ERROR_IF (!mpfr_nan_p (y) || inexact != 0,
167 "ERROR: mpfr_set failed to set variable to NaN (1).\n");
168 PRINT_ERROR_IF (s1 != s2,
169 "ERROR: mpfr_set doesn't preserve the sign bit (1).\n");
170
171 mpfr_clear_nanflag ();
172 inexact = mpfr_set (x, x, MPFR_RNDN);
173 s2 = mpfr_signbit (x) != 0;
174 PRINT_ERROR_IF (!mpfr_nanflag_p (),
175 "ERROR: mpfr_set doesn't set Nan flag (2).\n");
176 PRINT_ERROR_IF (!mpfr_nan_p (x) || inexact != 0,
177 "ERROR: mpfr_set failed to set variable to NaN (2).\n");
178 PRINT_ERROR_IF (s1 != s2,
179 "ERROR: mpfr_set doesn't preserve the sign bit (2).\n");
180
181 MPFR_CHANGE_SIGN (x);
182 s1 = !s1;
183
184 mpfr_clear_nanflag ();
185 inexact = mpfr_set (y, x, MPFR_RNDN);
186 s2 = mpfr_signbit (y) != 0;
187 PRINT_ERROR_IF (!mpfr_nanflag_p (),
188 "ERROR: mpfr_set doesn't set Nan flag (3).\n");
189 PRINT_ERROR_IF (!mpfr_nan_p (y) || inexact != 0,
190 "ERROR: mpfr_set failed to set variable to NaN (3).\n");
191 PRINT_ERROR_IF (s1 != s2,
192 "ERROR: mpfr_set doesn't preserve the sign bit (3).\n");
193
194 mpfr_clear_nanflag ();
195 inexact = mpfr_set (x, x, MPFR_RNDN);
196 s2 = mpfr_signbit (x) != 0;
197 PRINT_ERROR_IF (!mpfr_nanflag_p (),
198 "ERROR: mpfr_set doesn't set Nan flag (4).\n");
199 PRINT_ERROR_IF (!mpfr_nan_p (x) || inexact != 0,
200 "ERROR: mpfr_set failed to set variable to NaN (4).\n");
201 PRINT_ERROR_IF (s1 != s2,
202 "ERROR: mpfr_set doesn't preserve the sign bit (4).\n");
203
204 mpfr_clears (x, y, (mpfr_ptr) 0);
205 }
206
207 static void
check_ternary_value(void)208 check_ternary_value (void)
209 {
210 int k, p, q, rnd;
211 int inexact, cmp;
212 mpfr_t x, y;
213
214 mpfr_init (x);
215 mpfr_init (y);
216 for (p=2; p<500; p++)
217 {
218 mpfr_set_prec (x, p);
219 mpfr_urandomb (x, RANDS);
220 if (RAND_BOOL ())
221 mpfr_neg (x, x, MPFR_RNDN);
222 for (q=2; q<2*p; q++)
223 {
224 mpfr_set_prec (y, q);
225 RND_LOOP (rnd)
226 {
227 if (rnd == MPFR_RNDF) /* the test below makes no sense */
228 continue;
229 for (k = 0; k < 3; k++)
230 {
231 int a = 0, b = 0, c = 0;
232
233 switch (k)
234 {
235 case 0:
236 inexact = mpfr_set (y, x, (mpfr_rnd_t) rnd);
237 break;
238 case 1:
239 inexact = (mpfr_set) (y, x, (mpfr_rnd_t) rnd);
240 break;
241 case 2:
242 #ifdef IGNORE_CPP_COMPAT
243 #pragma GCC diagnostic push
244 #pragma GCC diagnostic ignored "-Wc++-compat"
245 #endif
246 inexact = mpfr_set ((a++, VOIDP_CAST(y)),
247 (b++, VOIDP_CAST(x)),
248 (c++, (mpfr_rnd_t) rnd));
249 #ifdef IGNORE_CPP_COMPAT
250 #pragma GCC diagnostic pop
251 #endif
252 MPFR_ASSERTN (a == 1);
253 MPFR_ASSERTN (b == 1);
254 MPFR_ASSERTN (c == 1);
255 break;
256 }
257 cmp = mpfr_cmp (y, x);
258 if (((inexact == 0) && (cmp != 0)) ||
259 ((inexact > 0) && (cmp <= 0)) ||
260 ((inexact < 0) && (cmp >= 0)))
261 {
262 printf ("Wrong ternary value in mpfr_set for %s (%d):"
263 " expected %d, got %d\n",
264 mpfr_print_rnd_mode ((mpfr_rnd_t) rnd),
265 k, cmp, inexact);
266 exit (1);
267 }
268 }
269 }
270 }
271 }
272 mpfr_clear (x);
273 mpfr_clear (y);
274 }
275
276 static void
test_set_1_2(void)277 test_set_1_2 (void)
278 {
279 mpfr_t u, v, zz, z;
280 int inex;
281
282 /* (8,16)-bit test */
283 mpfr_inits2 (16, u, v, zz, (mpfr_ptr) 0);
284 mpfr_init2 (z, 8);
285 mpfr_set_str_binary (u, "0.1100001100011010E-1");
286 mpfr_set_str_binary (v, "0.1100010101110010E0");
287 /* u + v = 1.0010011011111111 */
288 inex = mpfr_add (zz, u, v, MPFR_RNDN);
289 MPFR_ASSERTN(inex > 0);
290 mpfr_set_str_binary (u, "1.001001110000000");
291 MPFR_ASSERTN(mpfr_equal_p (zz, u));
292 inex = mpfr_set_1_2 (z, zz, MPFR_RNDN, inex);
293 /* we should have z = 1.0010011 and inex < 0 */
294 MPFR_ASSERTN(inex < 0);
295 mpfr_set_str_binary (u, "1.0010011");
296 MPFR_ASSERTN(mpfr_equal_p (z, u));
297 mpfr_clears (u, v, zz, z, (mpfr_ptr) 0);
298
299 /* (16,32)-bit test:
300 * take for v a random 32-bit number in [1/2,1), here 2859611790/2^32
301 * take for z a random 16-bit number in [1,2), less than 2*v,
302 with last bit 0, here we take z = 40900/2^15
303 * take u = z-v-1/2^16-1/2^32 */
304 mpfr_inits2 (32, u, v, zz, (mpfr_ptr) 0);
305 mpfr_init2 (z, 16);
306 mpfr_set_str_binary (u, "0.10010101000101001100100101110001");
307 mpfr_set_str_binary (v, "0.10101010011100100011011010001110");
308 /* u + v = 1.00111111100001101111111111111111 */
309 inex = mpfr_add (zz, u, v, MPFR_RNDN);
310 MPFR_ASSERTN(inex > 0);
311 mpfr_set_str_binary (u, "1.0011111110000111");
312 MPFR_ASSERTN(mpfr_equal_p (zz, u));
313 inex = mpfr_set_1_2 (z, zz, MPFR_RNDN, inex);
314 /* we should have z = 1.001111111000011 and inex < 0 */
315 MPFR_ASSERTN(inex < 0);
316 mpfr_set_str_binary (u, "1.001111111000011");
317 MPFR_ASSERTN(mpfr_equal_p (z, u));
318 mpfr_clears (u, v, zz, z, (mpfr_ptr) 0);
319
320 /* (32,64)-bit test:
321 * take for v a random 64-bit number in [1/2,1),
322 here v = 13687985014345662879/2^64
323 * take for z a random 32-bit number in [1,2), less than 2*v,
324 with last bit 0, here we take z = 2871078774/2^31
325 * take u = z-v-1/2^32-1/2^64 */
326 mpfr_inits2 (64, u, v, zz, (mpfr_ptr) 0);
327 mpfr_init2 (z, 32);
328 mpfr_set_str_binary (u, "0.10011000010011001110000100010001110010010000111001111110011");
329 mpfr_set_str_binary (v, "0.1011110111110101011111011101100100110110111100011000000110011111");
330 /* u + v = 1.0101011001000010010111101110101011111111111111111111111111111111 */
331 inex = mpfr_add (zz, u, v, MPFR_RNDN);
332 MPFR_ASSERTN(inex > 0);
333 mpfr_set_str_binary (u, "1.01010110010000100101111011101011");
334 MPFR_ASSERTN(mpfr_equal_p (zz, u));
335 inex = mpfr_set_1_2 (z, zz, MPFR_RNDN, inex);
336 /* we should have z = 1.0101011001000010010111101110101 and inex < 0 */
337 MPFR_ASSERTN(inex < 0);
338 mpfr_set_str_binary (u, "1.0101011001000010010111101110101");
339 MPFR_ASSERTN(mpfr_equal_p (z, u));
340 mpfr_clears (u, v, zz, z, (mpfr_ptr) 0);
341
342 /* (64,128)-bit test:
343 * take for v a random 128-bit number in [1/2,1),
344 here v = 322263811942091240216761391118876232409/2^128
345 * take for z a random 64-bit number in [1,2), less than 2*v,
346 with last bit 0, here we take z = 16440347967874738276/2^63
347 * take u = z-v-1/2^64-1/2^128 */
348 mpfr_inits2 (128, u, v, zz, (mpfr_ptr) 0);
349 mpfr_init2 (z, 64);
350 mpfr_set_str_binary (u, "0.1101010111011101111100100001011111111000010011011001000101111010110101101101011011100110101001010001101011011110101101010010011");
351 mpfr_set_str_binary (v, "0.11110010011100011100000010100110100010011010110010111111010011000010100100101001000110010101101011100101001000010100101011011001");
352 inex = mpfr_add (zz, u, v, MPFR_RNDN);
353 MPFR_ASSERTN(inex > 0);
354 mpfr_set_str_binary (u, "1.1100100001001111101100101011111010000001111110100101000011000111");
355 MPFR_ASSERTN(mpfr_equal_p (zz, u));
356 inex = mpfr_set_1_2 (z, zz, MPFR_RNDN, inex);
357 MPFR_ASSERTN(inex < 0);
358 mpfr_set_str_binary (u, "1.1100100001001111101100101011111010000001111110100101000011000110");
359 MPFR_ASSERTN(mpfr_equal_p (z, u));
360 mpfr_clears (u, v, zz, z, (mpfr_ptr) 0);
361 }
362
363 #define TEST_FUNCTION mpfr_set
364 #include "tgeneric.c"
365
366 int
main(void)367 main (void)
368 {
369 mpfr_t x, y, z, u;
370 int inexact;
371 mpfr_exp_t emax;
372
373 tests_start_mpfr ();
374
375 test_set_1_2 ();
376
377 /* Default : no error */
378 error = 0;
379
380 /* check prototypes of mpfr_init_set_* */
381 inexact = mpfr_init_set_si (x, -1, MPFR_RNDN);
382 MPFR_ASSERTN (inexact == 0);
383 inexact = mpfr_init_set (y, x, MPFR_RNDN);
384 MPFR_ASSERTN (inexact == 0);
385 inexact = mpfr_init_set_ui (z, 1, MPFR_RNDN);
386 MPFR_ASSERTN (inexact == 0);
387 inexact = mpfr_init_set_d (u, 1.0, MPFR_RNDN);
388 MPFR_ASSERTN (inexact == 0);
389
390 emax = mpfr_get_emax ();
391 set_emax (0);
392 mpfr_set_prec (x, 3);
393 mpfr_set_str_binary (x, "0.111");
394 mpfr_set_prec (y, 2);
395 mpfr_set (y, x, MPFR_RNDU);
396 if (!(MPFR_IS_INF (y) && MPFR_IS_POS (y)))
397 {
398 printf ("Error for y=x=0.111 with px=3, py=2 and emax=0\nx=");
399 mpfr_dump (x);
400 printf ("y=");
401 mpfr_dump (y);
402 exit (1);
403 }
404
405 set_emax (emax);
406
407 mpfr_set_prec (y, 11);
408 mpfr_set_str_binary (y, "0.11111111100E-8");
409 mpfr_set_prec (x, 2);
410 mpfr_set (x, y, MPFR_RNDN);
411 mpfr_set_str_binary (y, "1.0E-8");
412 if (mpfr_cmp (x, y))
413 {
414 printf ("Error for y=0.11111111100E-8, prec=2, rnd=MPFR_RNDN\n");
415 exit (1);
416 }
417
418 mpfr_clear (x);
419 mpfr_clear (y);
420 mpfr_clear (z);
421 mpfr_clear (u);
422
423 check_ternary_value ();
424 check_special ();
425 check_neg_special ();
426
427 test_generic (MPFR_PREC_MIN, 1000, 10);
428
429 tests_end_mpfr ();
430 return error;
431 }
432