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) else if (rnd == ARF_RND_NEAR)
{ {
bc = exp - val;
/* If exactly one excess bit, there is a tie; the rounding /* If exactly one excess bit, there is a tie; the rounding
direction is determined by the bit to the left of the direction is determined by the bit to the left of the
truncation point. */ truncation point. */
if (bc - 1 == prec) if (exp - val - 1 == prec)
{ {
increment = (x[val_limbs] >> val_bits) & 1; increment = (x[val_limbs] >> val_bits) & 1;
} }

View file

@ -28,23 +28,31 @@
int int
arf_mul_naive(arf_t z, const arf_t x, const arf_t y, slong prec, arf_rnd_t rnd) arf_mul_naive(arf_t z, const arf_t x, const arf_t y, slong prec, arf_rnd_t rnd)
{ {
fmpr_t a, b; if (rnd == ARF_RND_NEAR)
slong r; {
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(a);
fmpr_init(b); fmpr_init(b);
arf_get_fmpr(a, x); arf_get_fmpr(a, x);
arf_get_fmpr(b, y); 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(a);
fmpr_clear(b); fmpr_clear(b);
return (r == FMPR_RESULT_EXACT) ? 0 : 1; return (r == FMPR_RESULT_EXACT) ? 0 : 1;
}
} }
int main() int main()
@ -77,12 +85,13 @@ int main()
if (n_randint(state, 50) == 0) if (n_randint(state, 50) == 0)
prec = ARF_PREC_EXACT; prec = ARF_PREC_EXACT;
switch (n_randint(state, 4)) switch (n_randint(state, 5))
{ {
case 0: rnd = ARF_RND_DOWN; break; case 0: rnd = ARF_RND_DOWN; break;
case 1: rnd = ARF_RND_UP; break; case 1: rnd = ARF_RND_UP; break;
case 2: rnd = ARF_RND_FLOOR; 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)) switch (n_randint(state, 5))

View file

@ -68,12 +68,13 @@ int main()
if (n_randint(state, 10)) if (n_randint(state, 10))
prec = ARF_PREC_EXACT; prec = ARF_PREC_EXACT;
switch (n_randint(state, 4)) switch (n_randint(state, 5))
{ {
case 0: rnd = ARF_RND_DOWN; break; case 0: rnd = ARF_RND_DOWN; break;
case 1: rnd = ARF_RND_UP; break; case 1: rnd = ARF_RND_UP; break;
case 2: rnd = ARF_RND_FLOOR; 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)) switch (n_randint(state, 2))

View file

@ -68,12 +68,13 @@ int main()
if (n_randint(state, 10) == 0) if (n_randint(state, 10) == 0)
prec = ARF_PREC_EXACT; prec = ARF_PREC_EXACT;
switch (n_randint(state, 4)) switch (n_randint(state, 5))
{ {
case 0: rnd = ARF_RND_DOWN; break; case 0: rnd = ARF_RND_DOWN; break;
case 1: rnd = ARF_RND_UP; break; case 1: rnd = ARF_RND_UP; break;
case 2: rnd = ARF_RND_FLOOR; 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)) switch (n_randint(state, 2))

View file

@ -68,12 +68,13 @@ int main()
if (n_randint(state, 10) == 0) if (n_randint(state, 10) == 0)
prec = ARF_PREC_EXACT; prec = ARF_PREC_EXACT;
switch (n_randint(state, 4)) switch (n_randint(state, 5))
{ {
case 0: rnd = ARF_RND_DOWN; break; case 0: rnd = ARF_RND_DOWN; break;
case 1: rnd = ARF_RND_UP; break; case 1: rnd = ARF_RND_UP; break;
case 2: rnd = ARF_RND_FLOOR; 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)) switch (n_randint(state, 2))

View file

@ -28,23 +28,31 @@
int int
arf_mul_naive(arf_t z, const arf_t x, const arf_t y, slong prec, arf_rnd_t rnd) arf_mul_naive(arf_t z, const arf_t x, const arf_t y, slong prec, arf_rnd_t rnd)
{ {
fmpr_t a, b; if (rnd == ARF_RND_NEAR)
slong r; {
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(a);
fmpr_init(b); fmpr_init(b);
arf_get_fmpr(a, x); arf_get_fmpr(a, x);
arf_get_fmpr(b, y); 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(a);
fmpr_clear(b); fmpr_clear(b);
return (r == FMPR_RESULT_EXACT) ? 0 : 1; return (r == FMPR_RESULT_EXACT) ? 0 : 1;
}
} }
int main() int main()
@ -77,12 +85,13 @@ int main()
if (n_randint(state, 50) == 0) if (n_randint(state, 50) == 0)
prec = ARF_PREC_EXACT; prec = ARF_PREC_EXACT;
switch (n_randint(state, 4)) switch (n_randint(state, 5))
{ {
case 0: rnd = ARF_RND_DOWN; break; case 0: rnd = ARF_RND_DOWN; break;
case 1: rnd = ARF_RND_UP; break; case 1: rnd = ARF_RND_UP; break;
case 2: rnd = ARF_RND_FLOOR; 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)) 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*, Sets `z = x \times y`, rounded to *prec* bits in the direction specified by *rnd*,
returning nonzero iff the operation is inexact. 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) .. function:: int arf_add(arf_t z, const arf_t x, const arf_t y, slong prec, arf_rnd_t rnd)