summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile.am2
-rw-r--r--get_sj.c99
-rw-r--r--get_uj.c76
-rw-r--r--mpfr.h4
-rw-r--r--mpfr.texi10
-rw-r--r--tests/Makefile.am2
-rw-r--r--tests/tget_sj.c188
7 files changed, 378 insertions, 3 deletions
diff --git a/Makefile.am b/Makefile.am
index 86faf82d4..a158d9f26 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -7,7 +7,7 @@ include_HEADERS = mpfr.h mpf2mpfr.h
lib_LIBRARIES = libmpfr.a
-libmpfr_a_SOURCES = mpfr.h mpf2mpfr.h mpfr-gmp.h mpfr-impl.h mpfr-longlong.h mpfr-test.h log_b2.h exceptions.c save_expo.c extract.c uceil_exp2.c uceil_log2.c ufloor_log2.c add.c add1.c add_one_ulp.c add_ui.c agm.c clear.c cmp.c cmp_abs.c cmp_si.c cmp_ui.c comparisons.c div_2exp.c div_2si.c div_2ui.c div.c div_ui.c dump.c eq.c exp10.c exp2.c exp3.c exp.c frac.c get_d.c get_exp.c get_str.c init.c inp_str.c isinteger.c isinf.c isnan.c isnum.c const_log2.c log.c mul_2exp.c mul_2si.c mul_2ui.c mul.c mul_ui.c neg.c next.c out_str.c const_pi.c pow.c pow_si.c pow_ui.c print_raw.c print_rnd_mode.c random2.c random.c reldiff.c round_prec.c set.c setmax.c setmin.c set_d.c set_dfl_prec.c set_exp.c set_rnd.c set_f.c set_prc_raw.c set_prec.c set_q.c set_si.c set_str.c set_str_raw.c set_ui.c set_z.c sqrt.c sqrt_ui.c sub.c sub1.c sub_one_ulp.c sub_ui.c rint.c ui_div.c ui_sub.c urandomb.c get_z_exp.c swap.c factorial.c cosh.c sinh.c tanh.c acosh.c asinh.c atanh.c atan.c cmp2.c exp_2.c asin.c const_euler.c cos.c sin.c tan.c fma.c hypot.c log1p.c expm1.c log2.c log10.c ui_pow.c ui_pow_ui.c minmax.c dim.c copysign.c gmp_op.c init2.c acos.c sin_cos.c set_nan.c set_inf.c powerof2.c gamma.c set_ld.c get_ld.c cbrt.c volatile.c fits_s.h fits_sshort.c fits_sint.c fits_slong.c fits_u.h fits_ushort.c fits_uint.c fits_ulong.c get_si.c get_ui.c zeta.c cmp_d.c erf.c inits.c inits2.c clears.c sgn.c check.c sub1sp.c version.c mpn_exp.c mpfr-gmp.c mp_clz_tab.c sum.c add1sp.c free_cache.c si_op.c cmp_ld.c set_ui_2exp.c set_si_2exp.c set_uj.c set_sj.c get_z.c iszero.c cache.c sqr.c int_ceil_log2.c isqrt.c strtofr.c
+libmpfr_a_SOURCES = mpfr.h mpf2mpfr.h mpfr-gmp.h mpfr-impl.h mpfr-longlong.h mpfr-test.h log_b2.h exceptions.c save_expo.c extract.c uceil_exp2.c uceil_log2.c ufloor_log2.c add.c add1.c add_one_ulp.c add_ui.c agm.c clear.c cmp.c cmp_abs.c cmp_si.c cmp_ui.c comparisons.c div_2exp.c div_2si.c div_2ui.c div.c div_ui.c dump.c eq.c exp10.c exp2.c exp3.c exp.c frac.c get_d.c get_exp.c get_str.c init.c inp_str.c isinteger.c isinf.c isnan.c isnum.c const_log2.c log.c mul_2exp.c mul_2si.c mul_2ui.c mul.c mul_ui.c neg.c next.c out_str.c const_pi.c pow.c pow_si.c pow_ui.c print_raw.c print_rnd_mode.c random2.c random.c reldiff.c round_prec.c set.c setmax.c setmin.c set_d.c set_dfl_prec.c set_exp.c set_rnd.c set_f.c set_prc_raw.c set_prec.c set_q.c set_si.c set_str.c set_str_raw.c set_ui.c set_z.c sqrt.c sqrt_ui.c sub.c sub1.c sub_one_ulp.c sub_ui.c rint.c ui_div.c ui_sub.c urandomb.c get_z_exp.c swap.c factorial.c cosh.c sinh.c tanh.c acosh.c asinh.c atanh.c atan.c cmp2.c exp_2.c asin.c const_euler.c cos.c sin.c tan.c fma.c hypot.c log1p.c expm1.c log2.c log10.c ui_pow.c ui_pow_ui.c minmax.c dim.c copysign.c gmp_op.c init2.c acos.c sin_cos.c set_nan.c set_inf.c powerof2.c gamma.c set_ld.c get_ld.c cbrt.c volatile.c fits_s.h fits_sshort.c fits_sint.c fits_slong.c fits_u.h fits_ushort.c fits_uint.c fits_ulong.c get_si.c get_ui.c zeta.c cmp_d.c erf.c inits.c inits2.c clears.c sgn.c check.c sub1sp.c version.c mpn_exp.c mpfr-gmp.c mp_clz_tab.c sum.c add1sp.c free_cache.c si_op.c cmp_ld.c set_ui_2exp.c set_si_2exp.c set_uj.c set_sj.c get_sj.c get_uj.c get_z.c iszero.c cache.c sqr.c int_ceil_log2.c isqrt.c strtofr.c
libmpfr_a_LIBADD = @LIBOBJS@
diff --git a/get_sj.c b/get_sj.c
new file mode 100644
index 000000000..6ad9af9b0
--- /dev/null
+++ b/get_sj.c
@@ -0,0 +1,99 @@
+/* mpfr_get_sj -- convert a MPFR number to a huge machine signed integer
+
+Copyright 2004 Free Software Foundation, Inc.
+
+This file is part of the MPFR Library.
+
+The MPFR Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as published by
+the Free Software Foundation; either version 2.1 of the License, or (at your
+option) any later version.
+
+The MPFR Library is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+License for more details.
+
+You should have received a copy of the GNU Lesser General Public License
+along with the MPFR Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#if HAVE_CONFIG_H
+# include "config.h" /* for a build within gmp */
+#endif
+
+#ifdef HAVE_STDINT_H
+# include <stdint.h>
+#endif
+#ifdef HAVE_INTTYPES_H
+# include <inttypes.h>
+#endif
+
+#include "mpfr-impl.h"
+
+#ifdef _MPFR_H_HAVE_INTMAX_T
+
+intmax_t
+mpfr_get_sj (mpfr_srcptr f, mpfr_rnd_t rnd)
+{
+ intmax_t r;
+ mp_prec_t prec;
+ mpfr_t x;
+
+ /* determine the precision of intmax_t */
+ for (r = INTMAX_MIN, prec = 0; r != 0; r /= 2, prec++)
+ { }
+ /* Note: though INTMAX_MAX would have been sufficient for the conversion,
+ we chose INTMAX_MIN so that INTMAX_MIN - 1 is always representable in
+ precision prec; this is useful to detect overflows in GMP_RNDZ (will
+ be needed later). */
+
+ /* Now, r = 0. */
+
+ mpfr_init2 (x, prec);
+ mpfr_rint (x, f, rnd);
+ MPFR_ASSERTN (MPFR_IS_FP (x));
+
+ if (MPFR_NOTZERO (x))
+ {
+ mp_limb_t *xp;
+ int sh, n; /* An int should be sufficient in this context. */
+
+ xp = MPFR_MANT (x);
+ sh = MPFR_GET_EXP (x);
+ MPFR_ASSERTN (sh <= prec);
+ if (INTMAX_MIN + INTMAX_MAX != 0 && MPFR_UNLIKELY (sh == prec))
+ { /* 2's complement and x <= INTMAX_MIN: in the case mp_limb_t
+ has the same size as intmax_t, we cannot use the code in
+ the for loop since the operations would be performed in
+ unsigned arithmetic. */
+ MPFR_ASSERTN (MPFR_IS_NEG (x) && (mpfr_powerof2_raw (x)));
+ r = INTMAX_MIN;
+ }
+ else if (MPFR_IS_POS (x))
+ {
+ for (n = MPFR_LIMB_SIZE(x) - 1; n >= 0; n--)
+ {
+ sh -= BITS_PER_MP_LIMB;
+ r += sh >= 0 ? (intmax_t) xp[n] << sh
+ : (intmax_t) xp[n] >> (- sh);
+ }
+ }
+ else
+ {
+ for (n = MPFR_LIMB_SIZE(x) - 1; n >= 0; n--)
+ {
+ sh -= BITS_PER_MP_LIMB;
+ r -= sh >= 0 ? (intmax_t) xp[n] << sh
+ : (intmax_t) xp[n] >> (- sh);
+ }
+ }
+ }
+
+ mpfr_clear (x);
+
+ return r;
+}
+
+#endif
diff --git a/get_uj.c b/get_uj.c
new file mode 100644
index 000000000..4fdbafc31
--- /dev/null
+++ b/get_uj.c
@@ -0,0 +1,76 @@
+/* mpfr_get_uj -- convert a MPFR number to a huge machine unsigned integer
+
+Copyright 2004 Free Software Foundation, Inc.
+
+This file is part of the MPFR Library.
+
+The MPFR Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as published by
+the Free Software Foundation; either version 2.1 of the License, or (at your
+option) any later version.
+
+The MPFR Library is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+License for more details.
+
+You should have received a copy of the GNU Lesser General Public License
+along with the MPFR Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#if HAVE_CONFIG_H
+# include "config.h" /* for a build within gmp */
+#endif
+
+#ifdef HAVE_STDINT_H
+# include <stdint.h>
+#endif
+#ifdef HAVE_INTTYPES_H
+# include <inttypes.h>
+#endif
+
+#include "mpfr-impl.h"
+
+#ifdef _MPFR_H_HAVE_INTMAX_T
+
+uintmax_t
+mpfr_get_uj (mpfr_srcptr f, mpfr_rnd_t rnd)
+{
+ uintmax_t r;
+ mp_prec_t prec;
+ mpfr_t x;
+
+ /* determine the precision of uintmax_t */
+ for (r = UINTMAX_MAX, prec = 0; r != 0; r /= 2, prec++)
+ { }
+
+ /* Now, r = 0. */
+
+ mpfr_init2 (x, prec);
+ mpfr_rint (x, f, rnd);
+ MPFR_ASSERTN (MPFR_IS_FP (x));
+
+ if (MPFR_NOTZERO (x))
+ {
+ mp_limb_t *xp;
+ int sh, n; /* An int should be sufficient in this context. */
+
+ MPFR_ASSERTN (MPFR_IS_POS (x));
+ xp = MPFR_MANT (x);
+ sh = MPFR_GET_EXP (x);
+ MPFR_ASSERTN (sh <= prec);
+ for (n = MPFR_LIMB_SIZE(x) - 1; n >= 0; n--)
+ {
+ sh -= BITS_PER_MP_LIMB;
+ r += sh >= 0 ? (uintmax_t) xp[n] << sh
+ : (uintmax_t) xp[n] >> (- sh);
+ }
+ }
+
+ mpfr_clear (x);
+
+ return r;
+}
+
+#endif
diff --git a/mpfr.h b/mpfr.h
index 3154ac3d0..2c680f1a5 100644
--- a/mpfr.h
+++ b/mpfr.h
@@ -231,10 +231,14 @@ int mpfr_neg _MPFR_PROTO ((mpfr_ptr, mpfr_srcptr, mpfr_rnd_t));
#define mpfr_set_sj_2exp __gmpfr_set_sj_2exp
#define mpfr_set_uj __gmpfr_set_uj
#define mpfr_set_uj_2exp __gmpfr_set_uj_2exp
+#define mpfr_get_sj __gmpfr_mpfr_get_sj
+#define mpfr_get_uj __gmpfr_mpfr_get_uj
int mpfr_set_sj _MPFR_PROTO ((mpfr_t, intmax_t, mpfr_rnd_t));
int mpfr_set_sj_2exp _MPFR_PROTO ((mpfr_t, intmax_t, intmax_t, mpfr_rnd_t));
int mpfr_set_uj _MPFR_PROTO ((mpfr_t, uintmax_t, mpfr_rnd_t));
int mpfr_set_uj_2exp _MPFR_PROTO ((mpfr_t, uintmax_t, intmax_t, mpfr_rnd_t));
+intmax_t mpfr_get_sj _MPFR_PROTO ((mpfr_srcptr, mpfr_rnd_t));
+uintmax_t mpfr_get_uj _MPFR_PROTO ((mpfr_srcptr, mpfr_rnd_t));
#endif
mp_exp_t mpfr_get_z_exp _MPFR_PROTO ((mpz_ptr, mpfr_srcptr));
diff --git a/mpfr.texi b/mpfr.texi
index 7b3ecdd57..f15625f02 100644
--- a/mpfr.texi
+++ b/mpfr.texi
@@ -874,6 +874,14 @@ the result is undefined.
See also @code{mpfr_fits_slong_p} and @code{mpfr_fits_ulong_p}.
@end deftypefun
+@deftypefun intmax_t mpfr_get_sj (mpfr_t @var{op}, mp_rnd_t @var{rnd})
+@deftypefunx uintmax_t mpfr_get_uj (mpfr_t @var{op}, mp_rnd_t @var{op})
+Convert @var{op} to an @code{intmax_t} or @code{uintmax_t}, after rounding
+it with respect to @var{rnd}.
+If @var{op} is NaN or Inf, or too big for the return type,
+the result is undefined.
+@end deftypefun
+
@deftypefun mp_exp_t mpfr_get_z_exp (mpz_t @var{z}, mpfr_t @var{op})
Put the scaled mantissa of @var{op} (regarded as an integer, with the
precision of @var{op}) into @var{z}, and return the exponent @var{exp}
@@ -1785,7 +1793,7 @@ Jean-Luc R@'emy contributed the @code{mpfr_zeta} code.
Ludovic Meunier helped in the design of the @code{mpfr_erf} code.
Patrick P@'elissier has worked on low-precision optimizations
(new internal format), on debugging (specially the file @file{gmp_op.c})
-and on some other functions (@code{MPFR_DECL_INIT}, @code{mpfr_set_sj}, ...).
+and on some other functions (@code{MPFR_DECL_INIT}, @code{mpfr_set_sj}, etc.).
The development of the MPFR library would not have been possible without the
continuous support of LORIA, INRIA and INRIA Lorraine.
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 1570f4f76..7af2669fb 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -1,6 +1,6 @@
AUTOMAKE_OPTIONS = gnu
-check_PROGRAMS = tversion tinits tsgn tcheck tisnan texceptions tset_exp tset tabs tset_d tset_f tset_q tset_si tset_str tset_z tset_ld tset_sj tswap tcopysign tcmp tcmp2 tcmpabs tcmp_d tcmp_ld tcomparisons teq tadd tsub tmul tdiv tsub1sp tadd1sp tadd_ui tsub_ui tcmp_ui tdiv_ui tmul_ui tsqrt_ui tui_div tui_sub tgmpop tsi_op tmul_2exp tfma tsum tdim tminmax tnext tfits tget_d tget_d_2exp tget_z tget_str tout_str tinp_str toutimpl tcan_round tround_prec tsqrt tconst_log2 tconst_pi tconst_euler trandom ttrunc trint tfrac texp texp2 texpm1 tlog tlog2 tlog10 tlog1p tpow tui_pow tpow3 tcosh tsinh ttanh tacosh tasinh tatanh thyperbolic tasin tacos tcos tatan tsin ttan tsin_cos tagm thypot tfactorial tgamma terf tcbrt tzeta mpf_compat mpfr_compat reuse tsqr tstrtofr
+check_PROGRAMS = tversion tinits tsgn tcheck tisnan texceptions tset_exp tset tabs tset_d tset_f tset_q tset_si tset_str tset_z tset_ld tset_sj tswap tcopysign tcmp tcmp2 tcmpabs tcmp_d tcmp_ld tcomparisons teq tadd tsub tmul tdiv tsub1sp tadd1sp tadd_ui tsub_ui tcmp_ui tdiv_ui tmul_ui tsqrt_ui tui_div tui_sub tgmpop tsi_op tmul_2exp tfma tsum tdim tminmax tnext tfits tget_d tget_d_2exp tget_z tget_str tget_sj tout_str tinp_str toutimpl tcan_round tround_prec tsqrt tconst_log2 tconst_pi tconst_euler trandom ttrunc trint tfrac texp texp2 texpm1 tlog tlog2 tlog10 tlog1p tpow tui_pow tpow3 tcosh tsinh ttanh tacosh tasinh tatanh thyperbolic tasin tacos tcos tatan tsin ttan tsin_cos tagm thypot tfactorial tgamma terf tcbrt tzeta mpf_compat mpfr_compat reuse tsqr tstrtofr
EXTRA_DIST = tgeneric.c mpf_compat.h inp_str.data
diff --git a/tests/tget_sj.c b/tests/tget_sj.c
new file mode 100644
index 000000000..869977845
--- /dev/null
+++ b/tests/tget_sj.c
@@ -0,0 +1,188 @@
+/* Test file for mpfr_get_sj and mpfr_get_uj.
+
+Copyright 2004 Free Software Foundation, Inc.
+
+This file is part of the MPFR Library.
+
+The MPFR Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as published by
+the Free Software Foundation; either version 2.1 of the License, or (at your
+option) any later version.
+
+The MPFR Library is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+License for more details.
+
+You should have received a copy of the GNU Lesser General Public License
+along with the MPFR Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#if HAVE_CONFIG_H
+# include "config.h" /* for a build within gmp */
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#ifdef HAVE_STDINT_H
+# include <stdint.h>
+#endif
+#ifdef HAVE_INTTYPES_H
+# include <inttypes.h>
+#endif
+
+#include "mpfr-test.h"
+
+#ifndef _MPFR_H_HAVE_INTMAX_T
+
+int
+main (void)
+{
+ return 0;
+}
+
+#else
+
+static void
+check_sj (intmax_t s, mpfr_ptr x)
+{
+ mpfr_t y;
+ int i;
+
+ mpfr_init2 (y, MPFR_PREC (x));
+
+ for (i = -1; i <= 1; i++)
+ {
+ mpfr_rnd_t rnd;
+
+ mpfr_set_si_2exp (y, i, -2, GMP_RNDN);
+ mpfr_add (y, y, x, GMP_RNDN);
+ for (rnd = 0; rnd < GMP_RND_MAX; rnd++)
+ {
+ intmax_t r;
+
+ if (rnd == GMP_RNDZ && i < 0 && s >= 0)
+ continue;
+ if (rnd == GMP_RNDZ && i > 0 && s <= 0)
+ continue;
+ if (rnd == GMP_RNDD && i < 0)
+ continue;
+ if (rnd == GMP_RNDU && i > 0)
+ continue;
+ /* rint (y) == x == s */
+ r = mpfr_get_sj (y, rnd);
+ if (r != s)
+ {
+ printf ("Error in check_sj for y = ");
+ mpfr_out_str (stdout, 2, 0, y, GMP_RNDN);
+ printf (" in %s\n", mpfr_print_rnd_mode (rnd));
+ printf ("Got %jd instead of %jd.\n", r, s);
+ exit (1);
+ }
+ }
+ }
+
+ mpfr_clear (y);
+}
+
+static void
+check_uj (uintmax_t u, mpfr_ptr x)
+{
+ mpfr_t y;
+ int i;
+
+ mpfr_init2 (y, MPFR_PREC (x));
+
+ for (i = -1; i <= 1; i++)
+ {
+ mpfr_rnd_t rnd;
+
+ mpfr_set_si_2exp (y, i, -2, GMP_RNDN);
+ mpfr_add (y, y, x, GMP_RNDN);
+ for (rnd = 0; rnd < GMP_RND_MAX; rnd++)
+ {
+ uintmax_t r;
+
+ if (rnd == GMP_RNDZ && i < 0)
+ continue;
+ if (rnd == GMP_RNDD && i < 0)
+ continue;
+ if (rnd == GMP_RNDU && i > 0)
+ continue;
+ /* rint (y) == x == u */
+ r = mpfr_get_uj (y, rnd);
+ if (r != u)
+ {
+ printf ("Error in check_uj for y = ");
+ mpfr_out_str (stdout, 2, 0, y, GMP_RNDN);
+ printf (" in %s\n", mpfr_print_rnd_mode (rnd));
+ printf ("Got %ju instead of %ju.\n", r, u);
+ exit (1);
+ }
+ }
+ }
+
+ mpfr_clear (y);
+}
+
+int
+main (void)
+{
+ mp_prec_t prec;
+ mpfr_t x, y;
+ intmax_t s;
+ uintmax_t u;
+
+ tests_start_mpfr ();
+
+ for (u = UINTMAX_MAX, prec = 0; u != 0; u /= 2, prec++)
+ { }
+
+ mpfr_init2 (x, prec + 4);
+ mpfr_init2 (y, prec + 4);
+
+ mpfr_set_ui (x, 0, GMP_RNDN);
+ check_sj (0, x);
+ check_uj (0, x);
+
+ mpfr_set_si_2exp (x, 1, prec, GMP_RNDN);
+ mpfr_sub_ui (x, x, 1, GMP_RNDN); /* UINTMAX_MAX */
+
+ mpfr_div_ui (y, x, 2, GMP_RNDZ);
+ mpfr_trunc (y, y); /* INTMAX_MAX */
+ for (s = INTMAX_MAX; s != 0; s /= 17)
+ {
+ check_sj (s, y);
+ mpfr_div_ui (y, y, 17, GMP_RNDZ);
+ mpfr_trunc (y, y);
+ }
+
+ mpfr_div_ui (y, x, 2, GMP_RNDZ);
+ mpfr_trunc (y, y); /* INTMAX_MAX */
+ mpfr_neg (y, y, GMP_RNDN);
+ if (INTMAX_MIN + INTMAX_MAX != 0)
+ mpfr_sub_ui (y, y, 1, GMP_RNDN); /* INTMAX_MIN */
+ for (s = INTMAX_MIN; s != 0; s /= 17)
+ {
+ check_sj (s, y);
+ mpfr_div_ui (y, y, 17, GMP_RNDZ);
+ mpfr_trunc (y, y);
+ }
+
+ for (u = UINTMAX_MAX; u != 0; u /= 17)
+ {
+ check_uj (u, x);
+ mpfr_div_ui (x, x, 17, GMP_RNDZ);
+ mpfr_trunc (x, x);
+ }
+
+ mpfr_clear (x);
+ mpfr_clear (y);
+
+ tests_end_mpfr ();
+ return 0;
+}
+
+#endif