summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorthevenyp <thevenyp@211d60ee-9f03-0410-a15a-8952a2c7a4e4>2013-12-03 18:54:56 +0000
committerthevenyp <thevenyp@211d60ee-9f03-0410-a15a-8952a2c7a4e4>2013-12-03 18:54:56 +0000
commite4af317cde5d5d669cd123bd9aaad7204e9e47fa (patch)
tree425cbf9a957e57b300924ce415455917a50a6f8e
parent6fe038b3dfcfd0ff8b86eefbf9fb71bdc9103ea5 (diff)
downloadmpc-e4af317cde5d5d669cd123bd9aaad7204e9e47fa.tar.gz
[tests/] Add templated tests for mpc_sin_cos.
git-svn-id: svn://scm.gforge.inria.fr/svn/mpc/branches/benchs_tests@1379 211d60ee-9f03-0410-a15a-8952a2c7a4e4
-rw-r--r--tests/sin_cos.dsc1
-rw-r--r--tests/tsin_cos_tmpl.c267
2 files changed, 262 insertions, 6 deletions
diff --git a/tests/sin_cos.dsc b/tests/sin_cos.dsc
index 63e91d6..ddefe79 100644
--- a/tests/sin_cos.dsc
+++ b/tests/sin_cos.dsc
@@ -27,3 +27,4 @@ OUTPUT:
INPUT:
mpc_srcptr
mpc_rnd_t
+ mpc_rnd_t
diff --git a/tests/tsin_cos_tmpl.c b/tests/tsin_cos_tmpl.c
index a1e7424..d28c6e2 100644
--- a/tests/tsin_cos_tmpl.c
+++ b/tests/tsin_cos_tmpl.c
@@ -1,6 +1,6 @@
-/* tsin_cos -- test file for mpc_sin_cos.
+/* tsin_cos_tmpl.c -- templated test file for mpc_sin_cos.
-Copyright (C) 2011 INRIA
+Copyright (C) 2011, 2013 INRIA
This file is part of GNU MPC.
@@ -18,16 +18,271 @@ 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 "mpc-tests.h"
+#include "templates.h"
+
+static void random_params (mpc_fun_param_t *params,
+ mpfr_exp_t exp_min, mpfr_exp_t exp_max,
+ int special);
+static void check_against_quadruple_precision (mpc_fun_param_t *params,
+ mpc_fun_param_t *params_sin,
+ mpc_fun_param_t *params_cos,
+ mpfr_prec_t prec,
+ mpfr_exp_t exp_min,
+ mpfr_exp_t exp_max,
+ int special);
+
+/* tgeneric(desc, prec_min, prec_max, step, exp_max) checks rounding with
+ random numbers:
+ - with precision ranging from prec_min to prec_max with an increment of
+ step,
+ - with exponent between -exp_max and exp_max.
+ - for pure real, pure imaginary and infinite random parameters.
+
+ It also checks parameter reuse.
+*/
+static void
+tgeneric_custom (mpfr_prec_t prec_min, mpfr_prec_t prec_max, mpfr_prec_t step,
+ mpfr_exp_t exp_max)
+{
+ int special = 0;
+ const int last_special = 8;
+ mpfr_prec_t prec;
+ mpfr_exp_t exp_min;
+ mpc_fun_param_t params;
+ mpc_fun_param_t params_sin;
+ mpc_fun_param_t params_cos;
+
+ read_description (&params, "sin_cos.dsc");
+ init_parameters (&params);
+ read_description (&params_sin, "sin.dsc");
+ init_parameters (&params_sin);
+ read_description (&params_cos, "cos.dsc");
+ init_parameters (&params_cos);
+
+ /* ask for enough memory */
+ set_output_precision (&params, 4 * prec_max);
+ set_input_precision (&params, prec_max);
+ set_reference_precision (&params, prec_max);
+ set_output_precision (&params_sin, 4 * prec_max);
+ set_input_precision (&params_sin, prec_max);
+ set_reference_precision (&params_sin, prec_max);
+ set_output_precision (&params_cos, 4 * prec_max);
+ set_input_precision (&params_cos, prec_max);
+ set_reference_precision (&params_cos, prec_max);
+
+ /* sanity checks */
+ exp_min = mpfr_get_emin ();
+ if (exp_max <= 0 || exp_max > mpfr_get_emax ())
+ exp_max = mpfr_get_emax();
+ if (-exp_max > exp_min)
+ exp_min = - exp_max;
+ if (step < 1)
+ step = 1;
+
+ /* check consistency with quadruple precision for random parameters */
+ for (prec = prec_min; prec <= prec_max; prec += step)
+ check_against_quadruple_precision (&params, &params_sin, &params_cos,
+ prec, exp_min, exp_max, -1);
+
+ /* check consistency with quadruple precision for special values:
+ pure real, pure imaginary, or infinite arguments */
+ for (special = 0; special < last_special ; special++)
+ check_against_quadruple_precision (&params, &params_sin, &params_cos,
+ prec_max, exp_min, exp_max,
+ special);
+
+ clear_parameters (&params);
+ clear_parameters (&params_sin);
+ clear_parameters (&params_cos);
+}
+
+static void
+filter_params (mpc_fun_param_t *params_sin_cos,
+ mpc_fun_param_t *params,
+ int index)
+{
+ /* inex */
+ params->P[0].mpc_inex = (index == 0) ?
+ MPC_INEX1 (params_sin_cos->P[0].mpc_inex)
+ : MPC_INEX2 (params_sin_cos->P[0].mpc_inex);
+
+ /* output */
+ mpc_set (params->P[1].mpc, params_sin_cos->P[1 + index].mpc, MPC_RNDNN);
+
+ /* input */
+ mpc_set (params->P[2].mpc, params_sin_cos->P[3].mpc, MPC_RNDNN);
+
+ /* rnd mode is already set */
+}
+
+static void
+gather_params (mpc_fun_param_t *params_sin_cos,
+ mpc_fun_param_t *params_sin,
+ mpc_fun_param_t *params_cos)
+{
+ /* do not check inex value */
+ params_sin_cos->P[6].mpc_inex_data.real = TERNARY_NOT_CHECKED;
+ params_sin_cos->P[6].mpc_inex_data.imag = TERNARY_NOT_CHECKED;
+
+ mpc_set (params_sin_cos->P[7].mpc_data.mpc,
+ params_sin->P[5].mpc_data.mpc,
+ MPC_RNDNN);
+ params_sin_cos->P[7].mpc_data.known_sign_real = -1;
+ params_sin_cos->P[7].mpc_data.known_sign_imag = -1;
+
+ mpc_set (params_sin_cos->P[8].mpc_data.mpc,
+ params_cos->P[5].mpc_data.mpc,
+ MPC_RNDNN);
+ params_sin_cos->P[8].mpc_data.known_sign_real = -1;
+ params_sin_cos->P[8].mpc_data.known_sign_imag = -1;
+}
+
+static void
+gather_rounding_modes (mpc_fun_param_t *params_sin_cos,
+ mpc_fun_param_t *params_sin,
+ mpc_fun_param_t *params_cos)
+{
+ params_sin_cos->P[4].mpc_rnd = params_sin->P[3].mpc_rnd;
+ params_sin_cos->P[5].mpc_rnd = params_cos->P[3].mpc_rnd;
+}
+
+static void
+check_against_quadruple_precision (mpc_fun_param_t *params,
+ mpc_fun_param_t *params_sin,
+ mpc_fun_param_t *params_cos,
+ mpfr_prec_t prec,
+ mpfr_exp_t exp_min, mpfr_exp_t exp_max,
+ int special)
+{
+ mpc_operand_t *P = params->P; /* developer-friendly alias, used in macros */
+
+ set_input_precision (params, prec);
+ set_reference_precision (params, prec);
+ set_output_precision (params, 4 * prec);
+
+ set_input_precision (params_sin, prec);
+ set_reference_precision (params_sin, prec);
+ set_output_precision (params_sin, 4 * prec);
+
+ set_input_precision (params_cos, prec);
+ set_reference_precision (params_cos, prec);
+ set_output_precision (params_cos, 4 * prec);
+
+
+ for (first_rnd_mode (params_sin);
+ is_valid_rnd_mode (params_sin);
+ next_rnd_mode (params_sin))
+ {
+ for (first_rnd_mode (params_cos);
+ is_valid_rnd_mode (params_cos);
+ next_rnd_mode (params_cos))
+ {
+ gather_rounding_modes (params, params_sin, params_cos);
+ do
+ {
+ random_params (params, exp_min, exp_max, special);
+ P[0].mpc_inex = mpc_sin_cos (P[1].mpc, P[2].mpc, P[3].mpc,
+ P[4].mpc_rnd, P[5].mpc_rnd);
+ filter_params (params, params_sin, 0);
+ filter_params (params, params_cos, 1);
+ } while (double_rounding (params_sin)
+ || double_rounding (params_cos));
+ gather_params (params, params_sin, params_cos);
+
+ set_output_precision (params, prec);
+ P[0].mpc_inex = mpc_sin_cos (P[1].mpc, P[2].mpc, P[3].mpc,
+ P[4].mpc_rnd, P[5].mpc_rnd);
+ check_data (NULL, params, 0);
+
+ set_output_precision (params, 4 * prec);
+ }
+ }
+}
+
+
+/* special cases */
+
+enum {
+ SPECIAL_MINF,
+ SPECIAL_MZERO,
+ SPECIAL_PZERO,
+ SPECIAL_PINF,
+ SPECIAL_COUNT,
+} special_case;
+
+static void
+special_mpfr (mpfr_ptr x, int special)
+{
+ switch (special)
+ {
+ case SPECIAL_MINF:
+ mpfr_set_inf (x, -1);
+ break;
+ case SPECIAL_MZERO:
+ mpfr_set_zero (x, -1);
+ break;
+ case SPECIAL_PZERO:
+ mpfr_set_zero (x, +1);
+ break;
+ case SPECIAL_PINF:
+ mpfr_set_inf (x, +1);
+ break;
+ }
+}
+
+static void
+special_random_mpc (mpc_ptr z, mpfr_exp_t exp_min, mpfr_exp_t exp_max,
+ int special)
+{
+ mpfr_ptr special_part;
+ mpfr_ptr random_part;
+ int mpfr_special;
+
+ if (special < SPECIAL_COUNT)
+ {
+ mpfr_special = special;
+ special_part = mpc_realref (z);
+ random_part = mpc_imagref (z);
+ }
+ else
+ {
+ mpfr_special = special - SPECIAL_COUNT;
+ special_part = mpc_imagref (z);
+ random_part = mpc_realref (z);
+ }
+
+ special_mpfr (special_part, mpfr_special);
+ test_random_mpfr (random_part, exp_min, exp_max, 128);
+}
+
+static void
+random_params (mpc_fun_param_t *params,
+ mpfr_exp_t exp_min, mpfr_exp_t exp_max,
+ int special)
+{
+ int i;
+ int base_index = 0;
+ const int start = params->nbout;
+ const int end = start + params->nbin - 2;
+
+ for (i = start; i < end; i++)
+ {
+ if (base_index <= special
+ && special - base_index < 2 * SPECIAL_COUNT)
+ special_random_mpc (params->P[i].mpc, exp_min, exp_max,
+ special - base_index);
+ else
+ test_random_mpc (params->P[i].mpc, exp_min, exp_max, 128);
+ base_index += 2 * SPECIAL_COUNT;
+ }
+}
int
main (void)
{
- DECL_FUNC (CC_C, f, mpc_sin_cos);
-
test_start ();
- tgeneric (f, 2, 512, 13, 7);
+ tgeneric_custom (2, 512, 13, 7);
test_end ();