From f8e19d05072cb3e7bc32fc093868fdf73fa9a232 Mon Sep 17 00:00:00 2001 From: thevenyp Date: Wed, 22 Jan 2014 10:09:07 +0000 Subject: [tests] Support of sin_cos with the new test framework. git-svn-id: svn://scm.gforge.inria.fr/svn/mpc/trunk@1422 211d60ee-9f03-0410-a15a-8952a2c7a4e4 --- tests/check_data.c | 5 +- tests/clear_parameters.c | 3 +- tests/copy_parameter.c | 3 +- tests/double_rounding.c | 65 +++++++++--- tests/init_parameters.c | 3 +- tests/mpc-tests.h | 19 +++- tests/print_parameter.c | 7 ++ tests/read_description.c | 9 +- tests/read_line.c | 9 +- tests/rounding.c | 126 +++++++++++++++++------ tests/sin_cos.dsc | 4 +- tests/tgeneric.tpl | 3 +- tests/tsin_cos.c | 262 +---------------------------------------------- 13 files changed, 198 insertions(+), 320 deletions(-) diff --git a/tests/check_data.c b/tests/check_data.c index 6d6bc69..f834955 100644 --- a/tests/check_data.c +++ b/tests/check_data.c @@ -1,6 +1,6 @@ /* check_data.c -- Check computed data against reference result. -Copyright (C) 2012, 2013 INRIA +Copyright (C) 2012, 2013, 2014 INRIA This file is part of GNU MPC. @@ -62,6 +62,9 @@ check_param (mpc_operand_t* got, mpc_operand_t* expected, mpc_param_t t) return tpl_check_mpc_data (got->mpc, expected->mpc_data); + case MPCC_INEX: + return got->mpcc_inex == expected->mpcc_inex; + default: fprintf (stderr, "check_data: unsupported type.\n"); exit (1); diff --git a/tests/clear_parameters.c b/tests/clear_parameters.c index d5c74f8..cded00c 100644 --- a/tests/clear_parameters.c +++ b/tests/clear_parameters.c @@ -1,6 +1,6 @@ /* clear_parameters -- Deallocate memory for function parameters. -Copyright (C) 2012, 2013 INRIA +Copyright (C) 2012, 2013, 2014 INRIA This file is part of GNU MPC. @@ -48,6 +48,7 @@ clear_param (mpc_operand_t* p, mpc_param_t t) break; case MPC_INEX: + case MPCC_INEX: break; case MPC: mpc_clear (p->mpc); diff --git a/tests/copy_parameter.c b/tests/copy_parameter.c index 4c1ff37..8147019 100644 --- a/tests/copy_parameter.c +++ b/tests/copy_parameter.c @@ -1,7 +1,7 @@ /* copy_parameter.c -- Copy of an input parameter into a parameter reused for output. -Copyright (C) 2012, 2013 INRIA +Copyright (C) 2012, 2013, 2014 INRIA This file is part of GNU MPC. @@ -113,6 +113,7 @@ copy_parameter (mpc_fun_param_t *params, int index_dest, int index_src) case NATIVE_STRING: case MPFR_INEX: case MPFR_RND: case MPC_INEX: case MPC_RND: + case MPCC_INEX: /* no supported copy */ break; } diff --git a/tests/double_rounding.c b/tests/double_rounding.c index 6181d1a..601ba1a 100644 --- a/tests/double_rounding.c +++ b/tests/double_rounding.c @@ -1,6 +1,6 @@ /* double_rounding.c -- Functions for checking double rounding. -Copyright (C) 2013 INRIA +Copyright (C) 2013, 2014 INRIA This file is part of GNU MPC. @@ -35,7 +35,7 @@ double_rounding_mpfr (mpfr_ptr lowprec, if (hiprec_rnd == MPFR_RNDN) /* when rounding to nearest, use the trick for determining the - correct ternary value which is described in MPFR + correct ternary value which is described in the MPFR documentation */ { hiprec_err++; /* error is bounded by one half-ulp */ @@ -74,42 +74,75 @@ 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; + int rnd_index = offset - params->nbrnd; 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); + int inex; + + MPC_ASSERT ((params->T[0] == MPC_INEX) + || (params->T[0] == MPCC_INEX)); + MPC_ASSERT ((params->T[offset] == MPC_INEX) + || (params->T[offset] == MPCC_INEX)); MPC_ASSERT (params->T[out + offset] == MPC); MPC_ASSERT (params->T[rnd_index] == MPC_RND); + /* + For the time being, there may be either one or two rounding modes; + in the latter case, we assume that there are three outputs: + the inexact value and two complex numbers. + */ + inex = (params->nbrnd == 1 ? params->P[0].mpc_inex + : (out == 1 ? MPC_INEX1 (params->P[0].mpcc_inex) + : MPC_INEX2 (params->P[0].mpcc_inex))); + if (double_rounding_mpc (params->P[out + offset].mpc_data.mpc, params->P[out].mpc, - params->P[0].mpc_inex, + inex, params->P[rnd_index].mpc_rnd)) - /* the hight-precision value and the exact value round to the same + /* the high-precision value and the exact value round to the same low-precision value */ { - int inex; + int inex_hp, inex_re, inex_im; 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 + /* no double rounding means that the ternary value may come from the high-precision calculation or from the rounding */ + if (params->nbrnd == 1) + inex_hp = params->P[0].mpc_inex; + else /* nbrnd == 2 */ + if (out == 1) + inex_hp = MPC_INEX1 (params->P[0].mpcc_inex); + else /* out == 2 */ + inex_hp = MPC_INEX2 (params->P[0].mpcc_inex); + if (MPC_INEX_RE (inex) == 0) - params->P[offset].mpc_inex_data.real = - MPC_INEX_RE (params->P[0].mpc_inex); + inex_re = MPC_INEX_RE (inex_hp); else - params->P[offset].mpc_inex_data.real = MPC_INEX_RE (inex); + inex_re = 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); + inex_im = MPC_INEX_IM (inex_hp); else - params->P[offset].mpc_inex_data.imag = MPC_INEX_IM (inex); + inex_im = MPC_INEX_IM (inex); + + if (params->nbrnd == 1) { + params->P[offset].mpc_inex_data.real = inex_re; + params->P[offset].mpc_inex_data.imag = inex_im; + } + else /* nbrnd == 2 */ + if (out == 1) + params->P[offset].mpcc_inex = MPC_INEX (inex_re, inex_im); + else /* out == 2 */ + params->P[offset].mpcc_inex + = MPC_INEX12 (params->P[offset].mpcc_inex, + MPC_INEX (inex_re, inex_im)); + + rnd_index++; } else /* double rounding occurs */ @@ -141,6 +174,8 @@ double_rounding (mpc_fun_param_t *params) params->P[offset].mpfr_inex = params->P[0].mpfr_inex; else params->P[offset].mpfr_inex = inex; + + rnd_index++; } else /* double rounding occurs */ diff --git a/tests/init_parameters.c b/tests/init_parameters.c index ea94a34..a439c0b 100644 --- a/tests/init_parameters.c +++ b/tests/init_parameters.c @@ -1,6 +1,6 @@ /* init_parameters -- Allocate memory for function parameters. -Copyright (C) 2012 INRIA +Copyright (C) 2012, 2014 INRIA This file is part of GNU MPC. @@ -49,6 +49,7 @@ init_param (mpc_operand_t* p, mpc_param_t t) break; case MPC_INEX: + case MPCC_INEX: break; case MPC: mpc_init2 (p->mpc, 512); diff --git a/tests/mpc-tests.h b/tests/mpc-tests.h index 19027a5..8a33da8 100644 --- a/tests/mpc-tests.h +++ b/tests/mpc-tests.h @@ -1,6 +1,6 @@ /* mpc-tests.h -- Tests helper functions. -Copyright (C) 2008, 2009, 2010, 2011, 2012, 2013 INRIA +Copyright (C) 2008, 2009, 2010, 2011, 2012, 2013, 2014 INRIA This file is part of GNU MPC. @@ -179,7 +179,8 @@ typedef enum { MPFR_RND, /* mpfr_rnd_t */ MPC_INEX, /* mpc_inex */ MPC, /* mpc_t */ - MPC_RND /* mpc_rnd_t */ + MPC_RND, /* mpc_rnd_t */ + MPCC_INEX /* mpcc_inex */ } mpc_param_t; /* additional information for checking mpfr_t result */ @@ -255,15 +256,25 @@ typedef union { mpc_rnd_t mpc_rnd; int mpc_inex; mpc_inex_data_t mpc_inex_data; + int mpcc_inex; } mpc_operand_t; #define PARAMETER_ARRAY_SIZE 10 -/* function name plus parameters */ +/* function name plus parameters in the following order: + output parameters, input parameters (ending with rounding modes). + The input parameters include one rounding mode per mpfr/mpc + output starting from rnd_index. + For the time being, there may be either one or two rounding modes; + in the latter case, we assume that there are three outputs: + the inexact value and two complex numbers. + */ typedef struct { char *name; /* name of the function */ int nbout; /* number of output parameters */ - int nbin; /* number of input parameters */ + int nbin; /* number of input parameters, including rounding + modes */ + int nbrnd; /* number of rounding mode parameters */ mpc_operand_t P[PARAMETER_ARRAY_SIZE]; /* value of parameters */ mpc_param_t T[PARAMETER_ARRAY_SIZE]; /* type of parameters */ } mpc_fun_param_t; diff --git a/tests/print_parameter.c b/tests/print_parameter.c index e7820c8..3ae502b 100644 --- a/tests/print_parameter.c +++ b/tests/print_parameter.c @@ -118,6 +118,13 @@ print_parameter (mpc_fun_param_t* params, int index) mpc_rnd_mode[params->P[index].mpc_rnd]); break; + case MPCC_INEX: + printf (" double ternary value = %s, %s\n", + MPC_INEX_STR (MPC_INEX1 (params->P[index].mpcc_inex)), + MPC_INEX_STR (MPC_INEX2 (params->P[index].mpcc_inex)) + ); + break; + default: fprintf (stderr, "print_parameter: unsupported type.\n"); exit (1); diff --git a/tests/read_description.c b/tests/read_description.c index 8a02265..f706b69 100644 --- a/tests/read_description.c +++ b/tests/read_description.c @@ -56,7 +56,8 @@ static const param_typeval_t sparam_typeval[]= { { "mpc_inex" , MPC_INEX }, { "mpc_ptr" , MPC }, { "mpc_srcptr" , MPC }, - { "mpc_rnd_t" , MPC_RND } + { "mpc_rnd_t" , MPC_RND }, + { "mpcc_inex" , MPCC_INEX } }; /* read primitives */ @@ -166,6 +167,7 @@ read_description (mpc_fun_param_t* param, const char *filename) size_t len = 0; int nbout = 0; int nbin = 0; + int rnd_mode = 0; int j; open_datafile (&datafile_context, filename); @@ -251,12 +253,15 @@ read_description (mpc_fun_param_t* param, const char *filename) if (strlen (buffer) == 0 && feof (datafile_context.fd)) break; param->T[nbout+nbin] = description_findtype (buffer); + if (param->T[nbout+nbin] == MPC_RND || param->T[nbout+nbin] == MPFR_RND) + rnd_mode++; nbin++; } free (buffer); param->nbout = nbout; - param->nbin = nbin; + param->nbin = nbin; + param->nbrnd = rnd_mode; /* duplicate output parameters at the end for the expected values */ for (j = 0; j < param->nbout; j++) diff --git a/tests/read_line.c b/tests/read_line.c index 3fb29c5..cde5db8 100644 --- a/tests/read_line.c +++ b/tests/read_line.c @@ -1,6 +1,6 @@ /* read_line.c -- Read line of test data in file. -Copyright (C) 2012, 2013 INRIA +Copyright (C) 2012, 2013, 2014 INRIA This file is part of GNU MPC. @@ -98,6 +98,12 @@ read_param (mpc_datafile_context_t* datafile_context, case MPC_RND: tpl_read_mpc_rnd (datafile_context, &p->mpc_rnd); return; + + case MPCC_INEX: + /* TODO */ + fprintf (stderr, "read_param: type not implemented.\n"); + exit (1); + break; } fprintf (stderr, "read_param: unsupported type.\n"); @@ -134,6 +140,7 @@ set_precision (mpc_fun_param_t* params, int index) case GMP_F: case MPFR_INEX: case MPFR_RND: case MPC_INEX: case MPC_RND: + case MPCC_INEX: /* unsupported types */ break; } diff --git a/tests/rounding.c b/tests/rounding.c index 603e627..86c4321 100644 --- a/tests/rounding.c +++ b/tests/rounding.c @@ -1,6 +1,6 @@ /* rounding.c -- file for functions iterating over rounding modes. -Copyright (C) 2013 INRIA +Copyright (C) 2013, 2014 INRIA This file is part of GNU MPC. @@ -56,21 +56,45 @@ is_valid_mpfr_rnd_mode (mpfr_rnd_t curr) return 0; } +static mpc_rnd_t +next_mpc_rnd_mode (mpc_rnd_t rnd) +{ + mpfr_rnd_t rnd_re = MPC_RND_RE (rnd); + mpfr_rnd_t rnd_im = MPC_RND_IM (rnd); + + rnd_im = next_mpfr_rnd_mode (rnd_im); + if (!is_valid_mpfr_rnd_mode (rnd_im)) + { + rnd_re = next_mpfr_rnd_mode (rnd_re); + rnd_im = FIRST_MPFR_RND_MODE; + } + + return MPC_RND(rnd_re, rnd_im); +} + +static int +is_valid_mpc_rnd_mode (mpc_rnd_t rnd) +/* returns 1 if curr is a valid rounding mode, and 0 otherwise */ +{ + mpfr_rnd_t rnd_re = MPC_RND_RE (rnd); + mpfr_rnd_t rnd_im = MPC_RND_IM (rnd); + + return is_valid_mpfr_rnd_mode (rnd_re) && is_valid_mpfr_rnd_mode (rnd_im); +} /* functions using abstract parameters */ -void -first_rnd_mode (mpc_fun_param_t *params) +static void +first_mode (mpc_fun_param_t *params, int index) { - int rnd_mode_index = params->nbout + params->nbin - 1; - switch (params->T[rnd_mode_index]) + switch (params->T[index]) { case MPC_RND: - params->P[rnd_mode_index].mpc_rnd = + params->P[index].mpc_rnd = MPC_RND(FIRST_MPFR_RND_MODE, FIRST_MPFR_RND_MODE); break; case MPFR_RND: - params->P[rnd_mode_index].mpfr_rnd = FIRST_MPFR_RND_MODE; + params->P[index].mpfr_rnd = FIRST_MPFR_RND_MODE; break; default: printf ("The rounding mode is expected to be" @@ -79,27 +103,18 @@ first_rnd_mode (mpc_fun_param_t *params) } } -void -next_rnd_mode (mpc_fun_param_t *params) +static void +next_mode (mpc_fun_param_t *params, int index) { - mpfr_rnd_t rnd_re, rnd_im; - int rnd_mode_index = params->nbout + params->nbin - 1; - switch (params->T[rnd_mode_index]) + switch (params->T[index]) { case MPC_RND: - rnd_re = MPC_RND_RE (params->P[rnd_mode_index].mpc_rnd); - rnd_im = MPC_RND_IM (params->P[rnd_mode_index].mpc_rnd); - rnd_im = next_mpfr_rnd_mode (rnd_im); - if (!is_valid_mpfr_rnd_mode (rnd_im)) - { - rnd_re = next_mpfr_rnd_mode (rnd_re); - rnd_im = FIRST_MPFR_RND_MODE; - } - params->P[rnd_mode_index].mpc_rnd = MPC_RND(rnd_re, rnd_im); + params->P[index].mpc_rnd = + next_mpc_rnd_mode (params->P[index].mpc_rnd); break; case MPFR_RND: - params->P[rnd_mode_index].mpfr_rnd = - next_mpfr_rnd_mode (params->P[rnd_mode_index].mpfr_rnd); + params->P[index].mpfr_rnd = + next_mpfr_rnd_mode (params->P[index].mpfr_rnd); break; default: printf ("The rounding mode is expected to be" @@ -108,24 +123,67 @@ next_rnd_mode (mpc_fun_param_t *params) } } -int -is_valid_rnd_mode (mpc_fun_param_t *params) -/* returns 1 if curr is a valid rounding mode, and 0 otherwise */ +static int +is_valid_mode (mpc_fun_param_t *params, int index) +/* returns 1 if params->P[index] is a valid rounding mode, and 0 otherwise */ { - mpfr_rnd_t rnd_re, rnd_im; - int rnd_mode_index = params->nbout + params->nbin - 1; - switch (params->T[rnd_mode_index]) + switch (params->T[index]) { case MPC_RND: - rnd_re = MPC_RND_RE (params->P[rnd_mode_index].mpc_rnd); - rnd_im = MPC_RND_IM (params->P[rnd_mode_index].mpc_rnd); - return is_valid_mpfr_rnd_mode (rnd_re) - && is_valid_mpfr_rnd_mode (rnd_im); + return is_valid_mpc_rnd_mode (params->P[index].mpc_rnd); case MPFR_RND: - return is_valid_mpfr_rnd_mode (params->P[rnd_mode_index].mpfr_rnd); + return is_valid_mpfr_rnd_mode (params->P[index].mpfr_rnd); default: printf ("The rounding mode is expected to be" " the last input parameter.\n"); exit (-1); } } + +void +first_rnd_mode (mpc_fun_param_t *params) +{ + int rnd_mode_index; + + for (rnd_mode_index = params->nbout + params->nbin - params->nbrnd; + rnd_mode_index < params->nbout + params->nbin; + rnd_mode_index++) + { + first_mode (params, rnd_mode_index); + } +} + + +void +next_rnd_mode (mpc_fun_param_t *params) +/* cycle through all valid rounding modes and finish with an invalid one */ +{ + int last = params->nbout + params->nbin - 1; + int index = params->nbout + params->nbin - params->nbrnd; + int carry = 1; + + while (carry && index <= last) { + next_mode (params, index); + if (!is_valid_mode (params, index) && index < last) + first_mode (params, index); + else + carry = 0; + index++; + } +} + +int +is_valid_rnd_mode (mpc_fun_param_t *params) +/* returns 1 if all rounding parameters are set to a valid rounding mode, + and 0 otherwise */ +{ + int index; + + for (index = params->nbout + params->nbin - params->nbrnd; + index < params->nbout + params->nbin; + index++) + if (! is_valid_mode (params, index)) + return 0; + + return 1; +} diff --git a/tests/sin_cos.dsc b/tests/sin_cos.dsc index ddefe79..0bcecd4 100644 --- a/tests/sin_cos.dsc +++ b/tests/sin_cos.dsc @@ -1,6 +1,6 @@ # Description file for mpc_sin_cos # -# Copyright (C) 2013 INRIA +# Copyright (C) 2013, 2014 INRIA # # This file is part of GNU MPC. # @@ -20,7 +20,7 @@ NAME: mpc_sin_cos RETURN: - mpc_inex + mpcc_inex OUTPUT: mpc_ptr mpc_ptr diff --git a/tests/tgeneric.tpl b/tests/tgeneric.tpl index 22b2548..57a55a7 100644 --- a/tests/tgeneric.tpl +++ b/tests/tgeneric.tpl @@ -1,6 +1,6 @@ /* tgeneric.tpl -- template file for generic tests. -Copyright (C) 2008, 2009, 2010, 2011, 2012, 2013 INRIA +Copyright (C) 2008, 2009, 2010, 2011, 2012, 2013, 2014 INRIA This file is part of GNU MPC. @@ -320,6 +320,7 @@ random_params (mpc_fun_param_t *params, case NATIVE_STRING: case MPFR_INEX: case MPC_INEX: + case MPCC_INEX: /* unsupported types */ fprintf (stderr, "random_params: unsupported type.\n"); exit (1); diff --git a/tests/tsin_cos.c b/tests/tsin_cos.c index ae1b1c8..0d67d83 100644 --- a/tests/tsin_cos.c +++ b/tests/tsin_cos.c @@ -1,6 +1,6 @@ /* tsin_cos -- test file for mpc_sin_cos. -Copyright (C) 2011, 2013 INRIA +Copyright (C) 2011, 2013, 2014 INRIA This file is part of GNU MPC. @@ -20,269 +20,17 @@ along with this program. If not, see http://www.gnu.org/licenses/ . #include "mpc-tests.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); +#define MPC_FUNCTION_CALL \ + P[0].mpcc_inex = mpc_sin_cos (P[1].mpc, P[2].mpc, P[3].mpc, P[4].mpc_rnd, P[5].mpc_rnd) -/* 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 (¶ms, "sin_cos.dsc"); - init_parameters (¶ms); - read_description (¶ms_sin, "sin.dsc"); - init_parameters (¶ms_sin); - read_description (¶ms_cos, "cos.dsc"); - init_parameters (¶ms_cos); - - /* ask for enough memory */ - set_output_precision (¶ms, 4 * prec_max); - set_input_precision (¶ms, prec_max); - set_reference_precision (¶ms, prec_max); - set_output_precision (¶ms_sin, 4 * prec_max); - set_input_precision (¶ms_sin, prec_max); - set_reference_precision (¶ms_sin, prec_max); - set_output_precision (¶ms_cos, 4 * prec_max); - set_input_precision (¶ms_cos, prec_max); - set_reference_precision (¶ms_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 (¶ms, ¶ms_sin, ¶ms_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 (¶ms, ¶ms_sin, ¶ms_cos, - prec_max, exp_min, exp_max, - special); - - clear_parameters (¶ms); - clear_parameters (¶ms_sin); - clear_parameters (¶ms_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 -}; - -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; - } -} +#include "tgeneric.tpl" int main (void) { test_start (); - tgeneric_custom (2, 512, 13, 7); + tgeneric_template ("sin_cos.dsc", 2, 512, 13, 7); test_end (); -- cgit v1.2.1