diff options
author | thevenyp <thevenyp@211d60ee-9f03-0410-a15a-8952a2c7a4e4> | 2013-12-03 13:59:38 +0000 |
---|---|---|
committer | thevenyp <thevenyp@211d60ee-9f03-0410-a15a-8952a2c7a4e4> | 2013-12-03 13:59:38 +0000 |
commit | 9160794b0312583fb1755980362fff1df8fd205b (patch) | |
tree | a6475d050671f6853df8cf418ee6276e3a5c30a8 | |
parent | 25fe1f3e42fd9bf03953bbd26ae6e7af9275f873 (diff) | |
download | mpc-9160794b0312583fb1755980362fff1df8fd205b.tar.gz |
[tests/] Move functions for double rounding check in a separate file.
git-svn-id: svn://scm.gforge.inria.fr/svn/mpc/branches/benchs_tests@1360 211d60ee-9f03-0410-a15a-8952a2c7a4e4
-rw-r--r-- | tests/Makefile.am | 7 | ||||
-rw-r--r-- | tests/double_rounding.c | 151 | ||||
-rw-r--r-- | tests/templates.h | 14 | ||||
-rw-r--r-- | tests/tgeneric.tpl | 134 |
4 files changed, 163 insertions, 143 deletions
diff --git a/tests/Makefile.am b/tests/Makefile.am index 7d830d2..6bb214b 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -46,9 +46,10 @@ check_PROGRAMS = tabs tacos tacosh tadd tadd_fr tadd_si tadd_ui targ \ check_LTLIBRARIES=libmpc-tests.la libmpc_tests_la_SOURCES=mpc-tests.h random.c tgeneric.c read_data.c \ comparisons.c templates.h check_data.c clear_parameters.c \ - close_datafile.c copy_parameter.c init_parameters.c open_datafile.c \ - print_parameter.c read_description.c read_line.c rounding.c \ - setprec_parameters.c tpl_gmp.c tpl_mpc.c tpl_mpfr.c tpl_native.c + close_datafile.c copy_parameter.c double_rounding.c init_parameters.c \ + open_datafile.c print_parameter.c read_description.c read_line.c \ + rounding.c setprec_parameters.c tpl_gmp.c tpl_mpc.c tpl_mpfr.c \ + tpl_native.c DESCRIPTIONS = abs.dsc acos.dsc acosh.dsc asin.dsc asinh.dsc atan.dsc \ atanh.dsc add.dsc add_fr.dsc add_si.dsc add_ui.dsc arg.dsc conj.dsc \ diff --git a/tests/double_rounding.c b/tests/double_rounding.c new file mode 100644 index 0000000..3ea2188 --- /dev/null +++ b/tests/double_rounding.c @@ -0,0 +1,151 @@ +/* double_rounding.c -- Functions for checking double rounding. + +Copyright (C) 2013 INRIA + +This file is part of GNU MPC. + +GNU MPC 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 3 of the License, or (at your +option) any later version. + +GNU MPC 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 this program. If not, see http://www.gnu.org/licenses/ . +*/ + +#include "templates.h" + +/* return 1 if double rounding occurs; + return 0 otherwise */ +static int +double_rounding_mpfr (mpfr_ptr lowprec, + mpfr_ptr hiprec, int hiprec_inex, mpfr_rnd_t hiprec_rnd) +{ + mpfr_exp_t hiprec_err; + mpfr_rnd_t lowprec_rnd = hiprec_rnd; + mpfr_prec_t lowprec_prec = mpfr_get_prec (lowprec); + + /* hiprec error is bounded by one ulp */ + hiprec_err = mpfr_get_prec (hiprec) - 1; + + if (hiprec_rnd == MPFR_RNDN) + /* when rounding to nearest, use the trick for determining the + correct ternary value which is described in MPFR + documentation */ + { + hiprec_err++; /* error is bounded by one half-ulp */ + lowprec_rnd = MPFR_RNDZ; + lowprec_prec++; + } + + return (hiprec_inex == 0 + || mpfr_can_round (hiprec, hiprec_err, hiprec_rnd, + lowprec_rnd, lowprec_prec)); +} + +/* return 1 if double rounding occurs; + return 0 otherwise */ +static int +double_rounding_mpc (mpc_ptr lowprec, + mpc_ptr hiprec, int hiprec_inex, mpc_rnd_t hiprec_rnd) +{ + mpfr_ptr lowprec_re = mpc_realref (lowprec); + mpfr_ptr lowprec_im = mpc_imagref (lowprec); + mpfr_ptr hiprec_re = mpc_realref (hiprec); + mpfr_ptr hiprec_im = mpc_imagref (hiprec); + int inex_re = MPC_INEX_RE (hiprec_inex); + int inex_im = MPC_INEX_IM (hiprec_inex); + mpfr_rnd_t rnd_re = MPC_RND_RE (hiprec_rnd); + mpfr_rnd_t rnd_im = MPC_RND_IM (hiprec_rnd); + + return (double_rounding_mpfr (lowprec_re, hiprec_re, inex_re, rnd_re) + && double_rounding_mpfr (lowprec_im, hiprec_im, inex_im, rnd_im)); +} + +/* check whether double rounding occurs; if not, round extra precise output + value and set reference parameter */ +int +double_rounding (mpc_fun_param_t *params) +{ + int out; + const int offset = params->nbout + params->nbin; + const int rnd_index = params->nbout + params->nbin - 1; + + for (out = 0; out < params->nbout; out++) { + if (params->T[out] == MPC) + { + MPC_ASSERT (params->T[0] == MPC_INEX); + MPC_ASSERT (params->T[offset] == MPC_INEX); + MPC_ASSERT (params->T[out + offset] == MPC); + MPC_ASSERT (params->T[rnd_index] == MPC_RND); + + if (double_rounding_mpc (params->P[out + offset].mpc_data.mpc, + params->P[out].mpc, + params->P[0].mpc_inex, + params->P[rnd_index].mpc_rnd)) + /* the hight-precision value and the exact value round to the same + low-precision value */ + { + int inex; + inex = mpc_set (params->P[out + offset].mpc_data.mpc, + params->P[out].mpc, + params->P[rnd_index].mpc_rnd); + params->P[out + offset].mpc_data.known_sign_real = -1; + params->P[out + offset].mpc_data.known_sign_imag = -1; + + /* no double rounding means that the ternary value may comes from + the high-precision calculation or from the rounding */ + if (MPC_INEX_RE (inex) == 0) + params->P[offset].mpc_inex_data.real = + MPC_INEX_RE (params->P[0].mpc_inex); + else + params->P[offset].mpc_inex_data.real = MPC_INEX_RE (inex); + if (MPC_INEX_IM (inex) == 0) + params->P[offset].mpc_inex_data.imag = + MPC_INEX_IM (params->P[0].mpc_inex); + else + params->P[offset].mpc_inex_data.imag = MPC_INEX_IM (inex); + } + else + /* double rounding occurs */ + return 1; + } + else if (params->T[out] == MPFR) + { + MPC_ASSERT (params->T[0] == MPFR_INEX); + MPC_ASSERT (params->T[offset] == MPFR_INEX); + MPC_ASSERT (params->T[out + offset] == MPFR); + MPC_ASSERT (params->T[rnd_index] == MPFR_RND); + + if (double_rounding_mpfr (params->P[out + offset].mpfr_data.mpfr, + params->P[out].mpfr, + params->P[0].mpfr_inex, + params->P[rnd_index].mpfr_rnd)) + /* the hight-precision value and the exact value round to the same + low-precision value */ + { + int inex; + inex = mpfr_set (params->P[out + offset].mpfr_data.mpfr, + params->P[out].mpfr, + params->P[rnd_index].mpfr_rnd); + params->P[out + offset].mpfr_data.known_sign = -1; + + /* no double rounding means that the ternary value may comes from + the high-precision calculation or from the rounding */ + if (inex == 0) + params->P[offset].mpfr_inex = params->P[0].mpfr_inex; + else + params->P[offset].mpfr_inex = inex; + } + else + /* double rounding occurs */ + return 1; + } + } + return 0; +} diff --git a/tests/templates.h b/tests/templates.h index 6618cfe..404ca0f 100644 --- a/tests/templates.h +++ b/tests/templates.h @@ -210,14 +210,16 @@ void tpl_copy_mpz (mpz_ptr dest, mpz_srcptr src); void tpl_copy_mpfr (mpfr_ptr dest, mpfr_srcptr src); void tpl_copy_mpc (mpc_ptr dest, mpc_srcptr src); +int double_rounding (mpc_fun_param_t *params); + /* iterating over rounding modes */ -void first_rnd_mode (mpc_fun_param_t *params); -int is_valid_rnd_mode (mpc_fun_param_t *params); -void next_rnd_mode (mpc_fun_param_t *params); +void first_rnd_mode (mpc_fun_param_t *params); +int is_valid_rnd_mode (mpc_fun_param_t *params); +void next_rnd_mode (mpc_fun_param_t *params); /* parameter precision */ -void set_output_precision (mpc_fun_param_t *params, mpfr_prec_t prec); -void set_input_precision (mpc_fun_param_t *params, mpfr_prec_t prec); -void set_reference_precision (mpc_fun_param_t *params, mpfr_prec_t prec); +void set_output_precision (mpc_fun_param_t *params, mpfr_prec_t prec); +void set_input_precision (mpc_fun_param_t *params, mpfr_prec_t prec); +void set_reference_precision (mpc_fun_param_t *params, mpfr_prec_t prec); #endif /*__TEMPLATES_H*/ diff --git a/tests/tgeneric.tpl b/tests/tgeneric.tpl index 008688f..1ce8079 100644 --- a/tests/tgeneric.tpl +++ b/tests/tgeneric.tpl @@ -23,7 +23,6 @@ along with this program. If not, see http://www.gnu.org/licenses/ . #endif /* helper functions, defined after tgeneric */ -static int double_rounding (mpc_fun_param_t *params); static int count_special_cases (mpc_fun_param_t *params); static void random_params (mpc_fun_param_t *params, mpfr_exp_t exp_min, mpfr_exp_t exp_max, @@ -295,136 +294,3 @@ random_params (mpc_fun_param_t *params, } } } - - -/* return 1 if double rounding occurs; - return 0 otherwise */ -static int -double_rounding_mpfr (mpfr_ptr lowprec, - mpfr_ptr hiprec, int hiprec_inex, mpfr_rnd_t hiprec_rnd) -{ - mpfr_exp_t hiprec_err; - mpfr_rnd_t lowprec_rnd = hiprec_rnd; - mpfr_prec_t lowprec_prec = mpfr_get_prec (lowprec); - - /* hiprec error is bounded by one ulp */ - hiprec_err = mpfr_get_prec (hiprec) - 1; - - if (hiprec_rnd == MPFR_RNDN) - /* when rounding to nearest, use the trick for determining the - correct ternary value which is described in MPFR - documentation */ - { - hiprec_err++; /* error is bounded by one half-ulp */ - lowprec_rnd = MPFR_RNDZ; - lowprec_prec++; - } - - return (hiprec_inex == 0 - || mpfr_can_round (hiprec, hiprec_err, hiprec_rnd, - lowprec_rnd, lowprec_prec)); -} - -/* return 1 if double rounding occurs; - return 0 otherwise */ -static int -double_rounding_mpc (mpc_ptr lowprec, - mpc_ptr hiprec, int hiprec_inex, mpc_rnd_t hiprec_rnd) -{ - mpfr_ptr lowprec_re = mpc_realref (lowprec); - mpfr_ptr lowprec_im = mpc_imagref (lowprec); - mpfr_ptr hiprec_re = mpc_realref (hiprec); - mpfr_ptr hiprec_im = mpc_imagref (hiprec); - int inex_re = MPC_INEX_RE (hiprec_inex); - int inex_im = MPC_INEX_IM (hiprec_inex); - mpfr_rnd_t rnd_re = MPC_RND_RE (hiprec_rnd); - mpfr_rnd_t rnd_im = MPC_RND_IM (hiprec_rnd); - - return (double_rounding_mpfr (lowprec_re, hiprec_re, inex_re, rnd_re) - && double_rounding_mpfr (lowprec_im, hiprec_im, inex_im, rnd_im)); -} - -/* check whether double rounding occurs; if not, round extra precise output - value and set reference parameter */ -static int -double_rounding (mpc_fun_param_t *params) -{ - int out; - const int offset = params->nbout + params->nbin; - const int rnd_index = params->nbout + params->nbin - 1; - - for (out = 0; out < params->nbout; out++) { - if (params->T[out] == MPC) - { - MPC_ASSERT (params->T[0] == MPC_INEX); - MPC_ASSERT (params->T[offset] == MPC_INEX); - MPC_ASSERT (params->T[out + offset] == MPC); - MPC_ASSERT (params->T[rnd_index] == MPC_RND); - - if (double_rounding_mpc (params->P[out + offset].mpc_data.mpc, - params->P[out].mpc, - params->P[0].mpc_inex, - params->P[rnd_index].mpc_rnd)) - /* the hight-precision value and the exact value round to the same - low-precision value */ - { - int inex; - inex = mpc_set (params->P[out + offset].mpc_data.mpc, - params->P[out].mpc, - params->P[rnd_index].mpc_rnd); - params->P[out + offset].mpc_data.known_sign_real = -1; - params->P[out + offset].mpc_data.known_sign_imag = -1; - - /* no double rounding means that the ternary value may comes from - the high-precision calculation or from the rounding */ - if (MPC_INEX_RE (inex) == 0) - params->P[offset].mpc_inex_data.real = - MPC_INEX_RE (params->P[0].mpc_inex); - else - params->P[offset].mpc_inex_data.real = MPC_INEX_RE (inex); - if (MPC_INEX_IM (inex) == 0) - params->P[offset].mpc_inex_data.imag = - MPC_INEX_IM (params->P[0].mpc_inex); - else - params->P[offset].mpc_inex_data.imag = MPC_INEX_IM (inex); - } - else - /* double rounding occurs */ - return 1; - } - else if (params->T[out] == MPFR) - { - MPC_ASSERT (params->T[0] == MPFR_INEX); - MPC_ASSERT (params->T[offset] == MPFR_INEX); - MPC_ASSERT (params->T[out + offset] == MPFR); - MPC_ASSERT (params->T[rnd_index] == MPFR_RND); - - if (double_rounding_mpfr (params->P[out + offset].mpfr_data.mpfr, - params->P[out].mpfr, - params->P[0].mpfr_inex, - params->P[rnd_index].mpfr_rnd)) - /* the hight-precision value and the exact value round to the same - low-precision value */ - { - int inex; - inex = mpfr_set (params->P[out + offset].mpfr_data.mpfr, - params->P[out].mpfr, - params->P[rnd_index].mpfr_rnd); - params->P[out + offset].mpfr_data.known_sign = -1; - - /* no double rounding means that the ternary value may comes from - the high-precision calculation or from the rounding */ - if (inex == 0) - params->P[offset].mpfr_inex = params->P[0].mpfr_inex; - else - params->P[offset].mpfr_inex = inex; - } - else - /* double rounding occurs */ - return 1; - } - } - return 0; -} - - |