diff options
author | vlefevre <vlefevre@280ebfd0-de03-0410-8827-d642c229c3f4> | 2004-09-30 16:06:25 +0000 |
---|---|---|
committer | vlefevre <vlefevre@280ebfd0-de03-0410-8827-d642c229c3f4> | 2004-09-30 16:06:25 +0000 |
commit | 046a99a3dded4fe32a2b59194bfa8456e4a7ebce (patch) | |
tree | b78a738e42c6dcdf347e8e91850852a0c46c4a4f | |
parent | da0fbcf750b224a536d3d7c0808e9de7ee9f5eb7 (diff) | |
download | mpfr-046a99a3dded4fe32a2b59194bfa8456e4a7ebce.tar.gz |
Added functions mpfr_rint_round, mpfr_rint_trunc, mpfr_rint_ceil,
mpfr_rint_floor.
git-svn-id: svn://scm.gforge.inria.fr/svn/mpfr/trunk@3016 280ebfd0-de03-0410-8827-d642c229c3f4
-rw-r--r-- | mpfr.h | 4 | ||||
-rw-r--r-- | mpfr.texi | 15 | ||||
-rw-r--r-- | rint.c | 105 | ||||
-rw-r--r-- | tests/trint.c | 22 |
4 files changed, 135 insertions, 11 deletions
@@ -360,6 +360,10 @@ int mpfr_round _MPFR_PROTO((mpfr_ptr, mpfr_srcptr)); int mpfr_trunc _MPFR_PROTO((mpfr_ptr, mpfr_srcptr)); int mpfr_ceil _MPFR_PROTO((mpfr_ptr, mpfr_srcptr)); int mpfr_floor _MPFR_PROTO((mpfr_ptr, mpfr_srcptr)); +int mpfr_rint_round _MPFR_PROTO((mpfr_ptr, mpfr_srcptr, mpfr_rnd_t)); +int mpfr_rint_trunc _MPFR_PROTO((mpfr_ptr, mpfr_srcptr, mpfr_rnd_t)); +int mpfr_rint_ceil _MPFR_PROTO((mpfr_ptr, mpfr_srcptr, mpfr_rnd_t)); +int mpfr_rint_floor _MPFR_PROTO((mpfr_ptr, mpfr_srcptr, mpfr_rnd_t)); int mpfr_frac _MPFR_PROTO((mpfr_ptr, mpfr_srcptr, mpfr_rnd_t)); int mpfr_fits_ulong_p _MPFR_PROTO((mpfr_srcptr, mpfr_rnd_t)); @@ -1387,6 +1387,21 @@ in binary) in 2-bit precision, though @code{round(4.5)} is equal to 5 and 5 (101 in binary) is rounded to 6 (110 in binary) in 2-bit precision. @end deftypefun +@deftypefun int mpfr_rint_ceil (mpfr_t @var{rop}, mpfr_t @var{op}, mp_rnd_t @var{rnd}) +@deftypefunx int mpfr_rint_floor (mpfr_t @var{rop}, mpfr_t @var{op}, mp_rnd_t @var{rnd}) +@deftypefunx int mpfr_rint_round (mpfr_t @var{rop}, mpfr_t @var{op}, mp_rnd_t @var{rnd}) +@deftypefunx int mpfr_rint_trunc (mpfr_t @var{rop}, mpfr_t @var{op}, mp_rnd_t @var{rnd}) +Set @var{rop} to @var{op} rounded to an integer. +@code{mpfr_rint_ceil} rounds to the next higher or equal integer, +@code{mpfr_rint_floor} to the next lower or equal integer, +@code{mpfr_rint_round} to the nearest integer, rounding halfway cases away +from zero, and @code{mpfr_rint_trunc} to the next integer towards zero. +If the result is not representable, it is rounded in the direction @var{rnd}. +The returned value is the ternary value associated with the considered +round-to-integer function (regarded in the same way as any other +mathematical function). +@end deftypefun + @deftypefun int mpfr_frac (mpfr_t @var{rop}, mpfr_t @var{op}, mp_rnd_t @var{rnd}) Set @var{rop} to the fractional part of @var{op}, having the same sign as @var{op}, rounded in the direction @var{rnd} (unlike in @code{mpfr_rint}, @@ -24,7 +24,7 @@ MA 02111-1307, USA. */ /* Merge the following mpfr_rint code with mpfr_round_raw_generic? */ int -mpfr_rint (mpfr_ptr r, mpfr_srcptr u, mp_rnd_t rnd_mode) +mpfr_rint (mpfr_ptr r, mpfr_srcptr u, mpfr_rnd_t rnd_mode) { int sign; int rnd_away; @@ -51,7 +51,7 @@ mpfr_rint (mpfr_ptr r, mpfr_srcptr u, mp_rnd_t rnd_mode) } } MPFR_SET_SAME_SIGN(r, u); - + sign = MPFR_INT_SIGN(u); exp = MPFR_GET_EXP (u); @@ -327,3 +327,104 @@ mpfr_floor (mpfr_ptr r, mpfr_srcptr u) { return mpfr_rint(r, u, GMP_RNDD); } + +#undef mpfr_rint_round + +int +mpfr_rint_round (mpfr_ptr r, mpfr_srcptr u, mpfr_rnd_t rnd_mode) +{ + if (MPFR_UNLIKELY( MPFR_IS_SINGULAR(u) ) || mpfr_integer_p (u)) + return mpfr_set (r, u, rnd_mode); + else + { + mpfr_t tmp; + int inex; + + mpfr_save_emin_emax (); + mpfr_init2 (tmp, MPFR_PREC (u)); + /* round(u) is representable in tmp unless an overflow occurs */ + mpfr_clear_overflow (); + mpfr_round (tmp, u); + inex = (mpfr_overflow_p () + ? mpfr_set_overflow (r, rnd_mode, MPFR_SIGN (u)) + : mpfr_set (r, tmp, rnd_mode)); + mpfr_clear (tmp); + mpfr_restore_emin_emax (); + return mpfr_check_range (r, inex, rnd_mode); + } +} + +#undef mpfr_rint_trunc + +int +mpfr_rint_trunc (mpfr_ptr r, mpfr_srcptr u, mpfr_rnd_t rnd_mode) +{ + if (MPFR_UNLIKELY( MPFR_IS_SINGULAR(u) ) || mpfr_integer_p (u)) + return mpfr_set (r, u, rnd_mode); + else + { + mpfr_t tmp; + int inex; + + mpfr_save_emin_emax (); + mpfr_init2 (tmp, MPFR_PREC (u)); + /* trunc(u) is always representable in tmp */ + mpfr_trunc (tmp, u); + inex = mpfr_set (r, tmp, rnd_mode); + mpfr_clear (tmp); + mpfr_restore_emin_emax (); + return mpfr_check_range (r, inex, rnd_mode); + } +} + +#undef mpfr_rint_ceil + +int +mpfr_rint_ceil (mpfr_ptr r, mpfr_srcptr u, mpfr_rnd_t rnd_mode) +{ + if (MPFR_UNLIKELY( MPFR_IS_SINGULAR(u) ) || mpfr_integer_p (u)) + return mpfr_set (r, u, rnd_mode); + else + { + mpfr_t tmp; + int inex; + + mpfr_save_emin_emax (); + mpfr_init2 (tmp, MPFR_PREC (u)); + /* ceil(u) is representable in tmp unless an overflow occurs */ + mpfr_clear_overflow (); + mpfr_ceil (tmp, u); + inex = (mpfr_overflow_p () + ? mpfr_set_overflow (r, rnd_mode, MPFR_SIGN_POS) + : mpfr_set (r, tmp, rnd_mode)); + mpfr_clear (tmp); + mpfr_restore_emin_emax (); + return mpfr_check_range (r, inex, rnd_mode); + } +} + +#undef mpfr_rint_floor + +int +mpfr_rint_floor (mpfr_ptr r, mpfr_srcptr u, mpfr_rnd_t rnd_mode) +{ + if (MPFR_UNLIKELY( MPFR_IS_SINGULAR(u) ) || mpfr_integer_p (u)) + return mpfr_set (r, u, rnd_mode); + else + { + mpfr_t tmp; + int inex; + + mpfr_save_emin_emax (); + mpfr_init2 (tmp, MPFR_PREC (u)); + /* floor(u) is representable in tmp unless an overflow occurs */ + mpfr_clear_overflow (); + mpfr_floor (tmp, u); + inex = (mpfr_overflow_p () + ? mpfr_set_overflow (r, rnd_mode, MPFR_SIGN_NEG) + : mpfr_set (r, tmp, rnd_mode)); + mpfr_clear (tmp); + mpfr_restore_emin_emax (); + return mpfr_check_range (r, inex, rnd_mode); + } +} diff --git a/tests/trint.c b/tests/trint.c index a7475bed5..e2b66939d 100644 --- a/tests/trint.c +++ b/tests/trint.c @@ -243,25 +243,29 @@ main (int argc, char *argv[]) mpfr_set_prec (y, p); mpfr_set_prec (v, p); for (r = 0; r < GMP_RND_MAX ; r++) - for (trint = 0; trint < 2; trint++) + for (trint = 0; trint < 3; trint++) { - if (trint) + if (trint == 2) inexact = mpfr_rint (y, x, r); else if (r == GMP_RNDN) inexact = mpfr_round (y, x); else if (r == GMP_RNDZ) - inexact = mpfr_trunc (y, x); + inexact = (trint ? mpfr_trunc (y, x) : + mpfr_rint_trunc (y, x, GMP_RNDZ)); else if (r == GMP_RNDU) - inexact = mpfr_ceil (y, x); + inexact = (trint ? mpfr_ceil (y, x) : + mpfr_rint_ceil (y, x, GMP_RNDU)); else /* r = GMP_RNDD */ - inexact = mpfr_floor (y, x); + inexact = (trint ? mpfr_floor (y, x) : + mpfr_rint_floor (y, x, GMP_RNDD)); if (mpfr_sub (t, y, x, GMP_RNDN)) err ("subtraction 1 should be exact", s, x, y, p, r, trint, inexact); sign_t = mpfr_cmp_ui (t, 0); - if (((inexact == 0) && (sign_t != 0)) || - ((inexact < 0) && (sign_t >= 0)) || - ((inexact > 0) && (sign_t <= 0))) + if (trint != 0 && + (((inexact == 0) && (sign_t != 0)) || + ((inexact < 0) && (sign_t >= 0)) || + ((inexact > 0) && (sign_t <= 0)))) err ("wrong inexact flag", s, x, y, p, r, trint, inexact); if (inexact == 0) continue; /* end of the test for exact results */ @@ -300,7 +304,7 @@ main (int argc, char *argv[]) continue; /* |t| = |u|: x is the middle of two consecutive representable integers. */ - if (trint) + if (trint == 2) { /* halfway case for mpfr_rint in GMP_RNDN rounding mode: round to an even integer or mantissa. */ |