1 /* Test file for mpfr_set_z_2exp.
2
3 Copyright 1999, 2001-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 #include "mpfr-test.h"
24
25 /* generate a random exponent in [__gmpfr_emin, __gmpfr_emax-1] */
26 static mpfr_exp_t
randexp(void)27 randexp (void)
28 {
29 mpfr_uexp_t e;
30
31 if (MPFR_EXP_MAX <= MPFR_LIMB_MAX >> 1)
32 {
33 /* mpfr_uexp_t fits in a limb: we can generate the whole range
34 [emin, emax] directly. */
35 e = randlimb ();
36 }
37 else
38 {
39 mpfr_uexp_t emax = (mpfr_uexp_t) -1;
40
41 e = 0;
42 while (emax != 0)
43 {
44 /* Since mp_limb_t < mpfr_uexp_t, the shift counts are valid.
45 Use GMP_NUMB_BITS - 1 instead of GMP_NUMB_BITS to avoid a
46 bug in GCC. */
47 e = (e << (GMP_NUMB_BITS - 1)) + (randlimb () >> 1);
48 emax >>= GMP_NUMB_BITS - 1;
49 }
50 }
51 return (mpfr_exp_t) (e % (__gmpfr_emax - __gmpfr_emin)) + __gmpfr_emin;
52 }
53
54 static void
check0(void)55 check0 (void)
56 {
57 mpz_t y;
58 mpfr_t x;
59 int inexact, r;
60 mpfr_exp_t e;
61
62 /* Check for +0 */
63 mpfr_init (x);
64 mpz_init (y);
65 mpz_set_si (y, 0);
66 for (r = 0; r < MPFR_RND_MAX; r++)
67 {
68 e = randexp ();
69 inexact = mpfr_set_z_2exp (x, y, e, (mpfr_rnd_t) r);
70 if (!MPFR_IS_ZERO(x) || !MPFR_IS_POS(x) || inexact)
71 {
72 printf ("mpfr_set_z_2exp(x,0,e) failed for e=");
73 if (e < LONG_MIN)
74 printf ("(<LONG_MIN)");
75 else if (e > LONG_MAX)
76 printf ("(>LONG_MAX)");
77 else
78 printf ("%ld", (long) e);
79 printf (", rnd=%s\n", mpfr_print_rnd_mode ((mpfr_rnd_t) r));
80 exit (1);
81 }
82 }
83
84 /* coverage test for huge exponent */
85 mpz_setbit (y, GMP_NUMB_BITS);
86 mpfr_clear_flags ();
87 inexact = mpfr_set_z_2exp (x, y, mpfr_get_emax_max(), MPFR_RNDN);
88 MPFR_ASSERTN(inexact > 0);
89 MPFR_ASSERTN(mpfr_inf_p (x) && mpfr_sgn (x) > 0);
90 MPFR_ASSERTN(mpfr_overflow_p ());
91 mpfr_clear(x);
92 mpz_clear(y);
93 }
94
95 /* FIXME: It'd be better to examine the actual data in an mpfr_t to see that
96 it's as expected. Comparing mpfr_set_z with mpfr_cmp or against
97 mpfr_get_si is a rather indirect test of a low level routine. */
98
99 static void
check(long i,mpfr_rnd_t rnd,int reduced)100 check (long i, mpfr_rnd_t rnd, int reduced)
101 {
102 mpfr_t f1, f2, f3;
103 mpz_t z;
104 mpfr_exp_t e, old_emin, old_emax;
105 int inex;
106 mpfr_flags_t flags;
107
108 old_emin = mpfr_get_emin ();
109 old_emax = mpfr_get_emax ();
110
111 /* using CHAR_BIT * sizeof(long) bits of precision ensures that
112 mpfr_set_z_2exp is exact below */
113 mpfr_inits2 (CHAR_BIT * sizeof(long), f1, f2, f3, (mpfr_ptr) 0);
114 mpz_init (z);
115 mpz_set_ui (z, i);
116 /* the following loop ensures that no overflow occurs */
117 do
118 e = randexp ();
119 while (e > mpfr_get_emax () - CHAR_BIT * sizeof(long));
120
121 mpfr_clear_flags ();
122 inex = mpfr_set_z_2exp (f1, z, e, rnd);
123 flags = __gmpfr_flags;
124
125 if (inex != 0 || flags != 0 ||
126 (mpfr_div_2si (f2, f1, e, rnd), mpfr_get_si (f2, MPFR_RNDZ) != i))
127 {
128 printf ("Error in mpfr_set_z_2exp for i=%ld e=%" MPFR_EXP_FSPEC
129 "d rnd_mode=%d\n", i, (mpfr_eexp_t) e, rnd);
130 mpfr_set_si_2exp (f2, i, e, MPFR_RNDN);
131 printf ("expected "); mpfr_dump (f2);
132 printf ("with inex = %d and flags =", 0);
133 flags_out (0);
134 printf ("got "); mpfr_dump (f1);
135 printf ("with inex = %d and flags =", inex);
136 flags_out (flags);
137 exit (1);
138 }
139
140 if (reduced)
141 {
142 mpfr_exp_t ef, emin, emax;
143 int inex2, inex3;
144 mpfr_flags_t flags2, flags3;
145
146 ef = i == 0 ? 0 : mpfr_get_exp (f1);
147 for (emin = ef - 2; emin <= ef + 2; emin++)
148 for (emax = emin; emax <= ef + 2; emax++)
149 {
150 inex3 = mpfr_set (f3, f1, rnd);
151 MPFR_ASSERTN (inex3 == 0);
152 mpfr_set_emin (emin);
153 mpfr_set_emax (emax);
154 mpfr_clear_flags ();
155 inex2 = mpfr_set_z_2exp (f2, z, e, rnd);
156 flags2 = __gmpfr_flags;
157 mpfr_clear_flags ();
158 inex3 = mpfr_check_range (f3, 0, rnd);
159 flags3 = __gmpfr_flags;
160 if (!(mpfr_equal_p (f2, f3) &&
161 SAME_SIGN (inex2, inex3) &&
162 flags2 == flags3))
163 {
164 printf ("Error in mpfr_set_z_2exp for i=%ld e=%"
165 MPFR_EXP_FSPEC "d rnd_mode=%d\nand emin=%"
166 MPFR_EXP_FSPEC "d emax=%" MPFR_EXP_FSPEC
167 "d\n", i, (mpfr_eexp_t) e, rnd,
168 (mpfr_eexp_t) emin, (mpfr_eexp_t) emax);
169 printf ("expected "); mpfr_dump (f3);
170 printf ("with inex = %d and flags =", inex3);
171 flags_out (flags3);
172 printf ("got "); mpfr_dump (f2);
173 printf ("with inex = %d and flags =", inex2);
174 flags_out (flags2);
175 exit (1);
176 }
177 }
178 mpfr_set_emin (old_emin);
179 mpfr_set_emax (old_emax);
180 }
181
182 mpfr_clears (f1, f2, f3, (mpfr_ptr) 0);
183 mpz_clear (z);
184 }
185
186 static void
check_huge(void)187 check_huge (void)
188 {
189 if (getenv ("MPFR_CHECK_LARGEMEM") != NULL)
190 {
191 mpfr_t x;
192 mpz_t z;
193 long e;
194
195 /* Increase tests_memory_limit to the maximum in order to avoid
196 an obvious failure due to insufficient memory. */
197 tests_memory_limit = (size_t) -1; /* no memory limit */
198
199 mpfr_init2 (x, 32);
200
201 /* In r14140, with a 32-bit ABI (GCC's -m32):
202 - With UBsan (-fsanitize=undefined -fno-sanitize-recover),
203 this fails with:
204 set_z_2exp.c:71:26: runtime error: signed integer overflow:
205 67108864 * 32 cannot be represented in type 'long int'
206 - With -D_MPFR_EXP_FORMAT=4, this fails with:
207 Expected 0.10001000000000000000000000000000E5
208 Got 0
209 */
210 mpz_init_set_ui (z, 17);
211 e = 0x7ffffff0;
212 mpz_mul_2exp (z, z, e);
213 mpz_add_ui (z, z, 1);
214 mpfr_set_z_2exp (x, z, -e, MPFR_RNDN);
215 if (mpfr_cmp_ui0 (x, 17) != 0)
216 {
217 printf ("Error 1 in check_huge\n");
218 printf ("Expected 0.10001000000000000000000000000000E5\n");
219 printf ("Got ");
220 mpfr_dump (x);
221 exit (1);
222 }
223 mpz_clear (z);
224
225 mpz_init_set_ui (z, 17);
226 mpz_mul_2exp (z, z, 0xffffffb0);
227 mpz_add_ui (z, z, 1);
228 mpfr_set_z_2exp (x, z, -1, MPFR_RNDN);
229 if (! MPFR_IS_INF (x) || MPFR_IS_NEG (x))
230 {
231 printf ("Error 2 in check_huge\n");
232 printf ("Expected @Inf@\n");
233 printf ("Got ");
234 mpfr_dump (x);
235 exit (1);
236 }
237 mpz_clear (z);
238
239 mpfr_clear (x);
240 }
241 }
242
243 int
main(int argc,char * argv[])244 main (int argc, char *argv[])
245 {
246 long j;
247
248 tests_start_mpfr ();
249
250 check (0, MPFR_RNDN, 0);
251 for (j = 0; j < 200000; j++)
252 check (randlimb () & LONG_MAX, RND_RAND (), j < 200);
253 check0 ();
254
255 check_huge ();
256
257 tests_end_mpfr ();
258
259 return 0;
260 }
261