summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorthevenyp <thevenyp@211d60ee-9f03-0410-a15a-8952a2c7a4e4>2013-12-02 17:58:42 +0000
committerthevenyp <thevenyp@211d60ee-9f03-0410-a15a-8952a2c7a4e4>2013-12-02 17:58:42 +0000
commit45d15372624b20f43f8c157836c346eae309b0e1 (patch)
tree4331dd441411d55d20eec5f184b2fab2caaa6af0
parentc351c2c6e45588cf61ead29d6cd8b832d6e05ff2 (diff)
downloadmpc-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.tpl54
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;