From 70b7b5c7fabcdb4005fc495bde8d9ce77ad8250e Mon Sep 17 00:00:00 2001 From: pelissip Date: Tue, 26 Jul 2005 16:08:02 +0000 Subject: Add first version of MPFR stack interface. Need to check if everything is ok, specially the test. git-svn-id: svn://scm.gforge.inria.fr/svn/mpfr/trunk@3685 280ebfd0-de03-0410-8827-d642c229c3f4 --- Makefile.am | 2 +- mpfr.h | 50 ++++++++++++++++ mpfr.texi | 2 +- stack_interface.c | 103 ++++++++++++++++++++++++++++++++ tests/Makefile.am | 2 +- tests/tstckintc.c | 175 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 331 insertions(+), 3 deletions(-) create mode 100644 stack_interface.c create mode 100644 tests/tstckintc.c diff --git a/Makefile.am b/Makefile.am index d9cdb0d7e..841c58384 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_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_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 round_p.c erfc.c atan2.c subnormal.c const_catalan.c root.c gen_inverse.h sec.c csc.c cot.c eint.c sech.c csch.c coth.c round_near_x.c constant.c abort_prec_max.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_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_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 round_p.c erfc.c atan2.c subnormal.c const_catalan.c root.c gen_inverse.h sec.c csc.c cot.c eint.c sech.c csch.c coth.c round_near_x.c constant.c abort_prec_max.c stack_interface.c libmpfr_la_LIBADD = @LIBOBJS@ diff --git a/mpfr.h b/mpfr.h index 78770be26..aba081c37 100644 --- a/mpfr.h +++ b/mpfr.h @@ -126,6 +126,12 @@ struct __gmpfr_cache_s { }; typedef struct __gmpfr_cache_s mpfr_cache_t[1]; +/* Stack interface */ +typedef enum { + MPFR_NAN_KIND = 0, + MPFR_INF_KIND = 1, MPFR_ZERO_KIND = 2, MPFR_REGULAR_KIND = 3, +} mpfr_kind_t; + /* GMP defines: + size_t: Standard size_t + __GMP_ATTRIBUTE_PURE Attribute for math functions. @@ -550,6 +556,15 @@ __MPFR_DECLSPEC int mpfr_subnormalize _MPFR_PROTO ((mpfr_ptr, int, __MPFR_DECLSPEC int mpfr_strtofr _MPFR_PROTO ((mpfr_ptr, __gmp_const char *, char **, int, mpfr_rnd_t)); +__MPFR_DECLSPEC size_t mpfr_stack_get_size _MPFR_PROTO ((mp_prec_t)); +__MPFR_DECLSPEC void mpfr_stack_init _MPFR_PROTO ((void *, mp_prec_t)); +__MPFR_DECLSPEC void * mpfr_stack_get_mantissa _MPFR_PROTO ((mpfr_srcptr)); +__MPFR_DECLSPEC mp_exp_t mpfr_stack_get_exp _MPFR_PROTO ((mpfr_srcptr)); +__MPFR_DECLSPEC void mpfr_stack_move _MPFR_PROTO ((mpfr_ptr, void *)); +__MPFR_DECLSPEC void mpfr_stack_init_set _MPFR_PROTO ((mpfr_ptr, int, + mp_exp_t, mp_prec_t, void *)); +__MPFR_DECLSPEC int mpfr_stack_get_kind _MPFR_PROTO ((mpfr_srcptr)); + #if defined (__cplusplus) } #endif @@ -628,6 +643,41 @@ __MPFR_DECLSPEC int mpfr_strtofr _MPFR_PROTO ((mpfr_ptr, __gmp_const char *, #endif #endif +/* Macro version of mpfr_stack interface for fast access */ +#define mpfr_stack_get_size(p) ((size_t) \ + (((p)+GMP_NUMB_BITS-1)/GMP_NUMB_BITS*sizeof (mp_limb_t))) +#define mpfr_stack_init(m,p) do {} while (0) +#define mpfr_stack_get_mantissa(x) ((void*)((x)->_mpfr_d)) +#define mpfr_stack_get_exp(x) ((x)->_mpfr_exp) +#define mpfr_stack_move(x,m) do { ((x)->_mpfr_d = (mp_limb_t*)(m)); } while (0) +#define mpfr_stack_init_set(x,k,e,p,m) do { \ + mpfr_ptr _x = (x); \ + mp_exp_t _e; \ + mpfr_kind_t _t; \ + int _s, _k; \ + _k = (k); \ + if (_k >= 0) { \ + _t = (mpfr_kind_t) _k; \ + _s = 1; \ + } else { \ + _t = (mpfr_kind_t) -k; \ + _s = -1; \ + } \ + _e = _t == MPFR_REGULAR_KIND ? (e) : \ + _t == MPFR_NAN_KIND ? __MPFR_EXP_NAN : \ + _t == MPFR_INF_KIND ? __MPFR_EXP_INF : __MPFR_EXP_ZERO; \ + _x->_mpfr_prec = (p); \ + _x->_mpfr_sign = _s; \ + _x->_mpfr_exp = _e; \ + _x->_mpfr_d = (mp_limb_t*) (m); \ + } while (0) +#define mpfr_stack_get_kind(x) \ + ( (x)->_mpfr_exp > __MPFR_EXP_INF ? (int)MPFR_REGULAR_KIND*MPFR_SIGN (x) \ + : (x)->_mpfr_exp == __MPFR_EXP_INF ? (int)MPFR_INF_KIND*MPFR_SIGN (x) \ + : (x)->_mpfr_exp == __MPFR_EXP_NAN ? (int)MPFR_NAN_KIND \ + : (int) MPFR_ZERO_KIND * MPFR_SIGN (x) ) + + #endif /* MPFR_NO_MACRO */ /* Theses are defined to be macros */ diff --git a/mpfr.texi b/mpfr.texi index e962fd7c2..0c42dbfca 100644 --- a/mpfr.texi +++ b/mpfr.texi @@ -1615,7 +1615,7 @@ Put +0 in @var{rop} when size if zero. @deftypefun mp_exp_t mpfr_get_exp (mpfr_t @var{x}) Get the exponent of @var{x}, assuming that @var{x} is a non-zero ordinary -number. The return value for Nan, Infinity or Zero is undefined. +number. The behavior for Nan, Infinity or Zero is undefined. @end deftypefun @deftypefun int mpfr_set_exp (mpfr_t @var{x}, mp_exp_t @var{e}) diff --git a/stack_interface.c b/stack_interface.c new file mode 100644 index 000000000..785fcd867 --- /dev/null +++ b/stack_interface.c @@ -0,0 +1,103 @@ +/* mpfr_stack -- initialize a floating-point number with given allocation area + +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., 51 Franklin Place, Fifth Floor, Boston, +MA 02110-1301, USA. */ + +#include "mpfr-impl.h" + +#undef mpfr_stack_get_size +size_t +mpfr_stack_get_size (mp_prec_t prec) +{ + return (prec + BITS_PER_MP_LIMB -1) / BITS_PER_MP_LIMB * BYTES_PER_MP_LIMB; +} + +#undef mpfr_stack_init +void +mpfr_stack_init (void *mantissa, mp_prec_t prec) +{ + return ; +} + +#undef mpfr_stack_get_mantissa +void * +mpfr_stack_get_mantissa (mpfr_srcptr x) +{ + return (void*) MPFR_MANT (x); +} + +#undef mpfr_stack_get_exp +mp_exp_t +mpfr_stack_get_exp (mpfr_srcptr x) +{ + return MPFR_EXP (x); +} + +#undef mpfr_stack_move +void +mpfr_stack_move (mpfr_ptr x, void *new_position) +{ + MPFR_MANT (x) = (mp_limb_t *) new_position; +} + +#undef mpfr_stack_init_set +void +mpfr_stack_init_set (mpfr_ptr x, int kind, mp_exp_t exp, + mp_prec_t prec, void *mantissa) +{ + mpfr_kind_t t; + int s; + mp_exp_t e; + + if (kind >= 0) + { + t = (mpfr_kind_t) kind; + s = MPFR_SIGN_POS; + } + else + { + t = (mpfr_kind_t) -kind; + s = MPFR_SIGN_NEG; + } + MPFR_ASSERTD (t <= MPFR_REGULAR_KIND); + e = MPFR_LIKELY (t == MPFR_REGULAR_KIND) ? exp : + MPFR_UNLIKELY (t == MPFR_NAN_KIND) ? MPFR_EXP_NAN : + MPFR_UNLIKELY (t == MPFR_INF_KIND) ? MPFR_EXP_INF : MPFR_EXP_ZERO; + + MPFR_PREC (x) = prec; + MPFR_SET_SIGN (x, s); + MPFR_EXP (x) = e; + MPFR_MANT (x) = (mp_limb_t*) mantissa; + return; +} + +#undef mpfr_stack_get_kind +int +mpfr_stack_get_kind (mpfr_srcptr x) +{ + if (MPFR_LIKELY (!MPFR_IS_SINGULAR (x))) + return (int) MPFR_REGULAR_KIND * MPFR_INT_SIGN (x); + if (MPFR_IS_INF (x)) + return (int) MPFR_INF_KIND * MPFR_INT_SIGN (x); + if (MPFR_IS_NAN (x)) + return (int) MPFR_NAN_KIND; + MPFR_ASSERTD (MPFR_IS_ZERO (x)); + return (int) MPFR_ZERO_KIND * MPFR_INT_SIGN (x); +} + diff --git a/tests/Makefile.am b/tests/Makefile.am index 6d481bd46..53fd25ce6 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 tget_f tconst_catalan troot tsec tcsc tcot teint tcoth tcsch tsech +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 tconst_catalan troot tsec tcsc tcot teint tcoth tcsch tsech tstckintc EXTRA_DIST = tgeneric.c tgeneric_ui.c mpf_compat.h inp_str.data diff --git a/tests/tstckintc.c b/tests/tstckintc.c new file mode 100644 index 000000000..bfbb3265b --- /dev/null +++ b/tests/tstckintc.c @@ -0,0 +1,175 @@ +/* Test file for mpfr_stack_* + +Copyright 2005 Free Software Foundation. + +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., 51 Franklin Place, Fifth Floor, Boston, +MA 02110-1301, USA. */ + +#include +#include + +#include "mpfr-test.h" + +#define BUFFER_SIZE 1000 +#define PREC_TESTED 200 + +char Buffer[BUFFER_SIZE]; +char *stack = Buffer; +mp_prec_t p = PREC_TESTED; + +#define ALIGNED(s) ( ((s)+sizeof (long)-1) / sizeof (long) * sizeof (long)) + +static void * +new (size_t s) +{ + void *p = (void*) stack; + stack += ALIGNED (s); + if (MPFR_UNLIKELY (stack > &Buffer[BUFFER_SIZE])) + { + printf ("Stack overflow.\n"); + exit (1); + } + return p; +} + + /* Alloc a new mpfr_t on the main stack */ +static mpfr_ptr +new_mpfr (mp_prec_t p) +{ + mpfr_ptr x = (mpfr_ptr) new (sizeof (mpfr_t)); + void *mantissa = new (mpfr_stack_get_size (p)); + mpfr_stack_init (mantissa, p); + mpfr_stack_init_set (x, 0, 0, p, mantissa); + return x; +} + + /* Garbage the stack by keeping only x */ +static mpfr_ptr +return_mpfr (mpfr_ptr x, void *old_stack) +{ + void *mantissa = mpfr_stack_get_mantissa (x); + size_t size_mantissa = mpfr_stack_get_size (mpfr_get_prec (x)); + mpfr_ptr newx; + + memmove (old_stack, x, sizeof (mpfr_t)); + memmove (old_stack + ALIGNED (sizeof (mpfr_t)), mantissa, size_mantissa); + newx = (mpfr_ptr) old_stack; + mpfr_stack_move (newx, old_stack + ALIGNED (sizeof (mpfr_t))); + stack = old_stack + ALIGNED (sizeof (mpfr_t)) + ALIGNED (size_mantissa); + return newx; +} + +static void +test1 (void) +{ + mpfr_ptr x, y; + void *org; + + org = stack; + x = new_mpfr (p); + y = new_mpfr (p); + mpfr_set_ui (x, 42, GMP_RNDN); + mpfr_set_ui (y, 17, GMP_RNDN); + mpfr_add (y, x, y, GMP_RNDN); + y = return_mpfr (y, org); + if (y != x || mpfr_cmp_ui (y, 59) != 0) + { + printf ("Compact (1) failed!\n"); + exit (1); + } + stack = org; +} + +/* We build the MPFR variable each time it is needed */ +/* a[0] is the kind, a[1] is the exponent, &a[2] is the mantissa */ +static long * +dummy_new (void) +{ + long *r; + + r = new (ALIGNED (2*sizeof (long)) + ALIGNED (mpfr_stack_get_size (p))); + MPFR_ASSERTN (r != NULL); + (mpfr_stack_init) (&r[2], p); + r[0] = (int) MPFR_NAN_KIND; + r[1] = 0; + return r; +} + +static long * +dummy_set_si (long si) +{ + mpfr_t x; + long * r = dummy_new (); + (mpfr_stack_init_set) (x, 0, 0, p, &r[2]); + mpfr_set_si (x, si, GMP_RNDN); + r[0] = mpfr_stack_get_kind (x); + r[1] = mpfr_stack_get_exp (x); + return r; +} + +static long * +dummy_add (long *a, long *b) +{ + mpfr_t x, y, z; + long *r = dummy_new (); + mpfr_stack_init_set (x, 0, 0, p, &r[2]); + (mpfr_stack_init_set) (y, a[0], a[1], p, &a[2]); + mpfr_stack_init_set (z, b[0], b[1], p, &b[2]); + mpfr_add (x, y, z, GMP_RNDN); + r[0] = (mpfr_stack_get_kind) (x); + r[1] = (mpfr_stack_get_exp) (x); + return r; +} + +static long * +dummy_compact (long *r, void *org_stack) +{ + memmove (org_stack, r, + ALIGNED (2*sizeof (long)) + ALIGNED ((mpfr_stack_get_size) (p))); + return org_stack; +} + +static void +test2 (void) +{ + mpfr_t x; + void *org = stack; + long *a, *b, *c; + + a = dummy_set_si (42); + b = dummy_set_si (17); + c = dummy_add (a, b); + c = dummy_compact (c, org); + (mpfr_stack_init_set) (x, c[0], c[1], p, &c[2]); + if (c != a || mpfr_cmp_ui (x, 59) != 0) + { + printf ("Compact (2) failed! c=%p a=%p\n", c, a); + mpfr_dump (x); + exit (1); + } + stack = org; +} + +int +main (void) +{ + tests_start_mpfr (); + test1 (); + test2 (); + tests_end_mpfr (); + return 0; +} -- cgit v1.2.1