summaryrefslogtreecommitdiff
path: root/mpf
diff options
context:
space:
mode:
authortege <tege@gmplib.org>2000-06-29 17:41:25 +0200
committertege <tege@gmplib.org>2000-06-29 17:41:25 +0200
commitbf8a7583b815d456dfd84be4582e251057990fb3 (patch)
tree85c01a06cf8f0321c3b0138de261f63a73793787 /mpf
parent428c82548bb8cd90bf9d02470e7520e2d441e57e (diff)
downloadgmp-bf8a7583b815d456dfd84be4582e251057990fb3.tar.gz
Streamline criterion for whether to use mpn_lshift or
mpn_rshift. Increase precision when exp is a multiple of BITS_PER_MP_LIMB primarily to make exp==0 be a noop.
Diffstat (limited to 'mpf')
-rw-r--r--mpf/div_2exp.c33
-rw-r--r--mpf/mul_2exp.c39
2 files changed, 41 insertions, 31 deletions
diff --git a/mpf/div_2exp.c b/mpf/div_2exp.c
index 3964fa879..827d34262 100644
--- a/mpf/div_2exp.c
+++ b/mpf/div_2exp.c
@@ -51,38 +51,43 @@ mpf_div_2exp (r, u, exp)
abs_usize = ABS (usize);
up = u->_mp_d;
- if (abs_usize > prec)
- {
- up += abs_usize - prec;
- abs_usize = prec;
- }
-
if (exp % BITS_PER_MP_LIMB == 0)
{
+ prec++; /* retain more precision here as we don't need
+ to account for carry-out here */
+ if (abs_usize > prec)
+ {
+ up += abs_usize - prec;
+ abs_usize = prec;
+ }
if (rp != up)
MPN_COPY_INCR (rp, up, abs_usize);
r->_mp_exp = uexp - exp / BITS_PER_MP_LIMB;
}
else
{
- /* Use mpn_lshift since mpn_rshift operates upwards, and we therefore
- would clobber part of U before using that part, when R == U. */
mp_limb_t cy_limb;
- if (rp < up)
+ mp_size_t adj;
+ if (abs_usize > prec)
{
+ up += abs_usize - prec;
+ abs_usize = prec;
+ /* Use mpn_rshift since mpn_lshift operates downwards, and we
+ therefore would clobber part of U before using that part, in case
+ R is the same variable as U. */
cy_limb = mpn_rshift (rp + 1, up, abs_usize, exp % BITS_PER_MP_LIMB);
rp[0] = cy_limb;
- cy_limb = rp[abs_usize] != 0;
+ adj = rp[abs_usize] != 0;
}
else
{
- cy_limb = mpn_lshift (rp, up, abs_usize, -exp % BITS_PER_MP_LIMB);
+ cy_limb = mpn_lshift (rp, up, abs_usize, (-exp) % BITS_PER_MP_LIMB);
rp[abs_usize] = cy_limb;
- cy_limb = cy_limb != 0;
+ adj = cy_limb != 0;
}
- abs_usize += cy_limb;
- r->_mp_exp = uexp - exp / BITS_PER_MP_LIMB - 1 + cy_limb;
+ abs_usize += adj;
+ r->_mp_exp = uexp - exp / BITS_PER_MP_LIMB - 1 + adj;
}
r->_mp_size = usize >= 0 ? abs_usize : -abs_usize;
}
diff --git a/mpf/mul_2exp.c b/mpf/mul_2exp.c
index 5b7345866..6f9e1dc75 100644
--- a/mpf/mul_2exp.c
+++ b/mpf/mul_2exp.c
@@ -51,14 +51,15 @@ mpf_mul_2exp (r, u, exp)
abs_usize = ABS (usize);
up = u->_mp_d;
- if (abs_usize > prec)
- {
- up += abs_usize - prec;
- abs_usize = prec;
- }
-
if (exp % BITS_PER_MP_LIMB == 0)
{
+ prec++; /* retain more precision here as we don't need
+ to account for carry-out here */
+ if (abs_usize > prec)
+ {
+ up += abs_usize - prec;
+ abs_usize = prec;
+ }
if (rp != up)
MPN_COPY_INCR (rp, up, abs_usize);
r->_mp_exp = uexp + exp / BITS_PER_MP_LIMB;
@@ -66,23 +67,27 @@ mpf_mul_2exp (r, u, exp)
else
{
mp_limb_t cy_limb;
- if (rp >= up)
+ mp_size_t adj;
+ if (abs_usize > prec)
{
- cy_limb = mpn_lshift (rp, up, abs_usize, exp % BITS_PER_MP_LIMB);
- rp[abs_usize] = cy_limb;
- cy_limb = cy_limb != 0;
+ up += abs_usize - prec;
+ abs_usize = prec;
+ /* Use mpn_rshift since mpn_lshift operates downwards, and we
+ therefore would clobber part of U before using that part, in case
+ R is the same variable as U. */
+ cy_limb = mpn_rshift (rp + 1, up, abs_usize, (-exp) % BITS_PER_MP_LIMB);
+ rp[0] = cy_limb;
+ adj = rp[abs_usize] != 0;
}
else
{
- /* Use mpn_rshift since mpn_lshift operates downwards, and we
- therefore would clobber part of U before using that part. */
- cy_limb = mpn_rshift (rp + 1, up, abs_usize, -exp % BITS_PER_MP_LIMB);
- rp[0] = cy_limb;
- cy_limb = rp[abs_usize] != 0;
+ cy_limb = mpn_lshift (rp, up, abs_usize, exp % BITS_PER_MP_LIMB);
+ rp[abs_usize] = cy_limb;
+ adj = cy_limb != 0;
}
- abs_usize += cy_limb;
- r->_mp_exp = uexp + exp / BITS_PER_MP_LIMB + cy_limb;
+ abs_usize += adj;
+ r->_mp_exp = uexp + exp / BITS_PER_MP_LIMB + adj;
}
r->_mp_size = usize >= 0 ? abs_usize : -abs_usize;
}