summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorthevenyp <thevenyp@211d60ee-9f03-0410-a15a-8952a2c7a4e4>2013-12-03 13:59:38 +0000
committerthevenyp <thevenyp@211d60ee-9f03-0410-a15a-8952a2c7a4e4>2013-12-03 13:59:38 +0000
commit9160794b0312583fb1755980362fff1df8fd205b (patch)
treea6475d050671f6853df8cf418ee6276e3a5c30a8
parent25fe1f3e42fd9bf03953bbd26ae6e7af9275f873 (diff)
downloadmpc-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.am7
-rw-r--r--tests/double_rounding.c151
-rw-r--r--tests/templates.h14
-rw-r--r--tests/tgeneric.tpl134
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;
-}
-
-