1 /* Test file for mpz_set_fr / mpfr_get_z / mpfr_get_z_2exp.
2
3 Copyright 2004, 2006-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 void
check_diff(void)26 check_diff (void)
27 {
28 int inex;
29 mpfr_t x;
30 mpz_t z;
31 mpfr_exp_t emin;
32
33 mpz_init (z);
34 mpfr_init2 (x, 2);
35
36 mpfr_set_ui (x, 2047, MPFR_RNDU);
37 mpz_set_fr (z, x, MPFR_RNDN);
38 if (mpz_cmp_ui (z, 2048) != 0)
39 {
40 printf ("get_z RU 2048 failed\n");
41 exit (1);
42 }
43
44 mpfr_set_prec (x, 6);
45 mpfr_set_str (x, "17.5", 10, MPFR_RNDN);
46 inex = mpfr_get_z (z, x, MPFR_RNDN);
47 if (inex <= 0 || mpz_cmp_ui (z, 18) != 0)
48 {
49 printf ("get_z RN 17.5 failed\n");
50 exit (1);
51 }
52
53 /* save default emin */
54 emin = mpfr_get_emin ();;
55
56 set_emin (17);
57 mpfr_set_ui (x, 0, MPFR_RNDN);
58 inex = mpfr_get_z (z, x, MPFR_RNDN);
59 if (inex != 0 || mpz_cmp_ui (z, 0) != 0)
60 {
61 printf ("get_z 0 failed\n");
62 exit (1);
63 }
64
65 /* restore default emin */
66 set_emin (emin);
67
68 mpfr_clear (x);
69 mpz_clear (z);
70 }
71
72 static void
check_one(mpz_ptr z)73 check_one (mpz_ptr z)
74 {
75 mpfr_exp_t emin, emax;
76 int inex;
77 int sh, neg;
78 mpfr_t f;
79 mpz_t got, ex, t;
80
81 emin = mpfr_get_emin ();
82 emax = mpfr_get_emax ();
83
84 mpfr_init2 (f, MAX (mpz_sizeinbase (z, 2), MPFR_PREC_MIN));
85 mpz_init (got);
86 mpz_init (ex);
87 mpz_init (t);
88
89 for (sh = -2*GMP_NUMB_BITS ; sh < 2*GMP_NUMB_BITS ; sh++)
90 {
91 inex = mpfr_set_z (f, z, MPFR_RNDN); /* exact */
92 MPFR_ASSERTN (inex == 0);
93
94 inex = sh < 0 ?
95 mpfr_div_2ui (f, f, -sh, MPFR_RNDN) :
96 mpfr_mul_2ui (f, f, sh, MPFR_RNDN);
97 MPFR_ASSERTN (inex == 0);
98
99 for (neg = 0; neg <= 1; neg++)
100 {
101 int rnd;
102
103 /* Test (-1)^neg * z * 2^sh */
104
105 RND_LOOP_NO_RNDF (rnd)
106 {
107 int ex_inex, same;
108 int d, fi, e;
109 mpfr_flags_t flags[3] = { 0, MPFR_FLAGS_ALL ^ MPFR_FLAGS_ERANGE,
110 MPFR_FLAGS_ALL }, ex_flags, gt_flags;
111
112 if (neg)
113 mpz_neg (ex, z);
114 else
115 mpz_set (ex, z);
116
117 if (sh < 0)
118 switch (rnd)
119 {
120 case MPFR_RNDN:
121 mpz_set_si (t, neg ? -1 : 1);
122 mpz_mul_2exp (t, t, -sh - 1);
123 mpz_add (ex, ex, t);
124 /* d = mpz_divisible_2exp_p (ex, -sh); */
125 d = mpz_scan1 (ex, 0) >= -sh;
126 mpz_tdiv_q_2exp (ex, ex, -sh);
127 if (d && mpz_tstbit (ex, 0) != 0) /* even rounding */
128 {
129 if (neg)
130 mpz_add_ui (ex, ex, 1);
131 else
132 mpz_sub_ui (ex, ex, 1);
133 }
134 break;
135 case MPFR_RNDZ:
136 mpz_tdiv_q_2exp (ex, ex, -sh);
137 break;
138 case MPFR_RNDU:
139 mpz_cdiv_q_2exp (ex, ex, -sh);
140 break;
141 case MPFR_RNDD:
142 mpz_fdiv_q_2exp (ex, ex, -sh);
143 break;
144 case MPFR_RNDA:
145 if (neg)
146 mpz_fdiv_q_2exp (ex, ex, -sh);
147 else
148 mpz_cdiv_q_2exp (ex, ex, -sh);
149 break;
150 default:
151 MPFR_ASSERTN (0);
152 }
153 else
154 mpz_mul_2exp (ex, ex, sh);
155
156 ex_inex = - mpfr_cmp_z (f, ex);
157 ex_inex = VSIGN (ex_inex);
158
159 for (fi = 0; fi < numberof (flags); fi++)
160 for (e = 0; e < 2; e++)
161 {
162 if (e)
163 {
164 mpfr_exp_t ef;
165
166 if (MPFR_IS_ZERO (f))
167 break;
168 ef = MPFR_GET_EXP (f);
169 set_emin (ef);
170 set_emax (ef);
171 }
172 ex_flags = __gmpfr_flags = flags[fi];
173 if (ex_inex != 0)
174 ex_flags |= MPFR_FLAGS_INEXACT;
175 inex = mpfr_get_z (got, f, (mpfr_rnd_t) rnd);
176 inex = VSIGN (inex);
177 gt_flags = __gmpfr_flags;
178 set_emin (emin);
179 set_emax (emax);
180 same = SAME_SIGN (inex, ex_inex);
181
182 if (mpz_cmp (got, ex) != 0 ||
183 !same || gt_flags != ex_flags)
184 {
185 printf ("Error in check_one for sh=%d, fi=%d, %s%s\n",
186 sh, fi,
187 mpfr_print_rnd_mode ((mpfr_rnd_t) rnd),
188 e ? ", reduced exponent range" : "");
189 printf (" f = "); mpfr_dump (f);
190 printf ("expected "); mpz_out_str (stdout, 10, ex);
191 printf ("\n got "); mpz_out_str (stdout, 10, got);
192 printf ("\nExpected inex ~ %d, got %d (%s)\n",
193 ex_inex, inex, same ? "OK" : "wrong");
194 printf ("Flags:\n");
195 printf (" in"); flags_out (flags[fi]);
196 printf ("expected"); flags_out (ex_flags);
197 printf (" got"); flags_out (gt_flags);
198 exit (1);
199 }
200 }
201 }
202
203 mpfr_neg (f, f, MPFR_RNDN);
204 }
205 }
206
207 mpfr_clear (f);
208 mpz_clear (got);
209 mpz_clear (ex);
210 mpz_clear (t);
211 }
212
213 static void
check(void)214 check (void)
215 {
216 mpz_t z;
217
218 mpz_init (z);
219
220 mpz_set_ui (z, 0L);
221 check_one (z);
222
223 mpz_set_si (z, 17L);
224 check_one (z);
225
226 mpz_set_si (z, 123L);
227 check_one (z);
228
229 mpz_rrandomb (z, RANDS, 2*GMP_NUMB_BITS);
230 check_one (z);
231
232 mpz_rrandomb (z, RANDS, 5*GMP_NUMB_BITS);
233 check_one (z);
234
235 mpz_clear (z);
236 }
237
238 static void
special(void)239 special (void)
240 {
241 int inex;
242 mpfr_t x;
243 mpz_t z;
244 int i, fi;
245 int rnd;
246 mpfr_exp_t e;
247 mpfr_flags_t flags[3] = { 0, MPFR_FLAGS_ALL ^ MPFR_FLAGS_ERANGE,
248 MPFR_FLAGS_ALL }, ex_flags, gt_flags;
249
250 mpfr_init2 (x, 2);
251 mpz_init (z);
252
253 RND_LOOP (rnd)
254 for (i = -1; i <= 1; i++)
255 for (fi = 0; fi < numberof (flags); fi++)
256 {
257 ex_flags = flags[fi] | MPFR_FLAGS_ERANGE;
258 if (i != 0)
259 mpfr_set_nan (x);
260 else
261 mpfr_set_inf (x, i);
262 __gmpfr_flags = flags[fi];
263 inex = mpfr_get_z (z, x, (mpfr_rnd_t) rnd);
264 gt_flags = __gmpfr_flags;
265 if (gt_flags != ex_flags || inex != 0 || mpz_cmp_ui (z, 0) != 0)
266 {
267 printf ("special() failed on mpfr_get_z"
268 " for %s, i = %d, fi = %d\n",
269 mpfr_print_rnd_mode ((mpfr_rnd_t) rnd), i, fi);
270 printf ("Expected z = 0, inex = 0,");
271 flags_out (ex_flags);
272 printf ("Got z = ");
273 mpz_out_str (stdout, 10, z);
274 printf (", inex = %d,", inex);
275 flags_out (gt_flags);
276 exit (1);
277 }
278 __gmpfr_flags = flags[fi];
279 e = mpfr_get_z_2exp (z, x);
280 gt_flags = __gmpfr_flags;
281 if (gt_flags != ex_flags || e != __gmpfr_emin ||
282 mpz_cmp_ui (z, 0) != 0)
283 {
284 printf ("special() failed on mpfr_get_z_2exp"
285 " for %s, i = %d, fi = %d\n",
286 mpfr_print_rnd_mode ((mpfr_rnd_t) rnd), i, fi);
287 printf ("Expected z = 0, e = %" MPFR_EXP_FSPEC "d,",
288 (mpfr_eexp_t) __gmpfr_emin);
289 flags_out (ex_flags);
290 printf ("Got z = ");
291 mpz_out_str (stdout, 10, z);
292 printf (", e = %" MPFR_EXP_FSPEC "d,", (mpfr_eexp_t) e);
293 flags_out (gt_flags);
294 exit (1);
295 }
296 }
297
298 mpfr_clear (x);
299 mpz_clear (z);
300 }
301
302 int
main(void)303 main (void)
304 {
305 tests_start_mpfr ();
306
307 check ();
308 check_diff ();
309 special ();
310
311 tests_end_mpfr ();
312 return 0;
313 }
314