diff --git a/arf/set_round_mpn.c b/arf/set_round_mpn.c index 03ba13fa..43aec13b 100644 --- a/arf/set_round_mpn.c +++ b/arf/set_round_mpn.c @@ -79,12 +79,10 @@ _arf_set_round_mpn(arf_t y, slong * exp_shift, mp_srcptr x, mp_size_t xn, } else if (rnd == ARF_RND_NEAR) { - bc = exp - val; - /* If exactly one excess bit, there is a tie; the rounding direction is determined by the bit to the left of the truncation point. */ - if (bc - 1 == prec) + if (exp - val - 1 == prec) { increment = (x[val_limbs] >> val_bits) & 1; } diff --git a/arf/test/t-mul.c b/arf/test/t-mul.c index fbb48415..25f40ed8 100644 --- a/arf/test/t-mul.c +++ b/arf/test/t-mul.c @@ -28,23 +28,31 @@ int arf_mul_naive(arf_t z, const arf_t x, const arf_t y, slong prec, arf_rnd_t rnd) { - fmpr_t a, b; - slong r; + if (rnd == ARF_RND_NEAR) + { + arf_mul(z, x, y, ARF_PREC_EXACT, rnd); + return arf_set_round(z, z, prec, rnd); + } + else + { + fmpr_t a, b; + slong r; - fmpr_init(a); - fmpr_init(b); + fmpr_init(a); + fmpr_init(b); - arf_get_fmpr(a, x); - arf_get_fmpr(b, y); + arf_get_fmpr(a, x); + arf_get_fmpr(b, y); - r = fmpr_mul_naive(a, a, b, prec, rnd); + r = fmpr_mul_naive(a, a, b, prec, rnd); - arf_set_fmpr(z, a); + arf_set_fmpr(z, a); - fmpr_clear(a); - fmpr_clear(b); + fmpr_clear(a); + fmpr_clear(b); - return (r == FMPR_RESULT_EXACT) ? 0 : 1; + return (r == FMPR_RESULT_EXACT) ? 0 : 1; + } } int main() @@ -77,12 +85,13 @@ int main() if (n_randint(state, 50) == 0) prec = ARF_PREC_EXACT; - switch (n_randint(state, 4)) + switch (n_randint(state, 5)) { case 0: rnd = ARF_RND_DOWN; break; case 1: rnd = ARF_RND_UP; break; case 2: rnd = ARF_RND_FLOOR; break; - default: rnd = ARF_RND_CEIL; break; + case 3: rnd = ARF_RND_CEIL; break; + default: rnd = ARF_RND_NEAR; break; } switch (n_randint(state, 5)) diff --git a/arf/test/t-mul_fmpz.c b/arf/test/t-mul_fmpz.c index a962cf58..49b8eeaa 100644 --- a/arf/test/t-mul_fmpz.c +++ b/arf/test/t-mul_fmpz.c @@ -68,12 +68,13 @@ int main() if (n_randint(state, 10)) prec = ARF_PREC_EXACT; - switch (n_randint(state, 4)) + switch (n_randint(state, 5)) { case 0: rnd = ARF_RND_DOWN; break; case 1: rnd = ARF_RND_UP; break; case 2: rnd = ARF_RND_FLOOR; break; - default: rnd = ARF_RND_CEIL; break; + case 3: rnd = ARF_RND_CEIL; break; + default: rnd = ARF_RND_NEAR; break; } switch (n_randint(state, 2)) diff --git a/arf/test/t-mul_si.c b/arf/test/t-mul_si.c index ef4d2589..d4056c27 100644 --- a/arf/test/t-mul_si.c +++ b/arf/test/t-mul_si.c @@ -68,12 +68,13 @@ int main() if (n_randint(state, 10) == 0) prec = ARF_PREC_EXACT; - switch (n_randint(state, 4)) + switch (n_randint(state, 5)) { case 0: rnd = ARF_RND_DOWN; break; case 1: rnd = ARF_RND_UP; break; case 2: rnd = ARF_RND_FLOOR; break; - default: rnd = ARF_RND_CEIL; break; + case 3: rnd = ARF_RND_CEIL; break; + default: rnd = ARF_RND_NEAR; break; } switch (n_randint(state, 2)) diff --git a/arf/test/t-mul_ui.c b/arf/test/t-mul_ui.c index 12bf9716..c65db963 100644 --- a/arf/test/t-mul_ui.c +++ b/arf/test/t-mul_ui.c @@ -68,12 +68,13 @@ int main() if (n_randint(state, 10) == 0) prec = ARF_PREC_EXACT; - switch (n_randint(state, 4)) + switch (n_randint(state, 5)) { case 0: rnd = ARF_RND_DOWN; break; case 1: rnd = ARF_RND_UP; break; case 2: rnd = ARF_RND_FLOOR; break; - default: rnd = ARF_RND_CEIL; break; + case 3: rnd = ARF_RND_CEIL; break; + default: rnd = ARF_RND_NEAR; break; } switch (n_randint(state, 2)) diff --git a/arf/test/t-mul_via_mpfr.c b/arf/test/t-mul_via_mpfr.c index b5262d63..9d2182b6 100644 --- a/arf/test/t-mul_via_mpfr.c +++ b/arf/test/t-mul_via_mpfr.c @@ -28,23 +28,31 @@ int arf_mul_naive(arf_t z, const arf_t x, const arf_t y, slong prec, arf_rnd_t rnd) { - fmpr_t a, b; - slong r; + if (rnd == ARF_RND_NEAR) + { + arf_mul(z, x, y, ARF_PREC_EXACT, rnd); + return arf_set_round(z, z, prec, rnd); + } + else + { + fmpr_t a, b; + slong r; - fmpr_init(a); - fmpr_init(b); + fmpr_init(a); + fmpr_init(b); - arf_get_fmpr(a, x); - arf_get_fmpr(b, y); + arf_get_fmpr(a, x); + arf_get_fmpr(b, y); - r = fmpr_mul_naive(a, a, b, prec, rnd); + r = fmpr_mul_naive(a, a, b, prec, rnd); - arf_set_fmpr(z, a); + arf_set_fmpr(z, a); - fmpr_clear(a); - fmpr_clear(b); + fmpr_clear(a); + fmpr_clear(b); - return (r == FMPR_RESULT_EXACT) ? 0 : 1; + return (r == FMPR_RESULT_EXACT) ? 0 : 1; + } } int main() @@ -77,12 +85,13 @@ int main() if (n_randint(state, 50) == 0) prec = ARF_PREC_EXACT; - switch (n_randint(state, 4)) + switch (n_randint(state, 5)) { case 0: rnd = ARF_RND_DOWN; break; case 1: rnd = ARF_RND_UP; break; case 2: rnd = ARF_RND_FLOOR; break; - default: rnd = ARF_RND_CEIL; break; + case 3: rnd = ARF_RND_CEIL; break; + default: rnd = ARF_RND_NEAR; break; } switch (n_randint(state, 5)) diff --git a/doc/source/arf.rst b/doc/source/arf.rst index 8e8f752a..5f1d04ca 100644 --- a/doc/source/arf.rst +++ b/doc/source/arf.rst @@ -529,6 +529,7 @@ Addition and multiplication Sets `z = x \times y`, rounded to *prec* bits in the direction specified by *rnd*, returning nonzero iff the operation is inexact. + These methods support *ARF_RND_NEAR*. .. function:: int arf_add(arf_t z, const arf_t x, const arf_t y, slong prec, arf_rnd_t rnd)