Skip to content

Commit

Permalink
Positive * pos_inf should be pos_inf, not 0 +- inf. Same for other co…
Browse files Browse the repository at this point in the history
…mbinations of signs. This addresses github issue flintlib#408.
  • Loading branch information
postmath committed Mar 12, 2022
1 parent 076249e commit 89b489e
Show file tree
Hide file tree
Showing 7 changed files with 139 additions and 27 deletions.
21 changes: 21 additions & 0 deletions arb/addmul.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,13 @@ arb_addmul_arf(arb_t z, const arb_t x, const arf_t y, slong prec)
if (inexact)
arf_mag_add_ulp(arb_radref(z), arb_radref(z), arb_midref(z), prec);
}
else if (arf_is_inf(y) && arb_is_nonzero(x))
{
if (arf_sgn(arb_midref(x)) > 0)
arb_add_arf(z, z, y, prec);
else
arb_sub_arf(z, z, y, prec);
}
else if (ARB_IS_LAGOM(x) && ARF_IS_LAGOM(y) && ARB_IS_LAGOM(z))
{
mag_fast_init_set_arf(ym, y);
Expand Down Expand Up @@ -60,6 +67,20 @@ arb_addmul(arb_t z, const arb_t x, const arb_t y, slong prec)
{
arb_addmul_arf(z, y, arb_midref(x), prec);
}
else if (arf_is_inf(arb_midref(x)) && mag_is_finite(arb_radref(x)) && arb_is_nonzero(y))
{
if (arf_sgn(arb_midref(y)) > 0)
arb_add_arf(z, z, arb_midref(x), prec);
else
arb_sub_arf(z, z, arb_midref(x), prec);
}
else if (arf_is_inf(arb_midref(y)) && mag_is_finite(arb_radref(y)) && arb_is_nonzero(x))
{
if (arf_sgn(arb_midref(x)) > 0)
arb_add_arf(z, z, arb_midref(y), prec);
else
arb_sub_arf(z, z, arb_midref(y), prec);
}
else if (ARB_IS_LAGOM(x) && ARB_IS_LAGOM(y) && ARB_IS_LAGOM(z))
{
mag_fast_init_set_arf(xm, arb_midref(x));
Expand Down
21 changes: 21 additions & 0 deletions arb/fma.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,13 @@ arb_fma_arf(arb_t res, const arb_t x, const arf_t y, const arb_t z, slong prec)
else
mag_set(arb_radref(res), arb_radref(z));
}
else if (arf_is_inf(y) && arb_is_nonzero(x))
{
if (arf_sgn(arb_midref(x)) > 0)
arb_add_arf(res, z, y, prec);
else
arb_sub_arf(res, z, y, prec);
}
else if (ARB_IS_LAGOM(res) && ARB_IS_LAGOM(x) && ARF_IS_LAGOM(y) && ARB_IS_LAGOM(z))
{
mag_t tm;
Expand Down Expand Up @@ -73,6 +80,20 @@ arb_fma(arb_t res, const arb_t x, const arb_t y, const arb_t z, slong prec)
{
arb_fma_arf(res, y, arb_midref(x), z, prec);
}
else if (arf_is_inf(arb_midref(x)) && mag_is_finite(arb_radref(x)) && arb_is_nonzero(y))
{
if (arf_sgn(arb_midref(y)) > 0)
arb_add_arf(res, z, arb_midref(x), prec);
else
arb_sub_arf(res, z, arb_midref(x), prec);
}
else if (arf_is_inf(arb_midref(y)) && mag_is_finite(arb_radref(y)) && arb_is_nonzero(x))
{
if (arf_sgn(arb_midref(x)) > 0)
arb_add_arf(res, z, arb_midref(y), prec);
else
arb_sub_arf(res, z, arb_midref(y), prec);
}
else if (ARB_IS_LAGOM(res) && ARB_IS_LAGOM(x) && ARB_IS_LAGOM(y) && ARB_IS_LAGOM(z))
{
mag_fast_init_set_arf(xm, arb_midref(x));
Expand Down
19 changes: 19 additions & 0 deletions arb/mul.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,15 @@ arb_mul_arf(arb_t z, const arb_t x, const arf_t y, slong prec)
else
mag_zero(arb_radref(z));
}
else if (arf_is_inf(y) && arb_is_nonzero(x))
{
mag_zero(arb_radref(z));

if (arf_sgn(arb_midref(x)) * arf_sgn(y) > 0)
arf_pos_inf(arb_midref(z));
else
arf_neg_inf(arb_midref(z));
}
else if (ARB_IS_LAGOM(x) && ARF_IS_LAGOM(y) && ARB_IS_LAGOM(z))
{
mag_fast_init_set_arf(ym, y);
Expand Down Expand Up @@ -74,6 +83,16 @@ arb_mul(arb_t z, const arb_t x, const arb_t y, slong prec)
{
arb_mul_arf(z, x, arb_midref(y), prec);
}
else if (arf_is_inf(arb_midref(x)) && mag_is_finite(arb_radref(x)) && arb_is_nonzero(y) ||
arf_is_inf(arb_midref(y)) && mag_is_finite(arb_radref(y)) && arb_is_nonzero(x))
{
mag_zero(arb_radref(z));

if (arf_sgn(arb_midref(x)) * arf_sgn(arb_midref(y)) > 0)
arf_pos_inf(arb_midref(z));
else
arf_neg_inf(arb_midref(z));
}
else if (ARB_IS_LAGOM(x) && ARB_IS_LAGOM(y) && ARB_IS_LAGOM(z))
{
mag_fast_init_set_arf(xm, arb_midref(x));
Expand Down
21 changes: 21 additions & 0 deletions arb/submul.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,13 @@ arb_submul_arf(arb_t z, const arb_t x, const arf_t y, slong prec)
if (inexact)
arf_mag_add_ulp(arb_radref(z), arb_radref(z), arb_midref(z), prec);
}
else if (arf_is_inf(y) && arb_is_nonzero(x))
{
if (arf_sgn(arb_midref(x)) > 0)
arb_sub_arf(z, z, y, prec);
else
arb_add_arf(z, z, y, prec);
}
else if (ARB_IS_LAGOM(x) && ARF_IS_LAGOM(y) && ARB_IS_LAGOM(z))
{
mag_fast_init_set_arf(ym, y);
Expand Down Expand Up @@ -60,6 +67,20 @@ arb_submul(arb_t z, const arb_t x, const arb_t y, slong prec)
{
arb_submul_arf(z, y, arb_midref(x), prec);
}
else if (arf_is_inf(arb_midref(x)) && mag_is_finite(arb_radref(x)) && arb_is_nonzero(y))
{
if (arf_sgn(arb_midref(y)) > 0)
arb_sub_arf(z, z, arb_midref(x), prec);
else
arb_add_arf(z, z, arb_midref(x), prec);
}
else if (arf_is_inf(arb_midref(y)) && mag_is_finite(arb_radref(y)) && arb_is_nonzero(x))
{
if (arf_sgn(arb_midref(x)) > 0)
arb_sub_arf(z, z, arb_midref(y), prec);
else
arb_add_arf(z, z, arb_midref(y), prec);
}
else if (ARB_IS_LAGOM(x) && ARB_IS_LAGOM(y) && ARB_IS_LAGOM(z))
{
mag_fast_init_set_arf(xm, arb_midref(x));
Expand Down
28 changes: 18 additions & 10 deletions arb/test/t-addmul.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,19 @@ mag_close(const mag_t am, const mag_t bm)
return res1 && res2;
}

int
arb_equal_mid_close_mag(const arb_t a, const arb_t b)
{
return arf_equal(arb_midref(a), arb_midref(b)) &&
(mag_close(arb_radref(a), arb_radref(b)) ||
/* If a's and b's centres are infinite but their radii are finite, the radii don't need
to be close: they represent signed infinity regardless. If their centres are NaN,
then we should ignore their radii. */
(arf_is_inf(arb_midref(a)) && arf_is_inf(arb_midref(b)) &&
mag_is_finite(arb_radref(a)) && mag_is_finite(arb_radref(b))) ||
(arf_is_nan(arb_midref(a)) && arf_is_nan(arb_midref(b))));
}

void
arb_addmul_naive(arb_t z, const arb_t x, const arb_t y, slong prec)
{
Expand Down Expand Up @@ -214,8 +227,7 @@ int main()
arb_addmul(z, x, y, prec);
arb_addmul_naive(v, x, y, prec);

if (!arf_equal(arb_midref(z), arb_midref(v))
|| !mag_close(arb_radref(z), arb_radref(v)))
if (!arb_equal_mid_close_mag(z, v))
{
flint_printf("FAIL!\n");
flint_printf("x = "); arb_print(x); flint_printf("\n\n");
Expand All @@ -232,8 +244,7 @@ int main()
arb_addmul(z, x, y, prec);
arb_addmul(v, x, x, prec);

if (!arf_equal(arb_midref(z), arb_midref(v))
|| !mag_close(arb_radref(z), arb_radref(v)))
if (!arb_equal_mid_close_mag(z, v))
{
flint_printf("FAIL (aliasing 1)!\n");
flint_printf("x = "); arb_print(x); flint_printf("\n\n");
Expand All @@ -248,8 +259,7 @@ int main()
arb_addmul(v, x, x, prec);
arb_addmul(x, x, x, prec);

if (!arf_equal(arb_midref(x), arb_midref(v))
|| !mag_close(arb_radref(x), arb_radref(v)))
if (!arb_equal_mid_close_mag(x, v))
{
flint_printf("FAIL (aliasing 2)!\n");
flint_printf("x = "); arb_print(x); flint_printf("\n\n");
Expand All @@ -263,8 +273,7 @@ int main()
arb_addmul(v, x, y, prec);
arb_addmul(x, x, y, prec);

if (!arf_equal(arb_midref(x), arb_midref(v))
|| !mag_close(arb_radref(x), arb_radref(v)))
if (!arb_equal_mid_close_mag(x, v))
{
flint_printf("FAIL (aliasing 3)!\n");
flint_printf("x = "); arb_print(x); flint_printf("\n\n");
Expand All @@ -279,8 +288,7 @@ int main()
arb_addmul(v, x, y, prec);
arb_addmul(x, y, x, prec);

if (!arf_equal(arb_midref(x), arb_midref(v))
|| !mag_close(arb_radref(x), arb_radref(v)))
if (!arb_equal_mid_close_mag(x, v))
{
flint_printf("FAIL (aliasing 4)!\n");
flint_printf("x = "); arb_print(x); flint_printf("\n\n");
Expand Down
28 changes: 21 additions & 7 deletions arb/test/t-mul.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,19 @@ mag_close(const mag_t am, const mag_t bm)
return res1 && res2;
}

int
arb_equal_mid_close_mag(const arb_t a, const arb_t b)
{
return arf_equal(arb_midref(a), arb_midref(b)) &&
(mag_close(arb_radref(a), arb_radref(b)) ||
/* If a's and b's centres are infinite but their radii are finite, the radii don't need
to be close: they represent signed infinity regardless. If their centres are NaN,
then we should ignore their radii. */
(arf_is_inf(arb_midref(a)) && arf_is_inf(arb_midref(b)) &&
mag_is_finite(arb_radref(a)) && mag_is_finite(arb_radref(b))) ||
(arf_is_nan(arb_midref(a)) && arf_is_nan(arb_midref(b))));
}

void
arb_mul_naive(arb_t z, const arb_t x, const arb_t y, slong prec)
{
Expand Down Expand Up @@ -73,15 +86,18 @@ arb_mul_naive(arb_t z, const arb_t x, const arb_t y, slong prec)
fmpz_clear(e);
}

/* propagated error */
if (!arb_is_exact(x))
/* propagated error - note that (signed infinity) * nonzero should be a signed
infinity, meaning the error should *not* propagate */
if (!arb_is_exact(x) && !(
arb_is_nonzero(x) && arf_is_inf(arb_midref(y)) && mag_is_finite(arb_radref(y))))
{
arf_set_mag(t, arb_radref(x));
arf_abs(u, arb_midref(y));
arf_addmul(zr, t, u, MAG_BITS, ARF_RND_UP);
}

if (!arb_is_exact(y))
if (!arb_is_exact(y) && !(
arb_is_nonzero(y) && arf_is_inf(arb_midref(x)) && mag_is_finite(arb_radref(x))))
{
arf_set_mag(t, arb_radref(y));
arf_abs(u, arb_midref(x));
Expand Down Expand Up @@ -265,8 +281,7 @@ int main()
arb_mul(z, x, y, prec);
arb_mul_naive(v, x, y, prec);

if (!arf_equal(arb_midref(z), arb_midref(v))
|| !mag_close(arb_radref(z), arb_radref(v)))
if (!arb_equal_mid_close_mag(z, v))
{
flint_printf("FAIL!\n");
flint_printf("x = "); arb_print(x); flint_printf("\n\n");
Expand All @@ -282,8 +297,7 @@ int main()
arb_mul(z, x, y, prec);
arb_mul(v, x, x, prec);

if (!arf_equal(arb_midref(z), arb_midref(v))
|| !mag_close(arb_radref(z), arb_radref(v)))
if (!arb_equal_mid_close_mag(z, v))
{
flint_printf("FAIL (aliasing 1)!\n");
flint_printf("x = "); arb_print(x); flint_printf("\n\n");
Expand Down
28 changes: 18 additions & 10 deletions arb/test/t-submul.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,19 @@ mag_close(const mag_t am, const mag_t bm)
return res1 && res2;
}

int
arb_equal_mid_close_mag(const arb_t a, const arb_t b)
{
return arf_equal(arb_midref(a), arb_midref(b)) &&
(mag_close(arb_radref(a), arb_radref(b)) ||
/* If a's and b's centres are infinite but their radii are finite, the radii don't need
to be close: they represent signed infinity regardless. If their centres are NaN,
then we should ignore their radii. */
(arf_is_inf(arb_midref(a)) && arf_is_inf(arb_midref(b)) &&
mag_is_finite(arb_radref(a)) && mag_is_finite(arb_radref(b))) ||
(arf_is_nan(arb_midref(a)) && arf_is_nan(arb_midref(b))));
}

void
arb_submul_naive(arb_t z, const arb_t x, const arb_t y, slong prec)
{
Expand Down Expand Up @@ -214,8 +227,7 @@ int main()
arb_submul(z, x, y, prec);
arb_submul_naive(v, x, y, prec);

if (!arf_equal(arb_midref(z), arb_midref(v))
|| !mag_close(arb_radref(z), arb_radref(v)))
if (!arb_equal_mid_close_mag(z, v))
{
flint_printf("FAIL!\n");
flint_printf("x = "); arb_print(x); flint_printf("\n\n");
Expand All @@ -232,8 +244,7 @@ int main()
arb_submul(z, x, y, prec);
arb_submul(v, x, x, prec);

if (!arf_equal(arb_midref(z), arb_midref(v))
|| !mag_close(arb_radref(z), arb_radref(v)))
if (!arb_equal_mid_close_mag(z, v))
{
flint_printf("FAIL (aliasing 1)!\n");
flint_printf("x = "); arb_print(x); flint_printf("\n\n");
Expand All @@ -248,8 +259,7 @@ int main()
arb_submul(v, x, x, prec);
arb_submul(x, x, x, prec);

if (!arf_equal(arb_midref(x), arb_midref(v))
|| !mag_close(arb_radref(x), arb_radref(v)))
if (!arb_equal_mid_close_mag(x, v))
{
flint_printf("FAIL (aliasing 2)!\n");
flint_printf("x = "); arb_print(x); flint_printf("\n\n");
Expand All @@ -263,8 +273,7 @@ int main()
arb_submul(v, x, y, prec);
arb_submul(x, x, y, prec);

if (!arf_equal(arb_midref(x), arb_midref(v))
|| !mag_close(arb_radref(x), arb_radref(v)))
if (!arb_equal_mid_close_mag(x, v))
{
flint_printf("FAIL (aliasing 3)!\n");
flint_printf("x = "); arb_print(x); flint_printf("\n\n");
Expand All @@ -279,8 +288,7 @@ int main()
arb_submul(v, x, y, prec);
arb_submul(x, y, x, prec);

if (!arf_equal(arb_midref(x), arb_midref(v))
|| !mag_close(arb_radref(x), arb_radref(v)))
if (!arb_equal_mid_close_mag(x, v))
{
flint_printf("FAIL (aliasing 4)!\n");
flint_printf("x = "); arb_print(x); flint_printf("\n\n");
Expand Down

0 comments on commit 89b489e

Please sign in to comment.