1 /* mpfr_rint -- Round to an integer.
2
3 Copyright 1999-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-impl.h"
24
25 /* Merge the following mpfr_rint code with mpfr_round_raw_generic? */
26
27 /* For all the round-to-integer functions, we don't need to extend the
28 * exponent range. And it is better not to do so, so that we can test
29 * the flag setting for intermediate overflow in the test suite without
30 * involving huge non-integer numbers (thus in huge precision). This
31 * should also be faster.
32 *
33 * We also need to be careful with the flags.
34 */
35
36 int
mpfr_rint(mpfr_ptr r,mpfr_srcptr u,mpfr_rnd_t rnd_mode)37 mpfr_rint (mpfr_ptr r, mpfr_srcptr u, mpfr_rnd_t rnd_mode)
38 {
39 int sign;
40 int rnd_away;
41 mpfr_exp_t exp;
42
43 if (MPFR_UNLIKELY( MPFR_IS_SINGULAR(u) ))
44 {
45 if (MPFR_IS_NAN(u))
46 {
47 MPFR_SET_NAN(r);
48 MPFR_RET_NAN;
49 }
50 MPFR_SET_SAME_SIGN(r, u);
51 if (MPFR_IS_INF(u))
52 {
53 MPFR_SET_INF(r);
54 MPFR_RET(0); /* infinity is exact */
55 }
56 else /* now u is zero */
57 {
58 MPFR_ASSERTD(MPFR_IS_ZERO(u));
59 MPFR_SET_ZERO(r);
60 MPFR_RET(0); /* zero is exact */
61 }
62 }
63 MPFR_SET_SAME_SIGN (r, u); /* Does nothing if r==u */
64
65 sign = MPFR_INT_SIGN (u);
66 exp = MPFR_GET_EXP (u);
67
68 rnd_away =
69 rnd_mode == MPFR_RNDD ? sign < 0 :
70 rnd_mode == MPFR_RNDU ? sign > 0 :
71 rnd_mode == MPFR_RNDZ ? 0 :
72 rnd_mode == MPFR_RNDA ? 1 :
73 -1; /* round to nearest-even (RNDN) or nearest-away (RNDNA) */
74
75 /* rnd_away:
76 1 if round away from zero,
77 0 if round to zero,
78 -1 if not decided yet.
79 */
80
81 if (MPFR_UNLIKELY (exp <= 0)) /* 0 < |u| < 1 ==> round |u| to 0 or 1 */
82 {
83 /* Note: in the MPFR_RNDN mode, 0.5 must be rounded to 0. */
84 if (rnd_away != 0 &&
85 (rnd_away > 0 ||
86 (exp == 0 && (rnd_mode == MPFR_RNDNA ||
87 !mpfr_powerof2_raw (u)))))
88 {
89 /* The flags will correctly be set and overflow will correctly
90 be handled by mpfr_set_si. */
91 mpfr_set_si (r, sign, rnd_mode);
92 MPFR_RET(sign > 0 ? 2 : -2);
93 }
94 else
95 {
96 MPFR_SET_ZERO(r); /* r = 0 */
97 MPFR_RET(sign > 0 ? -2 : 2);
98 }
99 }
100 else /* exp > 0, |u| >= 1 */
101 {
102 mp_limb_t *up, *rp;
103 mp_size_t un, rn, ui;
104 int sh, idiff;
105 int uflags;
106
107 /*
108 * uflags will contain:
109 * _ 0 if u is an integer representable in r,
110 * _ 1 if u is an integer not representable in r,
111 * _ 2 if u is not an integer.
112 */
113
114 up = MPFR_MANT(u);
115 rp = MPFR_MANT(r);
116
117 un = MPFR_LIMB_SIZE(u);
118 rn = MPFR_LIMB_SIZE(r);
119 MPFR_UNSIGNED_MINUS_MODULO (sh, MPFR_PREC (r));
120
121 /* exp is in the current exponent range: obtained from the input. */
122 MPFR_SET_EXP (r, exp); /* Does nothing if r==u */
123
124 if ((exp - 1) / GMP_NUMB_BITS >= un)
125 {
126 ui = un;
127 idiff = 0;
128 uflags = 0; /* u is an integer, representable or not in r */
129 }
130 else
131 {
132 mp_size_t uj;
133
134 ui = (exp - 1) / GMP_NUMB_BITS + 1; /* #limbs of the int part */
135 MPFR_ASSERTD (un >= ui);
136 uj = un - ui; /* lowest limb of the integer part */
137 idiff = exp % GMP_NUMB_BITS; /* #int-part bits in up[uj] or 0 */
138
139 uflags = idiff == 0 || MPFR_LIMB_LSHIFT(up[uj],idiff) == 0 ? 0 : 2;
140 if (uflags == 0)
141 while (uj > 0)
142 if (up[--uj] != 0)
143 {
144 uflags = 2;
145 break;
146 }
147 }
148
149 if (ui > rn)
150 {
151 /* More limbs in the integer part of u than in r.
152 Just round u with the precision of r. */
153 MPFR_ASSERTD (rp != up && un > rn);
154 MPN_COPY (rp, up + (un - rn), rn); /* r != u */
155 if (rnd_away < 0)
156 {
157 /* This is a rounding to nearest mode (MPFR_RNDN or MPFR_RNDNA).
158 Decide the rounding direction here. */
159 if (rnd_mode == MPFR_RNDN &&
160 (rp[0] & (MPFR_LIMB_ONE << sh)) == 0)
161 { /* halfway cases rounded toward zero */
162 mp_limb_t a, b;
163 /* a: rounding bit and some of the following bits */
164 /* b: boundary for a (weight of the rounding bit in a) */
165 if (sh != 0)
166 {
167 a = rp[0] & ((MPFR_LIMB_ONE << sh) - 1);
168 b = MPFR_LIMB_ONE << (sh - 1);
169 }
170 else
171 {
172 a = up[un - rn - 1];
173 b = MPFR_LIMB_HIGHBIT;
174 }
175 rnd_away = a > b;
176 if (a == b)
177 {
178 mp_size_t i;
179 for (i = un - rn - 1 - (sh == 0); i >= 0; i--)
180 if (up[i] != 0)
181 {
182 rnd_away = 1;
183 break;
184 }
185 }
186 }
187 else /* halfway cases rounded away from zero */
188 rnd_away = /* rounding bit */
189 ((sh != 0 && (rp[0] & (MPFR_LIMB_ONE << (sh - 1))) != 0) ||
190 (sh == 0 && (up[un - rn - 1] & MPFR_LIMB_HIGHBIT) != 0));
191 }
192 if (uflags == 0)
193 { /* u is an integer; determine if it is representable in r */
194 if (sh != 0 && MPFR_LIMB_LSHIFT(rp[0], GMP_NUMB_BITS - sh) != 0)
195 uflags = 1; /* u is not representable in r */
196 else
197 {
198 mp_size_t i;
199 for (i = un - rn - 1; i >= 0; i--)
200 if (up[i] != 0)
201 {
202 uflags = 1; /* u is not representable in r */
203 break;
204 }
205 }
206 }
207 }
208 else /* ui <= rn */
209 {
210 mp_size_t uj, rj;
211 int ush;
212
213 uj = un - ui; /* lowest limb of the integer part in u */
214 rj = rn - ui; /* lowest limb of the integer part in r */
215
216 if (rp != up)
217 MPN_COPY(rp + rj, up + uj, ui);
218
219 /* Ignore the lowest rj limbs, all equal to zero. */
220 rp += rj;
221 rn = ui;
222
223 /* number of fractional bits in whole rp[0] */
224 ush = idiff == 0 ? 0 : GMP_NUMB_BITS - idiff;
225
226 if (rj == 0 && ush < sh)
227 {
228 /* If u is an integer (uflags == 0), we need to determine
229 if it is representable in r, i.e. if its sh - ush bits
230 in the non-significant part of r are all 0. */
231 if (uflags == 0 && (rp[0] & ((MPFR_LIMB_ONE << sh) -
232 (MPFR_LIMB_ONE << ush))) != 0)
233 uflags = 1; /* u is an integer not representable in r */
234 }
235 else /* The integer part of u fits in r, we'll round to it. */
236 sh = ush;
237
238 if (rnd_away < 0)
239 {
240 /* This is a rounding to nearest mode.
241 Decide the rounding direction here. */
242 if (uj == 0 && sh == 0)
243 rnd_away = 0; /* rounding bit = 0 (not represented in u) */
244 else if (rnd_mode == MPFR_RNDN &&
245 (rp[0] & (MPFR_LIMB_ONE << sh)) == 0)
246 { /* halfway cases rounded toward zero */
247 mp_limb_t a, b;
248 /* a: rounding bit and some of the following bits */
249 /* b: boundary for a (weight of the rounding bit in a) */
250 if (sh != 0)
251 {
252 a = rp[0] & ((MPFR_LIMB_ONE << sh) - 1);
253 b = MPFR_LIMB_ONE << (sh - 1);
254 }
255 else
256 {
257 MPFR_ASSERTD (uj >= 1); /* see above */
258 a = up[uj - 1];
259 b = MPFR_LIMB_HIGHBIT;
260 }
261 rnd_away = a > b;
262 if (a == b)
263 {
264 mp_size_t i;
265 for (i = uj - 1 - (sh == 0); i >= 0; i--)
266 if (up[i] != 0)
267 {
268 rnd_away = 1;
269 break;
270 }
271 }
272 }
273 else /* halfway cases rounded away from zero */
274 rnd_away = /* rounding bit */
275 ((sh != 0 && (rp[0] & (MPFR_LIMB_ONE << (sh - 1))) != 0) ||
276 (sh == 0 && (MPFR_ASSERTD (uj >= 1),
277 up[uj - 1] & MPFR_LIMB_HIGHBIT) != 0));
278 }
279 /* Now we can make the low rj limbs to 0 */
280 MPN_ZERO (rp-rj, rj);
281 }
282
283 if (sh != 0)
284 rp[0] &= MPFR_LIMB_MAX << sh;
285
286 /* If u is a representable integer, there is no rounding. */
287 if (uflags == 0)
288 MPFR_RET(0);
289
290 MPFR_ASSERTD (rnd_away >= 0); /* rounding direction is defined */
291 if (rnd_away && mpn_add_1 (rp, rp, rn, MPFR_LIMB_ONE << sh))
292 {
293 if (exp == __gmpfr_emax)
294 return mpfr_overflow (r, rnd_mode, sign) >= 0 ?
295 uflags : -uflags;
296 else /* no overflow */
297 {
298 MPFR_SET_EXP(r, exp + 1);
299 rp[rn-1] = MPFR_LIMB_HIGHBIT;
300 }
301 }
302
303 MPFR_RET (rnd_away ^ (sign < 0) ? uflags : -uflags);
304 } /* exp > 0, |u| >= 1 */
305 }
306
307 #undef mpfr_roundeven
308
309 int
mpfr_roundeven(mpfr_ptr r,mpfr_srcptr u)310 mpfr_roundeven (mpfr_ptr r, mpfr_srcptr u)
311 {
312 return mpfr_rint (r, u, MPFR_RNDN);
313 }
314
315 #undef mpfr_round
316
317 int
mpfr_round(mpfr_ptr r,mpfr_srcptr u)318 mpfr_round (mpfr_ptr r, mpfr_srcptr u)
319 {
320 return mpfr_rint (r, u, MPFR_RNDNA);
321 }
322
323 #undef mpfr_trunc
324
325 int
mpfr_trunc(mpfr_ptr r,mpfr_srcptr u)326 mpfr_trunc (mpfr_ptr r, mpfr_srcptr u)
327 {
328 return mpfr_rint (r, u, MPFR_RNDZ);
329 }
330
331 #undef mpfr_ceil
332
333 int
mpfr_ceil(mpfr_ptr r,mpfr_srcptr u)334 mpfr_ceil (mpfr_ptr r, mpfr_srcptr u)
335 {
336 return mpfr_rint (r, u, MPFR_RNDU);
337 }
338
339 #undef mpfr_floor
340
341 int
mpfr_floor(mpfr_ptr r,mpfr_srcptr u)342 mpfr_floor (mpfr_ptr r, mpfr_srcptr u)
343 {
344 return mpfr_rint (r, u, MPFR_RNDD);
345 }
346
347 /* We need to save the flags and restore them after calling the mpfr_round,
348 * mpfr_trunc, mpfr_ceil, mpfr_floor functions because these functions set
349 * the inexact flag when the argument is not an integer.
350 */
351
352 #undef mpfr_rint_roundeven
353
354 int
mpfr_rint_roundeven(mpfr_ptr r,mpfr_srcptr u,mpfr_rnd_t rnd_mode)355 mpfr_rint_roundeven (mpfr_ptr r, mpfr_srcptr u, mpfr_rnd_t rnd_mode)
356 {
357 if (MPFR_UNLIKELY( MPFR_IS_SINGULAR(u) ) || mpfr_integer_p (u))
358 return mpfr_set (r, u, rnd_mode);
359 else
360 {
361 mpfr_t tmp;
362 int inex;
363 mpfr_flags_t saved_flags = __gmpfr_flags;
364 MPFR_BLOCK_DECL (flags);
365
366 mpfr_init2 (tmp, MPFR_PREC (u));
367 /* round(u) is representable in tmp unless an overflow occurs */
368 MPFR_BLOCK (flags, mpfr_roundeven (tmp, u));
369 __gmpfr_flags = saved_flags;
370 inex = (MPFR_OVERFLOW (flags)
371 ? mpfr_overflow (r, rnd_mode, MPFR_SIGN (u))
372 : mpfr_set (r, tmp, rnd_mode));
373 mpfr_clear (tmp);
374 return inex;
375 }
376 }
377
378 #undef mpfr_rint_round
379
380 int
mpfr_rint_round(mpfr_ptr r,mpfr_srcptr u,mpfr_rnd_t rnd_mode)381 mpfr_rint_round (mpfr_ptr r, mpfr_srcptr u, mpfr_rnd_t rnd_mode)
382 {
383 if (MPFR_UNLIKELY( MPFR_IS_SINGULAR(u) ) || mpfr_integer_p (u))
384 return mpfr_set (r, u, rnd_mode);
385 else
386 {
387 mpfr_t tmp;
388 int inex;
389 mpfr_flags_t saved_flags = __gmpfr_flags;
390 MPFR_BLOCK_DECL (flags);
391
392 mpfr_init2 (tmp, MPFR_PREC (u));
393 /* round(u) is representable in tmp unless an overflow occurs */
394 MPFR_BLOCK (flags, mpfr_round (tmp, u));
395 __gmpfr_flags = saved_flags;
396 inex = (MPFR_OVERFLOW (flags)
397 ? mpfr_overflow (r, rnd_mode, MPFR_SIGN (u))
398 : mpfr_set (r, tmp, rnd_mode));
399 mpfr_clear (tmp);
400 return inex;
401 }
402 }
403
404 #undef mpfr_rint_trunc
405
406 int
mpfr_rint_trunc(mpfr_ptr r,mpfr_srcptr u,mpfr_rnd_t rnd_mode)407 mpfr_rint_trunc (mpfr_ptr r, mpfr_srcptr u, mpfr_rnd_t rnd_mode)
408 {
409 if (MPFR_UNLIKELY( MPFR_IS_SINGULAR(u) ) || mpfr_integer_p (u))
410 return mpfr_set (r, u, rnd_mode);
411 else
412 {
413 mpfr_t tmp;
414 int inex;
415 mpfr_flags_t saved_flags = __gmpfr_flags;
416
417 mpfr_init2 (tmp, MPFR_PREC (u));
418 /* trunc(u) is always representable in tmp */
419 mpfr_trunc (tmp, u);
420 __gmpfr_flags = saved_flags;
421 inex = mpfr_set (r, tmp, rnd_mode);
422 mpfr_clear (tmp);
423 return inex;
424 }
425 }
426
427 #undef mpfr_rint_ceil
428
429 int
mpfr_rint_ceil(mpfr_ptr r,mpfr_srcptr u,mpfr_rnd_t rnd_mode)430 mpfr_rint_ceil (mpfr_ptr r, mpfr_srcptr u, mpfr_rnd_t rnd_mode)
431 {
432 if (MPFR_UNLIKELY( MPFR_IS_SINGULAR(u) ) || mpfr_integer_p (u))
433 return mpfr_set (r, u, rnd_mode);
434 else
435 {
436 mpfr_t tmp;
437 int inex;
438 mpfr_flags_t saved_flags = __gmpfr_flags;
439 MPFR_BLOCK_DECL (flags);
440
441 mpfr_init2 (tmp, MPFR_PREC (u));
442 /* ceil(u) is representable in tmp unless an overflow occurs */
443 MPFR_BLOCK (flags, mpfr_ceil (tmp, u));
444 __gmpfr_flags = saved_flags;
445 inex = (MPFR_OVERFLOW (flags)
446 ? mpfr_overflow (r, rnd_mode, MPFR_SIGN_POS)
447 : mpfr_set (r, tmp, rnd_mode));
448 mpfr_clear (tmp);
449 return inex;
450 }
451 }
452
453 #undef mpfr_rint_floor
454
455 int
mpfr_rint_floor(mpfr_ptr r,mpfr_srcptr u,mpfr_rnd_t rnd_mode)456 mpfr_rint_floor (mpfr_ptr r, mpfr_srcptr u, mpfr_rnd_t rnd_mode)
457 {
458 if (MPFR_UNLIKELY( MPFR_IS_SINGULAR(u) ) || mpfr_integer_p (u))
459 return mpfr_set (r, u, rnd_mode);
460 else
461 {
462 mpfr_t tmp;
463 int inex;
464 mpfr_flags_t saved_flags = __gmpfr_flags;
465 MPFR_BLOCK_DECL (flags);
466
467 mpfr_init2 (tmp, MPFR_PREC (u));
468 /* floor(u) is representable in tmp unless an overflow occurs */
469 MPFR_BLOCK (flags, mpfr_floor (tmp, u));
470 __gmpfr_flags = saved_flags;
471 inex = (MPFR_OVERFLOW (flags)
472 ? mpfr_overflow (r, rnd_mode, MPFR_SIGN_NEG)
473 : mpfr_set (r, tmp, rnd_mode));
474 mpfr_clear (tmp);
475 return inex;
476 }
477 }
478