diff options
author | thevenyp <thevenyp@211d60ee-9f03-0410-a15a-8952a2c7a4e4> | 2013-12-02 17:58:42 +0000 |
---|---|---|
committer | thevenyp <thevenyp@211d60ee-9f03-0410-a15a-8952a2c7a4e4> | 2013-12-02 17:58:42 +0000 |
commit | 45d15372624b20f43f8c157836c346eae309b0e1 (patch) | |
tree | 4331dd441411d55d20eec5f184b2fab2caaa6af0 | |
parent | c351c2c6e45588cf61ead29d6cd8b832d6e05ff2 (diff) | |
download | mpc-45d15372624b20f43f8c157836c346eae309b0e1.tar.gz |
[tests/] Detect double rounding for a mpfr_t output.
git-svn-id: svn://scm.gforge.inria.fr/svn/mpc/branches/benchs_tests@1352 211d60ee-9f03-0410-a15a-8952a2c7a4e4
-rw-r--r-- | tests/tgeneric.tpl | 54 |
1 files changed, 53 insertions, 1 deletions
diff --git a/tests/tgeneric.tpl b/tests/tgeneric.tpl index 120dea3..ae503fb 100644 --- a/tests/tgeneric.tpl +++ b/tests/tgeneric.tpl @@ -300,6 +300,37 @@ 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 inex, + mpfr_rnd_t rnd) +{ + mpfr_exp_t hiprec_err; + mpfr_rnd_t lowprec_rnd = 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 (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 (mpfr_nan_p (hiprec) + || mpfr_zero_p (hiprec) + || mpfr_inf_p (hiprec) + || inex == 0 + || mpfr_can_round (hiprec, hiprec_err, 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 inex, mpc_rnd_t rnd) { /* reference value in high precision */ @@ -387,7 +418,28 @@ double_rounding (mpc_fun_param_t *params) } else if (params->T[out] == MPFR) { - /* TODO */ + 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; + params->P[offset].mpfr_inex = inex; + } + else + /* double rounding occurs */ + return 1; } } return 0; |