diff options
author | tege <tege@gmplib.org> | 1996-05-08 09:42:34 +0200 |
---|---|---|
committer | tege <tege@gmplib.org> | 1996-05-08 09:42:34 +0200 |
commit | 1b3800a70cb14a22a458594f31c896f7b7a42f93 (patch) | |
tree | 0ebf847260f4765d5411fded355fe7673fc0f571 /mpf/ui_div.c | |
parent | 3dacca0bd7a2b73ff2d074ce18cdd3a78336ddf4 (diff) | |
download | gmp-1b3800a70cb14a22a458594f31c896f7b7a42f93.tar.gz |
Changes from tiny.
Diffstat (limited to 'mpf/ui_div.c')
-rw-r--r-- | mpf/ui_div.c | 97 |
1 files changed, 56 insertions, 41 deletions
diff --git a/mpf/ui_div.c b/mpf/ui_div.c index 5ec4d1c9e..a49a95204 100644 --- a/mpf/ui_div.c +++ b/mpf/ui_div.c @@ -25,92 +25,107 @@ MA 02111-1307, USA. */ void #if __STDC__ -mpf_ui_div (mpf_ptr r, unsigned long int dividend, mpf_srcptr v) +mpf_ui_div (mpf_ptr r, unsigned long int u, mpf_srcptr v) #else -mpf_ui_div (r, dividend, v) +mpf_ui_div (r, u, v) mpf_ptr r; - unsigned long int dividend; + unsigned long int u; mpf_srcptr v; #endif { - mp_ptr up, vp; - mp_ptr rp; - mp_size_t usize, vsize, rsize; - mp_size_t abs_vsize; + mp_srcptr vp; + mp_ptr rp, tp; + mp_size_t vsize; + mp_size_t rsize, tsize; + mp_size_t sign_quotient; mp_size_t prec; unsigned normalization_steps; - mp_limb_t qlimb; + mp_limb_t q_limb; mp_exp_t rexp; TMP_DECL (marker); - TMP_MARK (marker); + vsize = v->_mp_size; + sign_quotient = vsize; + vsize = ABS (vsize); prec = r->_mp_prec; - rp = r->_mp_d; - vp = v->_mp_d; + if (vsize == 0) + vsize = 1 / vsize; /* divide by zero as directed */ + if (u == 0) + { + r->_mp_size = 0; + r->_mp_exp = 0; + return; + } + + TMP_MARK (marker); rexp = 1 - v->_mp_exp; - vsize = v->_mp_size; - abs_vsize = ABS (vsize); - usize = abs_vsize + prec; - up = (mp_ptr) TMP_ALLOC ((usize + 1) * BYTES_PER_MP_LIMB); - MPN_ZERO (up, usize); + rp = r->_mp_d; + vp = v->_mp_d; + + if (vsize > prec) + { + vp += vsize - prec; + vsize = prec; + } - count_leading_zeros (normalization_steps, vp[abs_vsize - 1]); + tsize = vsize + prec; + tp = (mp_ptr) TMP_ALLOC ((tsize + 1) * BYTES_PER_MP_LIMB); + MPN_ZERO (tp, tsize); - /* Normalize the denominator and the numerator. */ + count_leading_zeros (normalization_steps, vp[vsize - 1]); + + /* Normalize the divisor and the dividend. */ if (normalization_steps != 0) { - mp_ptr tp; + mp_ptr tmp; mp_limb_t dividend_high, dividend_low; /* Shift up the divisor setting the most significant bit of the most significant limb. Use temporary storage not to clobber the original contents of the divisor. */ - tp = (mp_ptr) TMP_ALLOC (abs_vsize * BYTES_PER_MP_LIMB); - mpn_lshift (tp, vp, abs_vsize, normalization_steps); - vp = tp; + tmp = (mp_ptr) TMP_ALLOC (vsize * BYTES_PER_MP_LIMB); + mpn_lshift (tmp, vp, vsize, normalization_steps); + vp = tmp; /* Shift up the dividend, possibly introducing a new most significant word. */ - dividend_high = (mp_limb_t) dividend >> (BITS_PER_MP_LIMB - normalization_steps); - dividend_low = (mp_limb_t) dividend << normalization_steps; + dividend_high = (mp_limb_t) u >> (BITS_PER_MP_LIMB - normalization_steps); + dividend_low = (mp_limb_t) u << normalization_steps; + tp[tsize - 1] = dividend_low; if (dividend_high != 0) { - up[usize] = dividend_high; - up[usize - 1] = dividend_low; + tp[tsize] = dividend_high; + tsize++; rexp++; } - else - { - usize--; - up[usize] = dividend_low; - } } else { /* The divisor is already normalized, as required. Copy it to temporary space if it overlaps with the quotient. */ - if (vp == rp) + if (vp - rp <= tsize - vsize) { - vp = (mp_ptr) TMP_ALLOC (abs_vsize * BYTES_PER_MP_LIMB); - MPN_COPY (vp, rp, abs_vsize); + mp_ptr tmp = (mp_ptr) TMP_ALLOC (vsize * BYTES_PER_MP_LIMB); + MPN_COPY (tmp, vp, vsize); + vp = (mp_srcptr) tmp; } - usize--; - up[usize] = dividend; + tp[tsize - 1] = u; } - qlimb = mpn_divmod (rp, up, usize + 1, vp, abs_vsize); - rsize = usize + 1 - abs_vsize; - if (qlimb) + q_limb = mpn_divmod (rp, tp, tsize, vp, vsize); + rsize = tsize - vsize; + if (q_limb) { - rp[rsize] = qlimb; + rp[rsize] = q_limb; rsize++; rexp++; } - r->_mp_size = vsize >= 0 ? rsize : -rsize; + + r->_mp_size = sign_quotient >= 0 ? rsize : -rsize; r->_mp_exp = rexp; TMP_FREE (marker); } |