diff options
author | zimmerma <zimmerma@280ebfd0-de03-0410-8827-d642c229c3f4> | 2012-03-26 14:11:26 +0000 |
---|---|---|
committer | zimmerma <zimmerma@280ebfd0-de03-0410-8827-d642c229c3f4> | 2012-03-26 14:11:26 +0000 |
commit | d174cbec56809cb5c6e079f09927525e71b83cba (patch) | |
tree | 6f8b36db1d9738f889ee3fdeac085acc42c9e73f | |
parent | cd495f23ec3954e722b7c51b3146edf3aac54ea3 (diff) | |
download | mpfr-d174cbec56809cb5c6e079f09927525e71b83cba.tar.gz |
added new function mpfr_fmodquo
(cf https://sympa.inria.fr/sympa/arc/mpfr/2012-03/msg00020.html)
git-svn-id: svn://scm.gforge.inria.fr/svn/mpfr/trunk@8129 280ebfd0-de03-0410-8827-d642c229c3f4
-rw-r--r-- | NEWS | 2 | ||||
-rw-r--r-- | doc/mpfr.texi | 8 | ||||
-rw-r--r-- | src/mpfr.h | 2 | ||||
-rw-r--r-- | src/rem1.c | 7 | ||||
-rw-r--r-- | tests/tremquo.c | 129 | ||||
-rwxr-xr-x | tools/cfarm.sh | 8 |
6 files changed, 149 insertions, 7 deletions
@@ -25,6 +25,8 @@ Changes from versions 3.1.* to version 3.2.0: - New functions: mpfr_fpif_export and mpfr_fpif_import to export and import numbers in a floating-point interchange format, independent both on the number of bits per word and on the endianness. +- New function mpfr_fmodquo to return the low bits of the quotient + corresponding to mpfr_fmod. - Updated tuning parameters. - Improved MPFR manual. - Bug fixes. diff --git a/doc/mpfr.texi b/doc/mpfr.texi index 619b53d76..cf3bdfa74 100644 --- a/doc/mpfr.texi +++ b/doc/mpfr.texi @@ -2525,13 +2525,15 @@ corresponding precision of @var{iop} and @var{fop} (equivalent to @end deftypefun @deftypefun int mpfr_fmod (mpfr_t @var{r}, mpfr_t @var{x}, mpfr_t @var{y}, mpfr_rnd_t @var{rnd}) +@deftypefunx int mpfr_fmodquo (mpfr_t @var{r}, long* @var{q}, mpfr_t @var{x}, mpfr_t @var{y}, mpfr_rnd_t @var{rnd}) @deftypefunx int mpfr_remainder (mpfr_t @var{r}, mpfr_t @var{x}, mpfr_t @var{y}, mpfr_rnd_t @var{rnd}) @deftypefunx int mpfr_remquo (mpfr_t @var{r}, long* @var{q}, mpfr_t @var{x}, mpfr_t @var{y}, mpfr_rnd_t @var{rnd}) Set @var{r} to the value of @math{@var{x} - @var{n}@var{y}}, rounded according to the direction @var{rnd}, where @var{n} is the integer quotient of @var{x} divided by @var{y}, defined as follows: @var{n} is rounded -toward zero for @code{mpfr_fmod}, and to the nearest integer (ties rounded -to even) for @code{mpfr_remainder} and @code{mpfr_remquo}. +toward zero for @code{mpfr_fmod} and @code{mpfr_fmodquo}, +and to the nearest integer (ties rounded to even) for @code{mpfr_remainder} +and @code{mpfr_remquo}. Special values are handled as described in Section F.9.7.1 of the ISO C99 standard: @@ -2541,7 +2543,7 @@ to the precision of @var{r}. If @var{r} is zero, it has the sign of @var{x}. The return value is the ternary value corresponding to @var{r}. -Additionally, @code{mpfr_remquo} stores +Additionally, @code{mpfr_fmodquo} and @code{mpfr_remquo} store the low significant bits from the quotient @var{n} in @var{*q} (more precisely the number of bits in a @code{long} minus one), with the sign of @var{x} divided by @var{y} diff --git a/src/mpfr.h b/src/mpfr.h index d3d7fbeeb..ce29a1eaf 100644 --- a/src/mpfr.h +++ b/src/mpfr.h @@ -587,6 +587,8 @@ __MPFR_DECLSPEC int mpfr_remainder _MPFR_PROTO ((mpfr_ptr, mpfr_srcptr, mpfr_srcptr, mpfr_rnd_t)); __MPFR_DECLSPEC int mpfr_fmod _MPFR_PROTO ((mpfr_ptr, mpfr_srcptr, mpfr_srcptr, mpfr_rnd_t)); +__MPFR_DECLSPEC int mpfr_fmodquo _MPFR_PROTO ((mpfr_ptr, long*, mpfr_srcptr, + mpfr_srcptr, mpfr_rnd_t)); __MPFR_DECLSPEC int mpfr_fits_ulong_p _MPFR_PROTO((mpfr_srcptr, mpfr_rnd_t)); __MPFR_DECLSPEC int mpfr_fits_slong_p _MPFR_PROTO((mpfr_srcptr, mpfr_rnd_t)); diff --git a/src/rem1.c b/src/rem1.c index a3f91f0e4..f49f167bd 100644 --- a/src/rem1.c +++ b/src/rem1.c @@ -227,3 +227,10 @@ mpfr_fmod (mpfr_ptr rem, mpfr_srcptr x, mpfr_srcptr y, mpfr_rnd_t rnd) { return mpfr_rem1 (rem, (long *) 0, MPFR_RNDZ, x, y, rnd); } + +int +mpfr_fmodquo (mpfr_ptr rem, long *quo, mpfr_srcptr x, mpfr_srcptr y, + mpfr_rnd_t rnd) +{ + return mpfr_rem1 (rem, quo, MPFR_RNDZ, x, y, rnd); +} diff --git a/tests/tremquo.c b/tests/tremquo.c index ef051a73b..0bbfb2c4d 100644 --- a/tests/tremquo.c +++ b/tests/tremquo.c @@ -1,4 +1,4 @@ -/* tremquo -- test file for mpfr_remquo and mpfr_remainder +/* tremquo -- test file for mpfr_remquo, mpfr_remainder and mpfr_fmodquo. Copyright 2007, 2008, 2009, 2010, 2011, 2012 Free Software Foundation, Inc. Contributed by the AriC and Caramel projects, INRIA. @@ -87,32 +87,45 @@ main (int argc, char *argv[]) mpfr_set_ui (y, 1, MPFR_RNDN); mpfr_remquo (r, q, x, y, MPFR_RNDN); MPFR_ASSERTN(mpfr_nan_p (r)); + mpfr_fmodquo (r, q, x, y, MPFR_RNDN); + MPFR_ASSERTN(mpfr_nan_p (r)); mpfr_set_ui (x, 1, MPFR_RNDN); mpfr_set_nan (y); mpfr_remquo (r, q, x, y, MPFR_RNDN); MPFR_ASSERTN(mpfr_nan_p (r)); + mpfr_fmodquo (r, q, x, y, MPFR_RNDN); + MPFR_ASSERTN(mpfr_nan_p (r)); mpfr_set_inf (x, 1); /* +Inf */ mpfr_set_ui (y, 1, MPFR_RNDN); mpfr_remquo (r, q, x, y, MPFR_RNDN); MPFR_ASSERTN (mpfr_nan_p (r)); + mpfr_fmodquo (r, q, x, y, MPFR_RNDN); + MPFR_ASSERTN (mpfr_nan_p (r)); mpfr_set_inf (x, 1); /* +Inf */ mpfr_set_ui (y, 0, MPFR_RNDN); mpfr_remquo (r, q, x, y, MPFR_RNDN); MPFR_ASSERTN (mpfr_nan_p (r)); + mpfr_fmodquo (r, q, x, y, MPFR_RNDN); + MPFR_ASSERTN (mpfr_nan_p (r)); mpfr_set_inf (x, 1); /* +Inf */ mpfr_set_inf (y, 1); mpfr_remquo (r, q, x, y, MPFR_RNDN); MPFR_ASSERTN (mpfr_nan_p (r)); + mpfr_fmodquo (r, q, x, y, MPFR_RNDN); + MPFR_ASSERTN (mpfr_nan_p (r)); mpfr_set_ui (x, 0, MPFR_RNDN); mpfr_set_inf (y, 1); mpfr_remquo (r, q, x, y, MPFR_RNDN); MPFR_ASSERTN (mpfr_cmp_ui (r, 0) == 0 && MPFR_IS_POS (r)); MPFR_ASSERTN (q[0] == (long) 0); + mpfr_fmodquo (r, q, x, y, MPFR_RNDN); + MPFR_ASSERTN (mpfr_cmp_ui (r, 0) == 0 && MPFR_IS_POS (r)); + MPFR_ASSERTN (q[0] == (long) 0); mpfr_set_ui (x, 0, MPFR_RNDN); mpfr_neg (x, x, MPFR_RNDN); /* -0 */ @@ -120,23 +133,34 @@ main (int argc, char *argv[]) mpfr_remquo (r, q, x, y, MPFR_RNDN); MPFR_ASSERTN (mpfr_cmp_ui (r, 0) == 0 && MPFR_IS_NEG (r)); MPFR_ASSERTN (q[0] == (long) 0); + mpfr_fmodquo (r, q, x, y, MPFR_RNDN); + MPFR_ASSERTN (mpfr_cmp_ui (r, 0) == 0 && MPFR_IS_NEG (r)); + MPFR_ASSERTN (q[0] == (long) 0); mpfr_set_ui (x, 17, MPFR_RNDN); mpfr_set_inf (y, 1); mpfr_remquo (r, q, x, y, MPFR_RNDN); MPFR_ASSERTN (mpfr_cmp (r, x) == 0); MPFR_ASSERTN (q[0] == (long) 0); + mpfr_fmodquo (r, q, x, y, MPFR_RNDN); + MPFR_ASSERTN (mpfr_cmp (r, x) == 0); + MPFR_ASSERTN (q[0] == (long) 0); mpfr_set_ui (x, 17, MPFR_RNDN); mpfr_set_ui (y, 0, MPFR_RNDN); mpfr_remquo (r, q, x, y, MPFR_RNDN); MPFR_ASSERTN (mpfr_nan_p (r)); + mpfr_fmodquo (r, q, x, y, MPFR_RNDN); + MPFR_ASSERTN (mpfr_nan_p (r)); mpfr_set_ui (x, 0, MPFR_RNDN); mpfr_set_ui (y, 17, MPFR_RNDN); mpfr_remquo (r, q, x, y, MPFR_RNDN); MPFR_ASSERTN (mpfr_cmp_ui (r, 0) == 0 && MPFR_IS_POS (r)); MPFR_ASSERTN (q[0] == (long) 0); + mpfr_fmodquo (r, q, x, y, MPFR_RNDN); + MPFR_ASSERTN (mpfr_cmp_ui (r, 0) == 0 && MPFR_IS_POS (r)); + MPFR_ASSERTN (q[0] == (long) 0); mpfr_set_ui (x, 0, MPFR_RNDN); mpfr_neg (x, x, MPFR_RNDN); @@ -144,32 +168,88 @@ main (int argc, char *argv[]) mpfr_remquo (r, q, x, y, MPFR_RNDN); MPFR_ASSERTN (mpfr_cmp_ui (r, 0) == 0 && MPFR_IS_NEG (r)); MPFR_ASSERTN (q[0] == (long) 0); + mpfr_fmodquo (r, q, x, y, MPFR_RNDN); + MPFR_ASSERTN (mpfr_cmp_ui (r, 0) == 0 && MPFR_IS_NEG (r)); + MPFR_ASSERTN (q[0] == (long) 0); mpfr_set_prec (x, 53); mpfr_set_prec (y, 53); - /* check four possible sign combinations */ + /* check four possible sign combinations for 42/17 */ mpfr_set_ui (x, 42, MPFR_RNDN); mpfr_set_ui (y, 17, MPFR_RNDN); mpfr_remquo (r, q, x, y, MPFR_RNDN); MPFR_ASSERTN (mpfr_cmp_ui (r, 8) == 0); MPFR_ASSERTN (q[0] == (long) 2); + mpfr_fmodquo (r, q, x, y, MPFR_RNDN); + MPFR_ASSERTN (mpfr_cmp_ui (r, 8) == 0); + MPFR_ASSERTN (q[0] == (long) 2); + mpfr_set_si (x, -42, MPFR_RNDN); mpfr_set_ui (y, 17, MPFR_RNDN); mpfr_remquo (r, q, x, y, MPFR_RNDN); MPFR_ASSERTN (mpfr_cmp_si (r, -8) == 0); MPFR_ASSERTN (q[0] == (long) -2); + mpfr_fmodquo (r, q, x, y, MPFR_RNDN); + MPFR_ASSERTN (mpfr_cmp_si (r, -8) == 0); + MPFR_ASSERTN (q[0] == (long) -2); + mpfr_set_si (x, -42, MPFR_RNDN); mpfr_set_si (y, -17, MPFR_RNDN); mpfr_remquo (r, q, x, y, MPFR_RNDN); MPFR_ASSERTN (mpfr_cmp_si (r, -8) == 0); MPFR_ASSERTN (q[0] == (long) 2); + mpfr_fmodquo (r, q, x, y, MPFR_RNDN); + MPFR_ASSERTN (mpfr_cmp_si (r, -8) == 0); + MPFR_ASSERTN (q[0] == (long) 2); + mpfr_set_ui (x, 42, MPFR_RNDN); mpfr_set_si (y, -17, MPFR_RNDN); mpfr_remquo (r, q, x, y, MPFR_RNDN); MPFR_ASSERTN (mpfr_cmp_ui (r, 8) == 0); MPFR_ASSERTN (q[0] == (long) -2); + mpfr_fmodquo (r, q, x, y, MPFR_RNDN); + MPFR_ASSERTN (mpfr_cmp_ui (r, 8) == 0); + MPFR_ASSERTN (q[0] == (long) -2); + + /* same tests for 43/17, rounded to 3 to nearest, and to 2 to zero */ + mpfr_set_ui (x, 43, MPFR_RNDN); + mpfr_set_ui (y, 17, MPFR_RNDN); + mpfr_remquo (r, q, x, y, MPFR_RNDN); + MPFR_ASSERTN (mpfr_cmp_si (r, -8) == 0); + MPFR_ASSERTN (q[0] == (long) 3); + mpfr_fmodquo (r, q, x, y, MPFR_RNDN); + MPFR_ASSERTN (mpfr_cmp_ui (r, 9) == 0); + MPFR_ASSERTN (q[0] == (long) 2); + mpfr_set_si (x, -43, MPFR_RNDN); + mpfr_set_ui (y, 17, MPFR_RNDN); + mpfr_remquo (r, q, x, y, MPFR_RNDN); + MPFR_ASSERTN (mpfr_cmp_si (r, 8) == 0); + MPFR_ASSERTN (q[0] == (long) -3); + mpfr_fmodquo (r, q, x, y, MPFR_RNDN); + MPFR_ASSERTN (mpfr_cmp_si (r, -9) == 0); + MPFR_ASSERTN (q[0] == (long) -2); + + mpfr_set_si (x, -43, MPFR_RNDN); + mpfr_set_si (y, -17, MPFR_RNDN); + mpfr_remquo (r, q, x, y, MPFR_RNDN); + MPFR_ASSERTN (mpfr_cmp_si (r, 8) == 0); + MPFR_ASSERTN (q[0] == (long) 3); + mpfr_fmodquo (r, q, x, y, MPFR_RNDN); + MPFR_ASSERTN (mpfr_cmp_si (r, -9) == 0); + MPFR_ASSERTN (q[0] == (long) 2); + + mpfr_set_ui (x, 43, MPFR_RNDN); + mpfr_set_si (y, -17, MPFR_RNDN); + mpfr_remquo (r, q, x, y, MPFR_RNDN); + MPFR_ASSERTN (mpfr_cmp_si (r, -8) == 0); + MPFR_ASSERTN (q[0] == (long) -3); + mpfr_fmodquo (r, q, x, y, MPFR_RNDN); + MPFR_ASSERTN (mpfr_cmp_ui (r, 9) == 0); + MPFR_ASSERTN (q[0] == (long) -2); + + /* other tests */ mpfr_set_prec (x, 100); mpfr_set_prec (y, 50); mpfr_set_ui (x, 42, MPFR_RNDN); @@ -178,6 +258,9 @@ main (int argc, char *argv[]) mpfr_remquo (r, q, x, y, MPFR_RNDN); MPFR_ASSERTN (mpfr_cmp_ui_2exp (r, 1, -94) == 0); MPFR_ASSERTN (q[0] == (long) 2); + mpfr_fmodquo (r, q, x, y, MPFR_RNDN); + MPFR_ASSERTN (mpfr_cmp_ui_2exp (r, 1, -94) == 0); + MPFR_ASSERTN (q[0] == (long) 2); mpfr_set_prec (x, 50); mpfr_set_prec (y, 100); @@ -187,6 +270,9 @@ main (int argc, char *argv[]) mpfr_remquo (r, q, x, y, MPFR_RNDN); MPFR_ASSERTN (mpfr_cmp_ui_2exp (r, 1, -44) == 0); MPFR_ASSERTN (q[0] == (long) 2); + mpfr_fmodquo (r, q, x, y, MPFR_RNDN); + MPFR_ASSERTN (mpfr_cmp_ui_2exp (r, 1, -44) == 0); + MPFR_ASSERTN (q[0] == (long) 2); mpfr_set_prec (x, 100); mpfr_set_prec (y, 50); @@ -197,6 +283,11 @@ main (int argc, char *argv[]) /* r should be 42 - 2*(21 + 2^(-45)) = -2^(-44) */ MPFR_ASSERTN (mpfr_cmp_si_2exp (r, -1, -44) == 0); MPFR_ASSERTN (q[0] == (long) 2); + mpfr_fmodquo (r, q, x, y, MPFR_RNDN); + /* r should be 42 - (21 + 2^(-45) = 21 - 2^(-45) */ + mpfr_sub_ui (r, r, 21, MPFR_RNDN); + MPFR_ASSERTN (mpfr_cmp_si_2exp (r, -1, -45) == 0); + MPFR_ASSERTN (q[0] == (long) 1); mpfr_set_prec (x, 50); mpfr_set_prec (y, 100); @@ -207,6 +298,11 @@ main (int argc, char *argv[]) /* r should be 42 - 2*(21 + 2^(-95)) = -2^(-94) */ MPFR_ASSERTN (mpfr_cmp_si_2exp (r, -1, -94) == 0); MPFR_ASSERTN (q[0] == (long) 2); + mpfr_fmodquo (r, q, x, y, MPFR_RNDN); + /* r should be 42 - (21 + 2^(-95) = 21 - 2^(-94), which rounded to 53 bits + should give 21 */ + MPFR_ASSERTN (mpfr_cmp_ui (r, 21) == 0); + MPFR_ASSERTN (q[0] == (long) 1); /* exercise large quotient */ mpfr_set_ui_2exp (x, 1, 65, MPFR_RNDN); @@ -215,6 +311,9 @@ main (int argc, char *argv[]) mpfr_remquo (r, q, x, y, MPFR_RNDN); MPFR_ASSERTN (mpfr_cmp_si (r, 0) == 0); MPFR_ASSERTN (q[0] % 1073741824L == 0L); + mpfr_fmodquo (r, q, x, y, MPFR_RNDN); + MPFR_ASSERTN (mpfr_cmp_si (r, 0) == 0); + MPFR_ASSERTN (q[0] % 1073741824L == 0L); /* another large quotient */ mpfr_set_prec (x, 65); @@ -227,6 +326,10 @@ main (int argc, char *argv[]) /* q should be 41803643793084085130, r should be 605/2048 */ MPFR_ASSERTN (mpfr_cmp_ui_2exp (r, 605, -11) == 0); MPFR_ASSERTN ((q[0] > 0) && ((q[0] % 1073741824L) == 733836170L)); + mpfr_fmodquo (r, q, x, y, MPFR_RNDN); + /* q should be 41803643793084085130, r should be 605/2048 */ + MPFR_ASSERTN (mpfr_cmp_ui_2exp (r, 605, -11) == 0); + MPFR_ASSERTN ((q[0] > 0) && ((q[0] % 1073741824L) == 733836170L)); /* check cases where quotient is 1.5 +/- eps */ mpfr_set_prec (x, 65); @@ -238,6 +341,11 @@ main (int argc, char *argv[]) /* x/y = 1.5, quotient should be 2 (even rule), remainder should be -1 */ MPFR_ASSERTN (mpfr_cmp_si (r, -1) == 0); MPFR_ASSERTN (q[0] == 2L); + mpfr_fmodquo (r, q, x, y, MPFR_RNDN); + /* x/y = 1.5, quotient should be 1, remainder should be 1 */ + MPFR_ASSERTN (mpfr_cmp_si (r, 1) == 0); + MPFR_ASSERTN (q[0] == 1L); + mpfr_set_ui (x, 3, MPFR_RNDN); mpfr_nextabove (x); /* 3 + 2^(-63) */ mpfr_set_ui (y, 2, MPFR_RNDN); @@ -246,6 +354,14 @@ main (int argc, char *argv[]) MPFR_ASSERTN (mpfr_add_ui (r, r, 1, MPFR_RNDN) == 0); MPFR_ASSERTN (mpfr_cmp_ui_2exp (r, 1, -63) == 0); MPFR_ASSERTN (q[0] == 2L); + mpfr_set_prec (r, 64); + mpfr_fmodquo (r, q, x, y, MPFR_RNDN); + /* x/y = 1.5 + 2^(-64), quo should be 1, r should be 1 + 2^(-63) */ + MPFR_ASSERTN (mpfr_sub_ui (r, r, 1, MPFR_RNDN) == 0); + MPFR_ASSERTN (mpfr_cmp_ui_2exp (r, 1, -63) == 0); + MPFR_ASSERTN (q[0] == 1L); + + mpfr_set_prec (r, 63); mpfr_set_ui (x, 3, MPFR_RNDN); mpfr_set_ui (y, 2, MPFR_RNDN); mpfr_nextabove (y); /* 2 + 2^(-63) */ @@ -254,10 +370,16 @@ main (int argc, char *argv[]) MPFR_ASSERTN (mpfr_sub_ui (r, r, 1, MPFR_RNDN) == 0); MPFR_ASSERTN (mpfr_cmp_si_2exp (r, -1, -63) == 0); MPFR_ASSERTN (q[0] == 1L); + mpfr_fmodquo (r, q, x, y, MPFR_RNDN); + /* x/y = 1.5 - eps, quo should be 1, r should be 1 - 2^(-63) */ + MPFR_ASSERTN (mpfr_sub_ui (r, r, 1, MPFR_RNDN) == 0); + MPFR_ASSERTN (mpfr_cmp_si_2exp (r, -1, -63) == 0); + MPFR_ASSERTN (q[0] == 1L); /* bug founds by Kaveh Ghazi, 3 May 2007 */ mpfr_set_ui (x, 2, MPFR_RNDN); mpfr_set_ui (y, 3, MPFR_RNDN); + /* quotient rounded to nearest is 1, thus remainder is -1 */ mpfr_remainder (r, x, y, MPFR_RNDN); MPFR_ASSERTN (mpfr_cmp_si (r, -1) == 0); @@ -277,6 +399,9 @@ main (int argc, char *argv[]) mpfr_remquo (r, q, x, y, MPFR_RNDN); MPFR_ASSERTN (mpfr_zero_p (r) && MPFR_SIGN (r) > 0); MPFR_ASSERTN (q[0] == 0); + mpfr_fmodquo (r, q, x, y, MPFR_RNDN); + MPFR_ASSERTN (mpfr_zero_p (r) && MPFR_SIGN (r) > 0); + MPFR_ASSERTN (q[0] == 0); mpfr_clear (x); mpfr_clear (y); diff --git a/tools/cfarm.sh b/tools/cfarm.sh index fb1040679..232d099c5 100755 --- a/tools/cfarm.sh +++ b/tools/cfarm.sh @@ -22,9 +22,13 @@ fi wget http://www.loria.fr/~zimmerma/mpfr-3.2.0-dev.tar.bz2 tar jxf mpfr-3.2.0-dev.tar.bz2 cd mpfr-3.2.0-dev -./configure --with-gmp=$HOME --prefix=$HOME +if [ "`hostname`" = "dingo" ]; then + # http://websympa.loria.fr/wwsympa/arc/mpfr/2011-10/msg00048.html + ./configure --with-gmp=$HOME --disable-thread-safe +else + ./configure --with-gmp=$HOME +fi make -make install make check # results with mpfr-3.1.0-rc1.tar.bz2 |