mirror of
https://github.com/vale981/arb
synced 2025-03-04 17:01:40 -05:00
change arf_get_mpfr to return an MPFR underflow/overflow result instead of throwing flint_abort() if the exponent is out of bounds
This commit is contained in:
parent
58d9ef888d
commit
f433b7597e
4 changed files with 131 additions and 4 deletions
|
@ -30,9 +30,49 @@ arf_get_mpfr(mpfr_t x, const arf_t y, mpfr_rnd_t rnd)
|
|||
}
|
||||
else if (COEFF_IS_MPZ(*ARF_EXPREF(y)))
|
||||
{
|
||||
flint_printf("exception: exponent too large to convert to mpfr");
|
||||
flint_abort();
|
||||
r = 0; /* dummy return because flint_abort() is not declared noreturn */
|
||||
/* Incidentally, COEFF_MIN and COEFF_MAX are exactly the same
|
||||
as the minimum and maximum allowed MPFR exponents. We
|
||||
assert this to make sure the following code is valid.
|
||||
Unfortunately, MPFR provides no convenient function to
|
||||
assign a big exponent with automatic underflow/overflow. */
|
||||
if (COEFF_MIN > mpfr_get_emin_min() ||
|
||||
COEFF_MAX < mpfr_get_emax_max())
|
||||
{
|
||||
flint_printf("unsupported MPFR exponent range: %wd, %wd, %wd, %wd\n",
|
||||
COEFF_MIN, mpfr_get_emin_min(), COEFF_MAX, mpfr_get_emax_max());
|
||||
flint_abort();
|
||||
}
|
||||
|
||||
if (fmpz_sgn(ARF_EXPREF(y)) > 0)
|
||||
{
|
||||
if (arf_sgn(y) > 0)
|
||||
{
|
||||
mpfr_set_inf(x, 1);
|
||||
mpfr_nextbelow(x);
|
||||
}
|
||||
else
|
||||
{
|
||||
mpfr_set_inf(x, -1);
|
||||
mpfr_nextabove(x);
|
||||
}
|
||||
|
||||
r = mpfr_mul_2si(x, x, 1, rnd);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (arf_sgn(y) > 0)
|
||||
{
|
||||
mpfr_set_zero(x, 1);
|
||||
mpfr_nextabove(x);
|
||||
}
|
||||
else
|
||||
{
|
||||
mpfr_set_zero(x, -1);
|
||||
mpfr_nextbelow(x);
|
||||
}
|
||||
|
||||
r = mpfr_mul_2si(x, x, -1, rnd);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -46,6 +46,7 @@ int main()
|
|||
{
|
||||
arf_t x, y, z;
|
||||
int conversion_error;
|
||||
FILE* tmp;
|
||||
|
||||
arf_init(x);
|
||||
arf_init(y);
|
||||
|
@ -55,7 +56,7 @@ int main()
|
|||
arf_randtest_special(y, state, 1 + n_randint(state, 1000), 1 + n_randint(state, 100));
|
||||
arf_randtest_special(z, state, 1 + n_randint(state, 1000), 1 + n_randint(state, 100));
|
||||
|
||||
FILE* tmp = tmpfile();
|
||||
tmp = tmpfile();
|
||||
arf_dump_file(tmp, x);
|
||||
fputc(' ', tmp);
|
||||
arf_dump_file(tmp, y);
|
||||
|
|
|
@ -50,6 +50,88 @@ int main()
|
|||
mpfr_clear(y);
|
||||
}
|
||||
|
||||
/* test set_mpfr out of range */
|
||||
{
|
||||
arf_t x, z;
|
||||
mpfr_t y;
|
||||
fmpz_t e;
|
||||
int r;
|
||||
|
||||
fmpz_init(e);
|
||||
arf_init(x);
|
||||
arf_init(z);
|
||||
mpfr_init2(y, 53);
|
||||
fmpz_one(e);
|
||||
fmpz_mul_2exp(e, e, 100);
|
||||
|
||||
arf_set_si(x, 1);
|
||||
arf_mul_2exp_fmpz(x, x, e);
|
||||
r = arf_get_mpfr(y, x, MPFR_RNDN);
|
||||
arf_set_mpfr(x, y);
|
||||
|
||||
if (!mpfr_inf_p(y) || mpfr_sgn(y) <= 0 || !mpfr_overflow_p())
|
||||
{
|
||||
flint_printf("expected +inf with overflow\n\n");
|
||||
arf_print(z); flint_printf("\n\n");
|
||||
flint_printf("r = %d \n\n", r);
|
||||
flint_abort();
|
||||
}
|
||||
|
||||
mpfr_clear_flags();
|
||||
|
||||
arf_set_si(x, -1);
|
||||
arf_mul_2exp_fmpz(x, x, e);
|
||||
r = arf_get_mpfr(y, x, MPFR_RNDN);
|
||||
arf_set_mpfr(x, y);
|
||||
|
||||
if (!mpfr_inf_p(y) || mpfr_sgn(y) >= 0 || !mpfr_overflow_p())
|
||||
{
|
||||
flint_printf("expected -inf with overflow\n\n");
|
||||
arf_print(z); flint_printf("\n\n");
|
||||
flint_printf("r = %d \n\n", r);
|
||||
flint_abort();
|
||||
}
|
||||
|
||||
mpfr_clear_flags();
|
||||
|
||||
fmpz_neg(e, e);
|
||||
|
||||
arf_set_si(x, 1);
|
||||
arf_mul_2exp_fmpz(x, x, e);
|
||||
r = arf_get_mpfr(y, x, MPFR_RNDN);
|
||||
arf_set_mpfr(x, y);
|
||||
|
||||
if (!mpfr_zero_p(y) || mpfr_signbit(y) || !mpfr_underflow_p())
|
||||
{
|
||||
flint_printf("expected +0 with underflow\n\n");
|
||||
arf_print(z); flint_printf("\n\n");
|
||||
flint_printf("r = %d \n\n", r);
|
||||
flint_abort();
|
||||
}
|
||||
|
||||
mpfr_clear_flags();
|
||||
|
||||
arf_set_si(x, -1);
|
||||
arf_mul_2exp_fmpz(x, x, e);
|
||||
r = arf_get_mpfr(y, x, MPFR_RNDN);
|
||||
arf_set_mpfr(x, y);
|
||||
|
||||
if (!mpfr_zero_p(y) || !mpfr_signbit(y) || !mpfr_underflow_p())
|
||||
{
|
||||
flint_printf("expected -0 with underflow\n\n");
|
||||
arf_print(z); flint_printf("\n\n");
|
||||
flint_printf("r = %d \n\n", r);
|
||||
flint_abort();
|
||||
}
|
||||
|
||||
mpfr_clear_flags();
|
||||
|
||||
arf_clear(x);
|
||||
arf_clear(z);
|
||||
mpfr_clear(y);
|
||||
fmpz_clear(e);
|
||||
}
|
||||
|
||||
flint_randclear(state);
|
||||
flint_cleanup();
|
||||
flint_printf("PASS\n");
|
||||
|
|
|
@ -267,6 +267,10 @@ Assignment, rounding and conversions
|
|||
indicates the direction of rounding, following the convention
|
||||
of the MPFR library.
|
||||
|
||||
If *x* has an exponent too large or small to fit in the MPFR type, the
|
||||
result overflows to an infinity or underflows to a (signed) zero,
|
||||
and the corresponding MPFR exception flags are set.
|
||||
|
||||
.. function:: int arf_get_fmpz(fmpz_t res, const arf_t x, arf_rnd_t rnd)
|
||||
|
||||
Sets *res* to *x* rounded to the nearest integer in the direction
|
||||
|
|
Loading…
Add table
Reference in a new issue