diff options
-rw-r--r-- | Makefile.am | 2 | ||||
-rw-r--r-- | get_f.c | 96 | ||||
-rw-r--r-- | mpfr.h | 2 | ||||
-rw-r--r-- | tests/Makefile.am | 2 | ||||
-rw-r--r-- | tests/tget_f.c | 134 |
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; +} @@ -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; +} |