/* File for generic tests.
Copyright (C) 2008, 2009 Philippe Th\'eveny, Andreas Enge, Paul Zimmermann
This file is part of the MPC Library.
The MPC Library 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 2.1 of the License, or (at your
option) any later version.
The MPC Library 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 the MPC Library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
MA 02111-1307, USA. */
/* #include <stdlib.h> */
#include "mpc-tests.h"
/* Warning: unlike the MPFR macro (defined in mpfr-impl.h), this one returns
true when b is singular */
#define MPFR_CAN_ROUND(b,err,prec,rnd) \
(mpfr_zero_p (b) || mpfr_inf_p (b) \
|| mpfr_can_round (b, (long)mpfr_get_prec (b) - (err), (rnd), \
GMP_RNDZ, (prec) + ((rnd)==GMP_RNDN)))
static void
tgeneric_cc (mpc_function *function, mpc_ptr op, mpc_ptr rop,
mpc_ptr rop4, mpc_ptr rop4rnd, mpc_rnd_t rnd)
{
known_signs_t ks = {1, 1};
/* We compute the result with four times the precision and check whether the
rounding is correct. Error reports in this part of the algorithm might
still be wrong, though, since there are two consecutive roundings (but we
try to avoid them). */
function->pointer.CC (rop4, op, rnd);
function->pointer.CC (rop, op, rnd);
/* can't use the mpfr_can_round function when argument is singular,
use a custom macro instead. */
if (MPFR_CAN_ROUND (MPC_RE (rop4), 1, MPFR_PREC (MPC_RE (rop)),
MPC_RND_RE (rnd))
&& MPFR_CAN_ROUND (MPC_IM (rop4), 1, MPFR_PREC (MPC_IM (rop)),
MPC_RND_IM (rnd)))
mpc_set (rop4rnd, rop4, rnd);
else
/* avoid double rounding error */
return;
if (same_mpc_value (rop, rop4rnd, ks))
return;
/* rounding failed */
printf ("Rounding in %s might be incorrect for\n", function->name);
OUT (op);
printf ("with rounding mode (%s, %s)",
mpfr_print_rnd_mode (MPC_RND_RE (rnd)),
mpfr_print_rnd_mode (MPC_RND_IM (rnd)));
printf ("\n%s gives ", function->name);
OUT (rop);
printf ("%s quadruple precision gives ", function->name);
OUT (rop4);
printf ("and is rounded to ");
OUT (rop4rnd);
exit (1);
}
static void
tgeneric_fc (mpc_function *function, mpc_ptr op, mpfr_ptr rop,
mpfr_ptr rop4, mpfr_ptr rop4rnd, mpfr_rnd_t rnd)
{
function->pointer.FC (rop4, op, rnd);
function->pointer.FC (rop, op, rnd);
if (MPFR_CAN_ROUND (rop4, 1, MPFR_PREC (rop), rnd))
mpfr_set (rop4rnd, rop4, rnd);
else
return;
if (same_mpfr_value (rop, rop4rnd, 1))
return;
printf ("Rounding in %s might be incorrect for\n", function->name);
OUT (op);
printf ("with rounding mode %s", mpfr_print_rnd_mode (rnd));
printf ("\n%s gives ", function->name);
MPFR_OUT (rop);
printf ("%s quadruple precision gives ", function->name);
MPFR_OUT (rop4);
printf ("and is rounded to ");
MPFR_OUT (rop4rnd);
exit (1);
}
static void
tgeneric_cfc (mpc_function *function, mpfr_ptr op1, mpc_ptr op2,
mpc_ptr rop, mpc_ptr rop4, mpc_ptr rop4rnd, mpc_rnd_t rnd)
{
known_signs_t ks = {1, 1};
function->pointer.CFC (rop4, op1, op2, rnd);
function->pointer.CFC (rop, op1, op2, rnd);
if (MPFR_CAN_ROUND (MPC_RE (rop4), 1, MPFR_PREC (MPC_RE (rop)),
MPC_RND_RE (rnd))
&& MPFR_CAN_ROUND (MPC_IM (rop4), 1, MPFR_PREC (MPC_IM (rop)),
MPC_RND_IM (rnd)))
mpc_set (rop4rnd, rop4, rnd);
else
return;
if (same_mpc_value (rop, rop4rnd, ks))
return;
printf ("Rounding in %s might be incorrect for\n", function->name);
MPFR_OUT (op1);
OUT (op2);
printf ("with rounding mode (%s, %s)",
mpfr_print_rnd_mode (MPC_RND_RE (rnd)),
mpfr_print_rnd_mode (MPC_RND_IM (rnd)));
printf ("\n%s gives ", function->name);
OUT (rop);
printf ("%s quadruple precision gives ", function->name);
OUT (rop4);
printf ("and is rounded to ");
OUT (rop4rnd);
exit (1);
}
static void
tgeneric_ccf (mpc_function *function, mpc_ptr op1, mpfr_ptr op2,
mpc_ptr rop, mpc_ptr rop4, mpc_ptr rop4rnd, mpc_rnd_t rnd)
{
known_signs_t ks = {1, 1};
function->pointer.CCF (rop4, op1, op2, rnd);
function->pointer.CCF (rop, op1, op2, rnd);
if (MPFR_CAN_ROUND (MPC_RE (rop4), 1, MPFR_PREC (MPC_RE (rop)),
MPC_RND_RE (rnd))
&& MPFR_CAN_ROUND (MPC_IM (rop4), 1, MPFR_PREC (MPC_IM (rop)),
MPC_RND_IM (rnd)))
mpc_set (rop4rnd, rop4, rnd);
else
return;
if (same_mpc_value (rop, rop4rnd, ks))
return;
printf ("Rounding in %s might be incorrect for\n", function->name);
OUT (op1);
MPFR_OUT (op2);
printf ("with rounding mode (%s, %s)",
mpfr_print_rnd_mode (MPC_RND_RE (rnd)),
mpfr_print_rnd_mode (MPC_RND_IM (rnd)));
printf ("\n%s gives ", function->name);
OUT (rop);
printf ("%s quadruple precision gives ", function->name);
OUT (rop4);
printf ("and is rounded to ");
OUT (rop4rnd);
exit (1);
}
static void
tgeneric_ccc (mpc_function *function, mpc_ptr op1, mpc_ptr op2,
mpc_ptr rop, mpc_ptr rop4, mpc_ptr rop4rnd, mpc_rnd_t rnd)
{
known_signs_t ks = {1, 1};
/* We compute the result with four times the precision and check whether the
rounding is correct. Error reports in this part of the algorithm might
still be wrong, though, since there are two consecutive roundings (but we
try to avoid them). */
function->pointer.CCC (rop4, op1, op2, rnd);
function->pointer.CCC (rop, op1, op2, rnd);
/* can't use mpfr_can_round when argument is singular */
if (MPFR_CAN_ROUND (MPC_RE (rop4), 1, MPFR_PREC (MPC_RE (rop)),
MPC_RND_RE (rnd))
&& MPFR_CAN_ROUND (MPC_IM (rop4), 1, MPFR_PREC (MPC_IM (rop)),
MPC_RND_IM (rnd)))
mpc_set (rop4rnd, rop4, rnd);
else
/* avoid double rounding error */
return;
if (same_mpc_value (rop, rop4rnd, ks))
return;
/* rounding failed */
printf ("Rounding in %s might be incorrect for\n", function->name);
OUT (op1);
OUT (op2);
printf ("with rounding mode (%s, %s)",
mpfr_print_rnd_mode (MPC_RND_RE (rnd)),
mpfr_print_rnd_mode (MPC_RND_IM (rnd)));
printf ("\n%s gives ", function->name);
OUT (rop);
printf ("%s quadruple precision gives ", function->name);
OUT (rop4);
printf ("and is rounded to ");
OUT (rop4rnd);
exit (1);
}
static void
tgeneric_ccu (mpc_function *function, mpc_ptr op1, unsigned long int op2,
mpc_ptr rop, mpc_ptr rop4, mpc_ptr rop4rnd, mpc_rnd_t rnd)
{
known_signs_t ks = {1, 1};
function->pointer.CCU (rop4, op1, op2, rnd);
function->pointer.CCU (rop, op1, op2, rnd);
if (MPFR_CAN_ROUND (MPC_RE (rop4), 1, MPFR_PREC (MPC_RE (rop)),
MPC_RND_RE (rnd))
&& MPFR_CAN_ROUND (MPC_IM (rop4), 1, MPFR_PREC (MPC_IM (rop)),
MPC_RND_IM (rnd)))
mpc_set (rop4rnd, rop4, rnd);
else
return;
if (same_mpc_value (rop, rop4rnd, ks))
return;
printf ("Rounding in %s might be incorrect for\n", function->name);
OUT (op1);
printf ("op2=%lu\n", op2);
printf ("with rounding mode (%s, %s)",
mpfr_print_rnd_mode (MPC_RND_RE (rnd)),
- 1
- 2
- 3
- 4
- 5
- 6
前往页