support ARF_RND_NEAR in arf_mul_* methods

This commit is contained in:
Fredrik Johansson 2016-04-15 15:27:34 +02:00
parent bbdf4f9c52
commit 16f6ebd87b
7 changed files with 55 additions and 35 deletions

View file

@ -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;
}

View file

@ -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))

View file

@ -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))

View file

@ -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))

View file

@ -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))

View file

@ -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))

View file

@ -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)