summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile.am2
-rw-r--r--get_f.c96
-rw-r--r--mpfr.h2
-rw-r--r--tests/Makefile.am2
-rw-r--r--tests/tget_f.c134
5 files changed, 234 insertions, 2 deletions
diff --git a/Makefile.am b/Makefile.am
index e6e3e5671..aa2183348 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -7,7 +7,7 @@ include_HEADERS = mpfr.h mpf2mpfr.h
lib_LTLIBRARIES = libmpfr.la
-libmpfr_la_SOURCES = mpfr.h mpf2mpfr.h mpfr-gmp.h mpfr-impl.h mpfr-longlong.h mpfr-test.h log_b2.h exceptions.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 fits_uintmax.c fits_intmax.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 pow_z.c logging.c mulders.c
+libmpfr_la_SOURCES = mpfr.h mpf2mpfr.h mpfr-gmp.h mpfr-impl.h mpfr-longlong.h mpfr-test.h log_b2.h exceptions.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 fits_uintmax.c fits_intmax.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 pow_z.c logging.c mulders.c get_f.c
libmpfr_la_LIBADD = @LIBOBJS@
diff --git a/get_f.c b/get_f.c
new file mode 100644
index 000000000..0ce81d311
--- /dev/null
+++ b/get_f.c
@@ -0,0 +1,96 @@
+/* mpfr_get_f -- convert a MPFR number to a GNU MPF number
+
+Copyright 2005 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. */
+
+#include <stdio.h>
+#include "mpfr-impl.h"
+
+/* return value is 0 iff no error occurred in the conversion
+ (1 for NaN, +Inf, -Inf that have no equivalent in mpf)
+*/
+int
+mpfr_get_f (mpf_ptr x, mpfr_srcptr y, mp_rnd_t rnd_mode)
+{
+ unsigned long sx, sy, precx, precy, sh;
+ mp_exp_t ey;
+
+ if (MPFR_UNLIKELY(MPFR_IS_SINGULAR(y)))
+ {
+ if (MPFR_IS_ZERO(y))
+ {
+ mpf_set_ui (x, 0);
+ return 0;
+ }
+ else /* NaN or Inf */
+ return 1;
+ }
+
+ sx = PREC(x); /* number of limbs of the mantissa of x */
+
+ precy = MPFR_PREC(y);
+ precx = sx * BITS_PER_MP_LIMB;
+ sy = 1 + (MPFR_PREC(y) - 1) / BITS_PER_MP_LIMB;
+
+ /* since mpf numbers are represented in base 2^BITS_PER_MP_LIMB,
+ we loose -EXP(y) % BITS_PER_MP_LIMB bits in the most significant limb */
+ ey = MPFR_GET_EXP(y) % BITS_PER_MP_LIMB;
+ if (ey <= 0)
+ sh = (unsigned long) (-ey);
+ else /* 0 < ey < BITS_PER_MP_LIMB */
+ sh = BITS_PER_MP_LIMB - (unsigned long) ey;
+ if (precy + sh <= precx) /* we can copy directly */
+ {
+ /* necessarily sy <= sx */
+ if (sh)
+ mpn_rshift (PTR(x) + sx - sy, MPFR_MANT(y), sy, sh);
+ else
+ MPN_COPY (PTR(x) + sx - sy, MPFR_MANT(y), sy);
+ if (sx > sy)
+ MPN_ZERO (PTR(x), sx - sy);
+ EXP(x) = (MPFR_GET_EXP(y) + sh) / BITS_PER_MP_LIMB;
+ }
+ else /* we have to round to precx - sh bits */
+ {
+ mpfr_t z;
+ unsigned long sz;
+
+ mpfr_init2 (z, precx - sh);
+ sz = 1 + (MPFR_PREC(z) - 1) / BITS_PER_MP_LIMB;
+ mpfr_set (z, y, rnd_mode);
+ /* warning, sh may change due to rounding, but then z is a power of two,
+ thus we can safely ignore its last bit which is 0 */
+ ey = MPFR_GET_EXP(z) % BITS_PER_MP_LIMB;
+ sh = (ey <= 0) ? (unsigned long) (-ey)
+ : BITS_PER_MP_LIMB - (unsigned long) ey;
+ if (sh)
+ mpn_rshift (PTR(x) + sx - sz, MPFR_MANT(z), sz, sh);
+ else
+ MPN_COPY (PTR(x) + sx - sz, MPFR_MANT(z), sz);
+ if (sx > sz)
+ MPN_ZERO (PTR(x), sx - sz);
+ EXP(x) = (MPFR_GET_EXP(z) + sh) / BITS_PER_MP_LIMB;
+ mpfr_clear (z);
+ }
+
+ /* set size and sign */
+ SIZ(x) = (MPFR_FROM_SIGN_TO_INT(MPFR_SIGN(y)) < 0) ? -sx : sx;
+
+ return 0;
+}
diff --git a/mpfr.h b/mpfr.h
index c6cdb62a9..3aa2dd5fc 100644
--- a/mpfr.h
+++ b/mpfr.h
@@ -236,6 +236,8 @@ __MPFR_DECLSPEC void mpfr_set_nan _MPFR_PROTO ((mpfr_ptr));
__MPFR_DECLSPEC void mpfr_set_inf _MPFR_PROTO ((mpfr_ptr, int));
__MPFR_DECLSPEC int
mpfr_set_f _MPFR_PROTO ((mpfr_ptr, mpf_srcptr, mpfr_rnd_t));
+__MPFR_DECLSPEC int
+ mpfr_get_f _MPFR_PROTO ((mpf_ptr, mpfr_srcptr, mpfr_rnd_t));
__MPFR_DECLSPEC int mpfr_set_si _MPFR_PROTO ((mpfr_ptr, long, mpfr_rnd_t));
__MPFR_DECLSPEC int
mpfr_set_ui _MPFR_PROTO ((mpfr_ptr, unsigned long, mpfr_rnd_t));
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 0d110582b..6082442ac 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -1,6 +1,6 @@
AUTOMAKE_OPTIONS = gnu no-dependencies $(top_builddir)/ansi2knr
-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 tpow_z
+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 tpow_z tget_f
EXTRA_DIST = tgeneric.c mpf_compat.h inp_str.data
diff --git a/tests/tget_f.c b/tests/tget_f.c
new file mode 100644
index 000000000..db38149b1
--- /dev/null
+++ b/tests/tget_f.c
@@ -0,0 +1,134 @@
+/* Test file for mpfr_get_f.
+
+Copyright 2005 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. */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+
+#include "mpfr-test.h"
+
+int
+main (void)
+{
+ mpf_t x;
+ mpfr_t y;
+ unsigned long i;
+ long j;
+
+ MPFR_TEST_USE_RANDS ();
+ tests_start_mpfr ();
+
+ mpfr_init (y);
+ mpf_init (x);
+
+ mpfr_set_nan (y);
+ if (mpfr_get_f (x, y, GMP_RNDN) == 0)
+ {
+ printf ("Error: mpfr_get_f(NaN) should fail\n");
+ exit (1);
+ }
+
+ mpfr_set_inf (y, 1);
+ if (mpfr_get_f (x, y, GMP_RNDN) == 0)
+ {
+ printf ("Error: mpfr_get_f(+Inf) should fail\n");
+ exit (1);
+ }
+
+ mpfr_set_inf (y, -1);
+ if (mpfr_get_f (x, y, GMP_RNDN) == 0)
+ {
+ printf ("Error: mpfr_get_f(-Inf) should fail\n");
+ exit (1);
+ }
+
+ mpfr_set_ui (y, 0, GMP_RNDN);
+ if (mpfr_get_f (x, y, GMP_RNDN) || mpf_cmp_ui (x, 0))
+ {
+ printf ("Error: mpfr_get_f(+0) fails\n");
+ exit (1);
+ }
+
+ mpfr_set_ui (y, 0, GMP_RNDN);
+ mpfr_neg (y, y, GMP_RNDN);
+ if (mpfr_get_f (x, y, GMP_RNDN) || mpf_cmp_ui (x, 0))
+ {
+ printf ("Error: mpfr_get_f(-0) fails\n");
+ exit (1);
+ }
+
+ i = 1;
+ while (i)
+ {
+ mpfr_set_ui (y, i, GMP_RNDN);
+ if (mpfr_get_f (x, y, GMP_RNDN) || mpf_cmp_ui (x, i))
+ {
+ printf ("Error: mpfr_get_f(%lu) fails\n", i);
+ exit (1);
+ }
+ i *= 2;
+ }
+
+ j = -1;
+ while (j)
+ {
+ mpfr_set_si (y, j, GMP_RNDN);
+ if (mpfr_get_f (x, y, GMP_RNDN) || mpf_cmp_si (x, j))
+ {
+ printf ("Error: mpfr_get_f(%ld) fails\n", j);
+ exit (1);
+ }
+ j *= 2;
+ }
+
+ /* same tests, but with a larger precision for y, which requires to
+ round it */
+ mpfr_set_prec (y, 100);
+ i = 1;
+ while (i)
+ {
+ mpfr_set_ui (y, i, GMP_RNDN);
+ if (mpfr_get_f (x, y, GMP_RNDN) || mpf_cmp_ui (x, i))
+ {
+ printf ("Error: mpfr_get_f(%lu) fails\n", i);
+ exit (1);
+ }
+ i *= 2;
+ }
+
+ j = -1;
+ while (j)
+ {
+ mpfr_set_si (y, j, GMP_RNDN);
+ if (mpfr_get_f (x, y, GMP_RNDN) || mpf_cmp_si (x, j))
+ {
+ printf ("Error: mpfr_get_f(%ld) fails\n", j);
+ exit (1);
+ }
+ j *= 2;
+ }
+
+ mpfr_clear (y);
+ mpf_clear (x);
+
+ tests_end_mpfr ();
+ return 0;
+}