1 /* Test file for mpfr_get_sj and mpfr_get_uj.
2
3 Copyright 2004-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 #define MPFR_NEED_INTMAX_H
24 #include "mpfr-test.h"
25
26 #ifndef _MPFR_H_HAVE_INTMAX_T
27
28 int
main(void)29 main (void)
30 {
31 return 77;
32 }
33
34 #else
35
36 #ifndef NPRINTF_J
37 #define PRMAX(SPEC,V) printf (" %j" SPEC ",", V)
38 #else
39 #define PRMAX(SPEC,V) (void) 0
40 #endif
41
42 static void
check_sj(intmax_t s,mpfr_ptr x)43 check_sj (intmax_t s, mpfr_ptr x)
44 {
45 mpfr_exp_t emin, emax;
46 mpfr_t y;
47 int i;
48
49 mpfr_init2 (y, MPFR_PREC (x) + 2);
50
51 emin = mpfr_get_emin ();
52 emax = mpfr_get_emax ();
53
54 for (i = -1; i <= 1; i++)
55 {
56 int rnd;
57 int inex;
58 int fi, e;
59 mpfr_flags_t flags[2] = { 0, MPFR_FLAGS_ALL }, ex_flags, gt_flags;
60
61 inex = mpfr_set_si_2exp (y, i, -2, MPFR_RNDN);
62 MPFR_ASSERTN (inex == 0);
63 inex = mpfr_add (y, y, x, MPFR_RNDN);
64 MPFR_ASSERTN (inex == 0);
65 /* y = x + i/4, with -1 <= i <= 1 */
66 RND_LOOP (rnd)
67 for (fi = 0; fi < numberof (flags); fi++)
68 {
69 intmax_t r;
70
71 if (rnd == MPFR_RNDZ && i < 0 && s >= 0)
72 continue;
73 if (rnd == MPFR_RNDZ && i > 0 && s <= 0)
74 continue;
75 if (rnd == MPFR_RNDD && i < 0)
76 continue;
77 if (rnd == MPFR_RNDU && i > 0)
78 continue;
79 if (rnd == MPFR_RNDA && ((MPFR_IS_POS(y) && i > 0) ||
80 (MPFR_IS_NEG(y) && i < 0)))
81 continue;
82
83 for (e = 0; e < 2; e++)
84 {
85 if (e)
86 {
87 mpfr_exp_t ey;
88
89 if (MPFR_IS_ZERO (y))
90 break;
91 ey = MPFR_GET_EXP (y);
92 set_emin (ey);
93 set_emax (ey);
94 }
95 /* rint (y) == x == s */
96 __gmpfr_flags = ex_flags = flags[fi];
97 if (i != 0)
98 ex_flags |= MPFR_FLAGS_INEXACT;
99 r = mpfr_get_sj (y, (mpfr_rnd_t) rnd);
100 gt_flags = __gmpfr_flags;
101 set_emin (emin);
102 set_emax (emax);
103 if ((r != s || gt_flags != ex_flags) && rnd != MPFR_RNDF)
104 {
105 printf ("Error in check_sj for fi = %d, y = ", fi);
106 mpfr_out_str (stdout, 2, 0, y, MPFR_RNDN);
107 printf (" in %s%s\n",
108 mpfr_print_rnd_mode ((mpfr_rnd_t) rnd),
109 e ? ", reduced exponent range" : "");
110 printf ("Expected:");
111 PRMAX ("d", s);
112 flags_out (ex_flags);
113 printf ("Got: ");
114 PRMAX ("d", r);
115 flags_out (gt_flags);
116 exit (1);
117 }
118 }
119 }
120 }
121
122 mpfr_clear (y);
123 }
124
125 static void
check_uj(uintmax_t u,mpfr_ptr x)126 check_uj (uintmax_t u, mpfr_ptr x)
127 {
128 mpfr_exp_t emin, emax;
129 mpfr_t y;
130 int i;
131
132 mpfr_init2 (y, MPFR_PREC (x) + 2);
133
134 emin = mpfr_get_emin ();
135 emax = mpfr_get_emax ();
136
137 for (i = -1; i <= 1; i++)
138 {
139 int rnd;
140 int inex;
141 int fi, e;
142 mpfr_flags_t flags[2] = { 0, MPFR_FLAGS_ALL }, ex_flags, gt_flags;
143
144 inex = mpfr_set_si_2exp (y, i, -2, MPFR_RNDN);
145 MPFR_ASSERTN (inex == 0);
146 inex = mpfr_add (y, y, x, MPFR_RNDN);
147 MPFR_ASSERTN (inex == 0);
148 /* y = x + i/4, with -1 <= i <= 1 */
149 RND_LOOP (rnd)
150 for (fi = 0; fi < numberof (flags); fi++)
151 {
152 uintmax_t r;
153
154 if (rnd == MPFR_RNDZ && i < 0)
155 continue;
156 if (rnd == MPFR_RNDD && i < 0)
157 continue;
158 if (rnd == MPFR_RNDU && i > 0)
159 continue;
160 if (rnd == MPFR_RNDA && ((MPFR_IS_POS(y) && i > 0) ||
161 (MPFR_IS_NEG(y) && i < 0)))
162 continue;
163
164 for (e = 0; e < 2; e++)
165 {
166 if (e)
167 {
168 mpfr_exp_t ey;
169
170 if (MPFR_IS_ZERO (y))
171 break;
172 ey = MPFR_GET_EXP (y);
173 set_emin (ey);
174 set_emax (ey);
175 }
176 /* rint (y) == x == u */
177 __gmpfr_flags = ex_flags = flags[fi];
178 if (i != 0)
179 ex_flags |= MPFR_FLAGS_INEXACT;
180 r = mpfr_get_uj (y, (mpfr_rnd_t) rnd);
181 gt_flags = __gmpfr_flags;
182 set_emin (emin);
183 set_emax (emax);
184 if ((r != u || gt_flags != ex_flags) && rnd != MPFR_RNDF)
185 {
186 printf ("Error in check_uj for fi = %d, y = ", fi);
187 mpfr_out_str (stdout, 2, 0, y, MPFR_RNDN);
188 printf (" in %s%s\n",
189 mpfr_print_rnd_mode ((mpfr_rnd_t) rnd),
190 e ? ", reduced exponent range" : "");
191 printf ("Expected:");
192 PRMAX ("u", u);
193 flags_out (ex_flags);
194 printf ("Got: ");
195 PRMAX ("u", r);
196 flags_out (gt_flags);
197 exit (1);
198 }
199 }
200 }
201 }
202
203 mpfr_clear (y);
204 }
205
206 #define CHECK_ERANGE(F,FMT,RES,INPUT,VALUE,E) \
207 do \
208 { \
209 __gmpfr_flags = ex_flags = flags[fi]; \
210 RES = F (x, (mpfr_rnd_t) rnd); \
211 gt_flags = __gmpfr_flags; \
212 if (E) \
213 ex_flags |= MPFR_FLAGS_ERANGE; \
214 if (RES == VALUE && gt_flags == ex_flags) \
215 continue; \
216 printf ("Error in check_erange for %s, %s, fi = %d on %s\n", \
217 #F, mpfr_print_rnd_mode ((mpfr_rnd_t) rnd), fi, INPUT); \
218 printf ("Expected:"); \
219 PRMAX (FMT, VALUE); \
220 flags_out (ex_flags); \
221 printf ("Got: "); \
222 PRMAX (FMT, RES); \
223 flags_out (gt_flags); \
224 exit (1); \
225 } \
226 while (0)
227
228 #define CHECK_ERANGE_U(INPUT,VALUE,E) \
229 CHECK_ERANGE (mpfr_get_uj, "u", u, INPUT, (uintmax_t) VALUE, E)
230 #define CHECK_ERANGE_S(INPUT,VALUE,E) \
231 CHECK_ERANGE (mpfr_get_sj, "d", d, INPUT, (intmax_t) VALUE, E)
232
233 static void
check_erange(void)234 check_erange (void)
235 {
236 mpfr_t x;
237 uintmax_t u;
238 intmax_t d;
239 int rnd;
240 int fi;
241 mpfr_flags_t flags[3] = { 0, MPFR_FLAGS_ALL ^ MPFR_FLAGS_ERANGE,
242 MPFR_FLAGS_ALL }, ex_flags, gt_flags;
243
244 /* Test for ERANGE flag + correct behavior if overflow */
245
246 mpfr_init2 (x, 256);
247
248 RND_LOOP (rnd)
249 for (fi = 0; fi < numberof (flags); fi++)
250 {
251 mpfr_set_uj (x, UINTMAX_MAX, MPFR_RNDN);
252 CHECK_ERANGE_U ("UINTMAX_MAX", UINTMAX_MAX, 0);
253 mpfr_add_ui (x, x, 1, MPFR_RNDN);
254 CHECK_ERANGE_U ("UINTMAX_MAX+1", UINTMAX_MAX, 1);
255 mpfr_set_sj (x, -1, MPFR_RNDN);
256 CHECK_ERANGE_U ("-1", 0, 1);
257 mpfr_set_sj (x, INTMAX_MAX, MPFR_RNDN);
258 CHECK_ERANGE_S ("INTMAX_MAX", INTMAX_MAX, 0);
259 mpfr_add_ui (x, x, 1, MPFR_RNDN);
260 CHECK_ERANGE_S ("INTMAX_MAX+1", INTMAX_MAX, 1);
261 mpfr_set_sj (x, INTMAX_MIN, MPFR_RNDN);
262 CHECK_ERANGE_S ("INTMAX_MIN", INTMAX_MIN, 0);
263 mpfr_sub_ui (x, x, 1, MPFR_RNDN);
264 CHECK_ERANGE_S ("INTMAX_MIN-1", INTMAX_MIN, 1);
265 mpfr_set_nan (x);
266 CHECK_ERANGE_U ("NaN", 0, 1);
267 CHECK_ERANGE_S ("NaN", 0, 1);
268 }
269
270 mpfr_clear (x);
271 }
272
273 static void
test_get_uj_smallneg(void)274 test_get_uj_smallneg (void)
275 {
276 mpfr_t x;
277 int i;
278
279 mpfr_init2 (x, 64);
280
281 for (i = 1; i <= 4; i++)
282 {
283 int r;
284
285 mpfr_set_si_2exp (x, -i, -2, MPFR_RNDN);
286 RND_LOOP (r)
287 {
288 intmax_t s;
289 uintmax_t u;
290
291 mpfr_clear_erangeflag ();
292 s = mpfr_get_sj (x, r != MPFR_RNDF ? (mpfr_rnd_t) r : MPFR_RNDA);
293 if (mpfr_erangeflag_p ())
294 {
295 printf ("ERROR for get_sj + ERANGE + small negative op"
296 " for rnd = %s and x = -%d/4\n",
297 mpfr_print_rnd_mode ((mpfr_rnd_t) r), i);
298 exit (1);
299 }
300 u = mpfr_get_uj (x, (mpfr_rnd_t) r);
301 if (u != 0)
302 {
303 printf ("ERROR for get_uj + ERANGE + small negative op"
304 " for rnd = %s and x = -%d/4\n",
305 mpfr_print_rnd_mode ((mpfr_rnd_t) r), i);
306 #ifndef NPRINTF_J
307 printf ("Expected 0, got %ju\n", u);
308 #endif
309 exit (1);
310 }
311 if ((s == 0) ^ !mpfr_erangeflag_p ())
312 {
313 const char *Not = s == 0 ? "" : " not";
314
315 printf ("ERROR for get_uj + ERANGE + small negative op"
316 " for rnd = %s and x = -%d/4\n",
317 mpfr_print_rnd_mode ((mpfr_rnd_t) r), i);
318 printf ("The rounded integer ");
319 #ifndef NPRINTF_J
320 printf("(%jd) ", s);
321 #endif
322 printf("is%s representable in unsigned long,\n"
323 "but the erange flag is%s set.\n", Not, Not);
324 exit (1);
325 }
326 }
327 }
328
329 mpfr_clear (x);
330 }
331
332 int
main(void)333 main (void)
334 {
335 mpfr_prec_t prec;
336 mpfr_t x, y;
337 intmax_t s;
338 uintmax_t u;
339
340 tests_start_mpfr ();
341
342 for (u = UINTMAX_MAX, prec = 0; u != 0; u /= 2, prec++)
343 { }
344
345 mpfr_init2 (x, prec + 4);
346 mpfr_init2 (y, prec + 4);
347
348 mpfr_set_ui (x, 0, MPFR_RNDN);
349 check_sj (0, x);
350 check_uj (0, x);
351
352 mpfr_set_ui (x, 1, MPFR_RNDN);
353 check_sj (1, x);
354 check_uj (1, x);
355
356 mpfr_neg (x, x, MPFR_RNDN);
357 check_sj (-1, x);
358
359 mpfr_set_si_2exp (x, 1, prec, MPFR_RNDN);
360 mpfr_sub_ui (x, x, 1, MPFR_RNDN); /* UINTMAX_MAX */
361
362 mpfr_div_ui (y, x, 2, MPFR_RNDZ);
363 mpfr_trunc (y, y); /* INTMAX_MAX */
364 for (s = INTMAX_MAX; s != 0; s /= 17)
365 {
366 check_sj (s, y);
367 mpfr_div_ui (y, y, 17, MPFR_RNDZ);
368 mpfr_trunc (y, y);
369 }
370
371 mpfr_div_ui (y, x, 2, MPFR_RNDZ);
372 mpfr_trunc (y, y); /* INTMAX_MAX */
373 mpfr_neg (y, y, MPFR_RNDN);
374 if (INTMAX_MIN + INTMAX_MAX != 0)
375 mpfr_sub_ui (y, y, 1, MPFR_RNDN); /* INTMAX_MIN */
376 for (s = INTMAX_MIN; s != 0; s /= 17)
377 {
378 check_sj (s, y);
379 mpfr_div_ui (y, y, 17, MPFR_RNDZ);
380 mpfr_trunc (y, y);
381 }
382
383 for (u = UINTMAX_MAX; u != 0; u /= 17)
384 {
385 check_uj (u, x);
386 mpfr_div_ui (x, x, 17, MPFR_RNDZ);
387 mpfr_trunc (x, x);
388 }
389
390 mpfr_clear (x);
391 mpfr_clear (y);
392
393 check_erange ();
394 test_get_uj_smallneg ();
395
396 tests_end_mpfr ();
397 return 0;
398 }
399
400 #endif
401