1 /* Test file for mpfr_exp10.
2
3 Copyright 2007-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 #define TEST_FUNCTION mpfr_exp10
26 #define TEST_RANDOM_EMIN -36
27 #define TEST_RANDOM_EMAX 36
28 #include "tgeneric.c"
29
30 static void
special_overflow(void)31 special_overflow (void)
32 {
33 mpfr_t x, y;
34 int inex;
35 mpfr_exp_t emin, emax;
36
37 emin = mpfr_get_emin ();
38 emax = mpfr_get_emax ();
39
40 set_emin (-125);
41 set_emax (128);
42
43 mpfr_init2 (x, 24);
44 mpfr_init2 (y, 24);
45
46 mpfr_set_str_binary (x, "0.101100100000000000110100E15");
47 inex = mpfr_exp10 (y, x, MPFR_RNDN);
48 if (!mpfr_inf_p (y) || inex <= 0)
49 {
50 printf ("Overflow error.\n");
51 mpfr_dump (y);
52 printf ("inex = %d\n", inex);
53 exit (1);
54 }
55
56 mpfr_clear (y);
57 mpfr_clear (x);
58 set_emin (emin);
59 set_emax (emax);
60 }
61
62 static void
emax_m_eps(void)63 emax_m_eps (void)
64 {
65 if (mpfr_get_emax () <= LONG_MAX)
66 {
67 mpfr_t x, y;
68 int inex, ov;
69
70 mpfr_init2 (x, sizeof(mpfr_exp_t) * CHAR_BIT * 4);
71 mpfr_init2 (y, 8);
72 mpfr_set_si (x, mpfr_get_emax (), MPFR_RNDN);
73
74 mpfr_clear_flags ();
75 inex = mpfr_exp10 (y, x, MPFR_RNDN);
76 ov = mpfr_overflow_p ();
77 if (!ov || !mpfr_inf_p (y) || inex <= 0)
78 {
79 printf ("Overflow error for x = emax, MPFR_RNDN.\n");
80 mpfr_dump (y);
81 printf ("inex = %d, %soverflow\n", inex, ov ? "" : "no ");
82 exit (1);
83 }
84
85 mpfr_clear (x);
86 mpfr_clear (y);
87 }
88 }
89
90 static void
exp_range(void)91 exp_range (void)
92 {
93 mpfr_t x;
94 mpfr_exp_t emin;
95
96 emin = mpfr_get_emin ();
97 set_emin (3);
98 mpfr_init2 (x, 16);
99 mpfr_set_ui (x, 4, MPFR_RNDN);
100 mpfr_exp10 (x, x, MPFR_RNDN);
101 set_emin (emin);
102 if (mpfr_nan_p (x) || mpfr_cmp_ui (x, 10000) != 0)
103 {
104 printf ("Error in mpfr_exp10 for x = 4, with emin = 3\n");
105 printf ("Expected 10000, got ");
106 mpfr_out_str (stdout, 2, 0, x, MPFR_RNDN);
107 printf ("\n");
108 exit (1);
109 }
110 mpfr_clear (x);
111 }
112
113 static void
overfl_exp10_0(void)114 overfl_exp10_0 (void)
115 {
116 mpfr_t x, y;
117 int emax, i, inex, rnd, err = 0;
118 mpfr_exp_t old_emax;
119
120 old_emax = mpfr_get_emax ();
121
122 mpfr_init2 (x, 8);
123 mpfr_init2 (y, 8);
124
125 for (emax = -1; emax <= 0; emax++)
126 {
127 mpfr_set_ui_2exp (y, 1, emax, MPFR_RNDN);
128 mpfr_nextbelow (y);
129 set_emax (emax); /* 1 is not representable. */
130 /* and if emax < 0, 1 - eps is not representable either. */
131 for (i = -1; i <= 1; i++)
132 RND_LOOP (rnd)
133 {
134 mpfr_set_si_2exp (x, i, -512 * ABS (i), MPFR_RNDN);
135 mpfr_clear_flags ();
136 inex = mpfr_exp10 (x, x, (mpfr_rnd_t) rnd);
137 if ((i >= 0 || emax < 0 || rnd == MPFR_RNDN || rnd == MPFR_RNDU) &&
138 ! mpfr_overflow_p ())
139 {
140 printf ("Error in overfl_exp10_0 (i = %d, rnd = %s):\n"
141 " The overflow flag is not set.\n",
142 i, mpfr_print_rnd_mode ((mpfr_rnd_t) rnd));
143 err = 1;
144 }
145 if (rnd == MPFR_RNDZ || rnd == MPFR_RNDD)
146 {
147 if (inex >= 0)
148 {
149 printf ("Error in overfl_exp10_0 (i = %d, rnd = %s):\n"
150 " The inexact value must be negative.\n",
151 i, mpfr_print_rnd_mode ((mpfr_rnd_t) rnd));
152 err = 1;
153 }
154 if (! mpfr_equal_p (x, y))
155 {
156 printf ("Error in overfl_exp10_0 (i = %d, rnd = %s):\n"
157 " Got ", i,
158 mpfr_print_rnd_mode ((mpfr_rnd_t) rnd));
159 mpfr_dump (x);
160 printf (" instead of 0.11111111E%d.\n", emax);
161 err = 1;
162 }
163 }
164 else if (rnd != MPFR_RNDF)
165 {
166 if (inex <= 0)
167 {
168 printf ("Error in overfl_exp10_0 (i = %d, rnd = %s):\n"
169 " The inexact value must be positive.\n",
170 i, mpfr_print_rnd_mode ((mpfr_rnd_t) rnd));
171 err = 1;
172 }
173 if (! (mpfr_inf_p (x) && MPFR_IS_POS (x)))
174 {
175 printf ("Error in overfl_exp10_0 (i = %d, rnd = %s):\n"
176 " Got ", i,
177 mpfr_print_rnd_mode ((mpfr_rnd_t) rnd));
178 mpfr_dump (x);
179 printf (" instead of +Inf.\n");
180 err = 1;
181 }
182 }
183 }
184 set_emax (old_emax);
185 }
186
187 if (err)
188 exit (1);
189 mpfr_clear (x);
190 mpfr_clear (y);
191 }
192
193 /* Bug in mpfr_pow_general found by ofuf_thresholds (on 2023-02-13 for
194 a 32-bit exponent, changed on 2023-03-06 for a 64-bit exponent too),
195 fixed in commit b62966df913f73f08b3c5252e1d0c702bc20442f.
196 With a 32-bit exponent, failure for i=0.
197 expected 0.1111E1073741823
198 got @Inf@
199 expected flags = inexact (8)
200 got flags = overflow inexact (10)
201 With a 64-bit exponent, failure for i=1.
202 expected 0.11111111111111111111111E4611686018427387903
203 got @Inf@
204 expected flags = inexact (8)
205 got flags = overflow inexact (10)
206 Note: ofuf_thresholds was added to the master branch, but for the
207 time being, there are issues with these tests.
208 */
209 static void
bug20230213(void)210 bug20230213 (void)
211 {
212 const char *s[2] = {
213 "0x1.34413504b3ccdbd5dd8p+28",
214 "0x1.34413509f79fef2c4e0dd14a7ae0ecfbacdbp+60"
215 };
216 mpfr_t x1, x2, y1, y2;
217 mpfr_prec_t px[2] = { 74, 147 };
218 mpfr_prec_t py[2] = { 4, 23 };
219 mpfr_exp_t old_emax, emax;
220 mpfr_flags_t flags1, flags2;
221 int i;
222
223 old_emax = mpfr_get_emax ();
224
225 for (i = 0; i < 2; i++)
226 {
227 if (i != 0)
228 set_emax (MPFR_EMAX_MAX);
229
230 emax = mpfr_get_emax ();
231
232 mpfr_inits2 (px[i], x1, x2, (mpfr_ptr) 0);
233 mpfr_inits2 (py[i], y1, y2, (mpfr_ptr) 0);
234
235 mpfr_setmax (y1, emax);
236 mpfr_log10 (x1, y1, MPFR_RNDD);
237 mpfr_set_str (x2, s[i], 0, MPFR_RNDN);
238 /* For i == 0, emax == 2^30, so that the value can be checked.
239 For i != 0, check the value for the case emax == 2^62.
240 The "0UL" ensures that the shifts are valid. */
241 if (i == 0 || (((0UL + MPFR_EMAX_MAX) >> 31) >> 30) == 1)
242 {
243 /* printf ("Checking x1 for i=%d\n", i); */
244 MPFR_ASSERTN (mpfr_equal_p (x1, x2));
245 }
246
247 /* Let MAXF be the maximum finite value (y1 above).
248 Since x1 < log10(MAXF), one should have exp10(x1) < MAXF, and
249 therefore, y2 = RU(exp10(x1)) <= RU(MAXF) = MAXF (no overflow). */
250 flags1 = MPFR_FLAGS_INEXACT;
251 mpfr_clear_flags ();
252 mpfr_exp10 (y2, x1, MPFR_RNDU);
253 flags2 = __gmpfr_flags;
254
255 if (! (mpfr_lessequal_p (y2, y1) && flags2 == flags1))
256 {
257 printf ("Error in bug20230213 for i=%d\n", i);
258 printf ("emax = %" MPFR_EXP_FSPEC "d\n", (mpfr_eexp_t) emax);
259 printf ("expected "); mpfr_dump (y1);
260 printf ("got "); mpfr_dump (y2);
261 printf ("expected flags =");
262 flags_out (flags1);
263 printf ("got flags =");
264 flags_out (flags2);
265 exit (1);
266 }
267
268 mpfr_clears (x1, x2, y1, y2, (mpfr_ptr) 0);
269 }
270
271 set_emax (old_emax);
272 }
273
274 /* Bug in mpfr_pow_general in precision 1 in the particular case of
275 rounding to nearest, z * 2^k = 2^(emin - 2) and real result larger
276 than this value; fixed in ff5012b61d5e5fee5156c57b8aa8fc1739c2a771
277 (which is simplified in 4f5de980be290687ac1409aa02873e9e0dd1a030);
278 initially found by ofuf_thresholds (though the test was incorrect).
279 With a 32-bit exponent, failure for i=0.
280 With a 64-bit exponent, failure for i=1.
281 The result was correct, but the underflow flag was missing.
282 Note: ofuf_thresholds was added to the master branch, but for the
283 time being, there are issues with these tests.
284 */
285 static void
bug20230427(void)286 bug20230427 (void)
287 {
288 const char *s[2] = {
289 "-0.1001101000100000100110101000011E29",
290 "-0.100110100010000010011010100001001111101111001111111101111001101E61"
291 };
292 mpfr_t x, y, z, t1, t2;
293 mpfr_exp_t old_emin;
294 mpfr_flags_t flags, ex_flags;
295 int i, inex;
296
297 old_emin = mpfr_get_emin ();
298
299 mpfr_init2 (x, 63);
300 mpfr_inits2 (1, y, z, (mpfr_ptr) 0);
301 mpfr_inits2 (128, t1, t2, (mpfr_ptr) 0);
302
303 for (i = 0; i < 2; i++)
304 {
305 if (i == 0)
306 {
307 /* Basic check: the default emin should be -2^30 (exactly). */
308 if (mpfr_get_emin () != -1073741823)
309 abort ();
310 }
311 else
312 {
313 /* This test assumes that MPFR_EMIN_MIN = -2^62 (exactly).
314 The "0UL" ensures that the shifts are valid. */
315 if ((((0UL - MPFR_EMIN_MIN) >> 31) >> 30) != 1)
316 break;
317
318 set_emin (MPFR_EMIN_MIN);
319 }
320
321 mpfr_set_str_binary (x, s[i]);
322
323 /* We will test 10^x rounded to nearest in precision 1.
324 Check that 2^(emin - 2) < 10^x < (3/2) * 2^(emin - 2).
325 This is approximate, but by outputting the values, one can check
326 that one is not too close to the boundaries:
327 emin - 2 = -4611686018427387905
328 log2(10^x) ~= -4611686018427387904.598
329 emin - 2 + log2(3/2) ~= -4611686018427387904.415
330 Thus the result should be the smallest positive number 2^(emin - 1)
331 because 10^x is closer to this number than to 0, the midpoint being
332 2^(emin - 2). And there should be an underflow in precision 1 because
333 the result rounded to nearest in an unbounded exponent range should
334 have been 2^(emin - 2), the midpoint being (3/2) * 2^(emin - 2).
335 */
336 mpfr_set_ui (t1, 10, MPFR_RNDN);
337 mpfr_log2 (t2, t1, MPFR_RNDN);
338 mpfr_mul (t1, t2, x, MPFR_RNDN);
339 inex = mpfr_set_exp_t (t2, mpfr_get_emin () - 2, MPFR_RNDN);
340 MPFR_ASSERTN (inex == 0);
341 MPFR_ASSERTN (mpfr_greater_p (t1, t2)); /* log2(10^x) > emin - 2 */
342 inex = mpfr_sub (t1, t1, t2, MPFR_RNDN);
343 MPFR_ASSERTN (inex == 0);
344 mpfr_set_ui (t2, 3, MPFR_RNDN);
345 mpfr_log2 (t2, t2, MPFR_RNDN);
346 mpfr_sub_ui (t2, t2, 1, MPFR_RNDN); /* log2(3/2) */
347 MPFR_ASSERTN (mpfr_less_p (t1, t2));
348
349 mpfr_clear_flags ();
350 mpfr_exp10 (y, x, MPFR_RNDN);
351 flags = __gmpfr_flags;
352 ex_flags = MPFR_FLAGS_UNDERFLOW | MPFR_FLAGS_INEXACT;
353
354 mpfr_setmin (z, mpfr_get_emin ()); /* z = 0.1@emin */
355 if (! (mpfr_equal_p (y, z) && flags == ex_flags))
356 {
357 printf ("Error in bug20230427 for i=%d\n", i);
358 printf ("expected "); mpfr_dump (z);
359 printf ("got "); mpfr_dump (y);
360 printf ("emin = %" MPFR_EXP_FSPEC "d\n",
361 (mpfr_eexp_t) mpfr_get_emin ());
362 printf ("expected flags =");
363 flags_out (ex_flags);
364 printf ("got flags =");
365 flags_out (flags);
366 exit (1);
367 }
368 }
369
370 mpfr_clears (x, y, z, t1, t2, (mpfr_ptr) 0);
371 set_emin (old_emin);
372 }
373
374 int
main(int argc,char * argv[])375 main (int argc, char *argv[])
376 {
377 mpfr_t x, y;
378 mpfr_exp_t emin, emax;
379 int inex, ov;
380
381 tests_start_mpfr ();
382
383 bug20230213 ();
384 bug20230427 ();
385
386 special_overflow ();
387 emax_m_eps ();
388 exp_range ();
389
390 mpfr_init (x);
391 mpfr_init (y);
392
393 mpfr_set_ui (x, 4, MPFR_RNDN);
394 mpfr_exp10 (y, x, MPFR_RNDN);
395 if (mpfr_cmp_ui (y, 10000) != 0)
396 {
397 printf ("Error for 10^4, MPFR_RNDN\n");
398 exit (1);
399 }
400 mpfr_exp10 (y, x, MPFR_RNDD);
401 if (mpfr_cmp_ui (y, 10000) != 0)
402 {
403 printf ("Error for 10^4, MPFR_RNDD\n");
404 exit (1);
405 }
406 mpfr_exp10 (y, x, MPFR_RNDU);
407 if (mpfr_cmp_ui (y, 10000) != 0)
408 {
409 printf ("Error for 10^4, MPFR_RNDU\n");
410 exit (1);
411 }
412
413 mpfr_set_prec (x, 10);
414 mpfr_set_prec (y, 10);
415 /* save emin */
416 emin = mpfr_get_emin ();
417 set_emin (-11);
418 mpfr_set_si (x, -4, MPFR_RNDN);
419 mpfr_exp10 (y, x, MPFR_RNDN);
420 if (MPFR_NOTZERO (y) || MPFR_IS_NEG (y))
421 {
422 printf ("Error for emin = -11, x = -4, RNDN\n");
423 printf ("Expected +0\n");
424 printf ("Got "); mpfr_dump (y);
425 exit (1);
426 }
427 /* restore emin */
428 set_emin (emin);
429
430 /* save emax */
431 emax = mpfr_get_emax ();
432 set_emax (13);
433 mpfr_set_ui (x, 4, MPFR_RNDN);
434 mpfr_exp10 (y, x, MPFR_RNDN);
435 if (!mpfr_inf_p (y) || mpfr_sgn (y) < 0)
436 {
437 printf ("Error for emax = 13, x = 4, RNDN\n");
438 printf ("Expected +inf\n");
439 printf ("Got "); mpfr_dump (y);
440 exit (1);
441 }
442 /* restore emax */
443 set_emax (emax);
444
445 MPFR_SET_INF (x);
446 MPFR_SET_POS (x);
447 mpfr_exp10 (y, x, MPFR_RNDN);
448 if (!MPFR_IS_INF (y))
449 {
450 printf ("evaluation of function in INF does not return INF\n");
451 exit (1);
452 }
453
454 MPFR_CHANGE_SIGN (x);
455 mpfr_exp10 (y, x, MPFR_RNDN);
456 if (!MPFR_IS_ZERO (y))
457 {
458 printf ("evaluation of function in -INF does not return 0\n");
459 exit (1);
460 }
461
462 MPFR_SET_NAN (x);
463 mpfr_exp10 (y, x, MPFR_RNDN);
464 if (!MPFR_IS_NAN (y))
465 {
466 printf ("evaluation of function in NaN does not return NaN\n");
467 exit (1);
468 }
469
470 if ((mpfr_uexp_t) 8 << 31 != 0 ||
471 mpfr_get_emax () <= (mpfr_uexp_t) 100000 * 100000)
472 {
473 /* emax <= 10000000000 */
474 mpfr_set_prec (x, 40);
475 mpfr_set_prec (y, 40);
476 mpfr_set_str (x, "3010299957", 10, MPFR_RNDN);
477 mpfr_clear_flags ();
478 inex = mpfr_exp10 (y, x, MPFR_RNDN);
479 ov = mpfr_overflow_p ();
480 if (!(MPFR_IS_INF (y) && MPFR_IS_POS (y) && ov))
481 {
482 printf ("Overflow error for x = 3010299957, MPFR_RNDN.\n");
483 mpfr_dump (y);
484 printf ("inex = %d, %soverflow\n", inex, ov ? "" : "no ");
485 exit (1);
486 }
487 }
488
489 test_generic (MPFR_PREC_MIN, 100, 100);
490
491 mpfr_clear (x);
492 mpfr_clear (y);
493
494 overfl_exp10_0 ();
495
496 data_check ("data/exp10", mpfr_exp10, "mpfr_exp10");
497 bad_cases (mpfr_exp10, mpfr_log10, "mpfr_exp10",
498 0, -256, 255, 4, 128, 800, 50);
499
500 tests_end_mpfr ();
501 return 0;
502 }
503