1 /* mpfr_rint -- Round to an integer.
3 Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
4 Contributed by the Arenaire and Cacao projects, INRIA.
6 This file is part of the GNU MPFR Library.
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 2.1 of the License, or (at your
11 option) any later version.
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.
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.LIB. If not, write to
20 the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
21 MA 02110-1301, USA. */
23 #include "mpfr-impl.h"
25 /* Merge the following mpfr_rint code with mpfr_round_raw_generic? */
28 mpfr_rint (mpfr_ptr r
, mpfr_srcptr u
, mpfr_rnd_t rnd_mode
)
34 if (MPFR_UNLIKELY( MPFR_IS_SINGULAR(u
) ))
41 MPFR_SET_SAME_SIGN(r
, u
);
45 MPFR_RET(0); /* infinity is exact */
47 else /* now u is zero */
49 MPFR_ASSERTD(MPFR_IS_ZERO(u
));
51 MPFR_RET(0); /* zero is exact */
54 MPFR_SET_SAME_SIGN (r
, u
); /* Does nothing if r==u */
56 sign
= MPFR_INT_SIGN (u
);
57 exp
= MPFR_GET_EXP (u
);
60 rnd_mode
== GMP_RNDD
? sign
< 0 :
61 rnd_mode
== GMP_RNDU
? sign
> 0 :
62 rnd_mode
== GMP_RNDZ
? 0 : -1;
65 1 if round away from zero,
67 -1 if not decided yet.
70 if (MPFR_UNLIKELY (exp
<= 0)) /* 0 < |u| < 1 ==> round |u| to 0 or 1 */
72 /* Note: in the GMP_RNDN mode, 0.5 must be rounded to 0. */
75 (exp
== 0 && (rnd_mode
== GMP_RNDNA
||
76 !mpfr_powerof2_raw (u
)))))
82 rm
= (MPFR_PREC(r
) - 1) / BITS_PER_MP_LIMB
;
83 rp
[rm
] = MPFR_LIMB_HIGHBIT
;
85 MPFR_SET_EXP (r
, 1); /* |r| = 1 */
86 MPFR_RET(sign
> 0 ? 2 : -2);
90 MPFR_SET_ZERO(r
); /* r = 0 */
91 MPFR_RET(sign
> 0 ? -2 : 2);
94 else /* exp > 0, |u| >= 1 */
102 * uflags will contain:
103 * _ 0 if u is an integer representable in r,
104 * _ 1 if u is an integer not representable in r,
105 * _ 2 if u is not an integer.
111 un
= MPFR_LIMB_SIZE(u
);
112 rn
= MPFR_LIMB_SIZE(r
);
113 MPFR_UNSIGNED_MINUS_MODULO (sh
, MPFR_PREC (r
));
115 MPFR_SET_EXP (r
, exp
); /* Does nothing if r==u */
117 if ((exp
- 1) / BITS_PER_MP_LIMB
>= un
)
121 uflags
= 0; /* u is an integer, representable or not in r */
127 ui
= (exp
- 1) / BITS_PER_MP_LIMB
+ 1; /* #limbs of the int part */
128 MPFR_ASSERTD (un
>= ui
);
129 uj
= un
- ui
; /* lowest limb of the integer part */
130 idiff
= exp
% BITS_PER_MP_LIMB
; /* #int-part bits in up[uj] or 0 */
132 uflags
= idiff
== 0 || (up
[uj
] << idiff
) == 0 ? 0 : 2;
144 /* More limbs in the integer part of u than in r.
145 Just round u with the precision of r. */
146 MPFR_ASSERTD (rp
!= up
&& un
> rn
);
147 MPN_COPY (rp
, up
+ (un
- rn
), rn
); /* r != u */
150 /* This is a rounding to nearest mode (GMP_RNDN or GMP_RNDNA).
151 Decide the rounding direction here. */
152 if (rnd_mode
== GMP_RNDN
&&
153 (rp
[0] & (MPFR_LIMB_ONE
<< sh
)) == 0)
154 { /* halfway cases rounded towards zero */
156 /* a: rounding bit and some of the following bits */
157 /* b: boundary for a (weight of the rounding bit in a) */
160 a
= rp
[0] & ((MPFR_LIMB_ONE
<< sh
) - 1);
161 b
= MPFR_LIMB_ONE
<< (sh
- 1);
166 b
= MPFR_LIMB_HIGHBIT
;
172 for (i
= un
- rn
- 1 - (sh
== 0); i
>= 0; i
--)
180 else /* halfway cases rounded away from zero */
181 rnd_away
= /* rounding bit */
182 ((sh
!= 0 && (rp
[0] & (MPFR_LIMB_ONE
<< (sh
- 1))) != 0) ||
183 (sh
== 0 && (up
[un
- rn
- 1] & MPFR_LIMB_HIGHBIT
) != 0));
186 { /* u is an integer; determine if it is representable in r */
187 if (sh
!= 0 && rp
[0] << (BITS_PER_MP_LIMB
- sh
) != 0)
188 uflags
= 1; /* u is not representable in r */
192 for (i
= un
- rn
- 1; i
>= 0; i
--)
195 uflags
= 1; /* u is not representable in r */
206 uj
= un
- ui
; /* lowest limb of the integer part in u */
207 rj
= rn
- ui
; /* lowest limb of the integer part in r */
209 if (MPFR_LIKELY (rp
!= up
))
210 MPN_COPY(rp
+ rj
, up
+ uj
, ui
);
212 /* Ignore the lowest rj limbs, all equal to zero. */
216 /* number of fractional bits in whole rp[0] */
217 ush
= idiff
== 0 ? 0 : BITS_PER_MP_LIMB
- idiff
;
219 if (rj
== 0 && ush
< sh
)
221 /* If u is an integer (uflags == 0), we need to determine
222 if it is representable in r, i.e. if its sh - ush bits
223 in the non-significant part of r are all 0. */
224 if (uflags
== 0 && (rp
[0] & ((MPFR_LIMB_ONE
<< sh
) -
225 (MPFR_LIMB_ONE
<< ush
))) != 0)
226 uflags
= 1; /* u is an integer not representable in r */
228 else /* The integer part of u fits in r, we'll round to it. */
233 /* This is a rounding to nearest mode.
234 Decide the rounding direction here. */
235 if (uj
== 0 && sh
== 0)
236 rnd_away
= 0; /* rounding bit = 0 (not represented in u) */
237 else if (rnd_mode
== GMP_RNDN
&&
238 (rp
[0] & (MPFR_LIMB_ONE
<< sh
)) == 0)
239 { /* halfway cases rounded towards zero */
241 /* a: rounding bit and some of the following bits */
242 /* b: boundary for a (weight of the rounding bit in a) */
245 a
= rp
[0] & ((MPFR_LIMB_ONE
<< sh
) - 1);
246 b
= MPFR_LIMB_ONE
<< (sh
- 1);
250 MPFR_ASSERTD (uj
>= 1); /* see above */
252 b
= MPFR_LIMB_HIGHBIT
;
258 for (i
= uj
- 1 - (sh
== 0); i
>= 0; i
--)
266 else /* halfway cases rounded away from zero */
267 rnd_away
= /* rounding bit */
268 ((sh
!= 0 && (rp
[0] & (MPFR_LIMB_ONE
<< (sh
- 1))) != 0) ||
269 (sh
== 0 && (MPFR_ASSERTD (uj
>= 1),
270 up
[uj
- 1] & MPFR_LIMB_HIGHBIT
) != 0));
272 /* Now we can make the low rj limbs to 0 */
273 MPN_ZERO (rp
-rj
, rj
);
277 rp
[0] &= MP_LIMB_T_MAX
<< sh
;
279 /* If u is a representable integer, there is no rounding. */
283 MPFR_ASSERTD (rnd_away
>= 0); /* rounding direction is defined */
284 if (rnd_away
&& mpn_add_1(rp
, rp
, rn
, MPFR_LIMB_ONE
<< sh
))
286 if (exp
== __gmpfr_emax
)
287 return mpfr_overflow(r
, rnd_mode
, MPFR_SIGN(r
)) >= 0 ?
291 MPFR_SET_EXP(r
, exp
+ 1);
292 rp
[rn
-1] = MPFR_LIMB_HIGHBIT
;
296 MPFR_RET (rnd_away
^ (sign
< 0) ? uflags
: -uflags
);
297 } /* exp > 0, |u| >= 1 */
303 mpfr_round (mpfr_ptr r
, mpfr_srcptr u
)
305 return mpfr_rint(r
, u
, GMP_RNDNA
);
311 mpfr_trunc (mpfr_ptr r
, mpfr_srcptr u
)
313 return mpfr_rint(r
, u
, GMP_RNDZ
);
319 mpfr_ceil (mpfr_ptr r
, mpfr_srcptr u
)
321 return mpfr_rint(r
, u
, GMP_RNDU
);
327 mpfr_floor (mpfr_ptr r
, mpfr_srcptr u
)
329 return mpfr_rint(r
, u
, GMP_RNDD
);
332 #undef mpfr_rint_round
335 mpfr_rint_round (mpfr_ptr r
, mpfr_srcptr u
, mpfr_rnd_t rnd_mode
)
337 if (MPFR_UNLIKELY( MPFR_IS_SINGULAR(u
) ) || mpfr_integer_p (u
))
338 return mpfr_set (r
, u
, rnd_mode
);
343 MPFR_SAVE_EXPO_DECL (expo
);
344 MPFR_BLOCK_DECL (flags
);
346 MPFR_SAVE_EXPO_MARK (expo
);
347 mpfr_init2 (tmp
, MPFR_PREC (u
));
348 /* round(u) is representable in tmp unless an overflow occurs */
349 MPFR_BLOCK (flags
, mpfr_round (tmp
, u
));
350 inex
= (MPFR_OVERFLOW (flags
)
351 ? mpfr_overflow (r
, rnd_mode
, MPFR_SIGN (u
))
352 : mpfr_set (r
, tmp
, rnd_mode
));
354 MPFR_SAVE_EXPO_FREE (expo
);
355 return mpfr_check_range (r
, inex
, rnd_mode
);
359 #undef mpfr_rint_trunc
362 mpfr_rint_trunc (mpfr_ptr r
, mpfr_srcptr u
, mpfr_rnd_t rnd_mode
)
364 if (MPFR_UNLIKELY( MPFR_IS_SINGULAR(u
) ) || mpfr_integer_p (u
))
365 return mpfr_set (r
, u
, rnd_mode
);
370 MPFR_SAVE_EXPO_DECL (expo
);
372 MPFR_SAVE_EXPO_MARK (expo
);
373 mpfr_init2 (tmp
, MPFR_PREC (u
));
374 /* trunc(u) is always representable in tmp */
376 inex
= mpfr_set (r
, tmp
, rnd_mode
);
378 MPFR_SAVE_EXPO_FREE (expo
);
379 return mpfr_check_range (r
, inex
, rnd_mode
);
383 #undef mpfr_rint_ceil
386 mpfr_rint_ceil (mpfr_ptr r
, mpfr_srcptr u
, mpfr_rnd_t rnd_mode
)
388 if (MPFR_UNLIKELY( MPFR_IS_SINGULAR(u
) ) || mpfr_integer_p (u
))
389 return mpfr_set (r
, u
, rnd_mode
);
394 MPFR_SAVE_EXPO_DECL (expo
);
395 MPFR_BLOCK_DECL (flags
);
397 MPFR_SAVE_EXPO_MARK (expo
);
398 mpfr_init2 (tmp
, MPFR_PREC (u
));
399 /* ceil(u) is representable in tmp unless an overflow occurs */
400 MPFR_BLOCK (flags
, mpfr_ceil (tmp
, u
));
401 inex
= (MPFR_OVERFLOW (flags
)
402 ? mpfr_overflow (r
, rnd_mode
, MPFR_SIGN_POS
)
403 : mpfr_set (r
, tmp
, rnd_mode
));
405 MPFR_SAVE_EXPO_FREE (expo
);
406 return mpfr_check_range (r
, inex
, rnd_mode
);
410 #undef mpfr_rint_floor
413 mpfr_rint_floor (mpfr_ptr r
, mpfr_srcptr u
, mpfr_rnd_t rnd_mode
)
415 if (MPFR_UNLIKELY( MPFR_IS_SINGULAR(u
) ) || mpfr_integer_p (u
))
416 return mpfr_set (r
, u
, rnd_mode
);
421 MPFR_SAVE_EXPO_DECL (expo
);
422 MPFR_BLOCK_DECL (flags
);
424 MPFR_SAVE_EXPO_MARK (expo
);
425 mpfr_init2 (tmp
, MPFR_PREC (u
));
426 /* floor(u) is representable in tmp unless an overflow occurs */
427 MPFR_BLOCK (flags
, mpfr_floor (tmp
, u
));
428 inex
= (MPFR_OVERFLOW (flags
)
429 ? mpfr_overflow (r
, rnd_mode
, MPFR_SIGN_NEG
)
430 : mpfr_set (r
, tmp
, rnd_mode
));
432 MPFR_SAVE_EXPO_FREE (expo
);
433 return mpfr_check_range (r
, inex
, rnd_mode
);