Annotation of OpenXM_contrib/gmp/mpz/dmincl.c, Revision 1.1
1.1 ! maekawa 1: /* dmincl.c -- include file for tdiv_qr.c, tdiv_r.c.
! 2:
! 3: Copyright (C) 1991, 1993, 1994, 1996 Free Software Foundation, Inc.
! 4:
! 5: This file is part of the GNU MP Library.
! 6:
! 7: The GNU MP Library is free software; you can redistribute it and/or modify
! 8: it under the terms of the GNU Library General Public License as published by
! 9: the Free Software Foundation; either version 2 of the License, or (at your
! 10: option) any later version.
! 11:
! 12: The GNU MP Library is distributed in the hope that it will be useful, but
! 13: WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
! 14: or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
! 15: License for more details.
! 16:
! 17: You should have received a copy of the GNU Library General Public License
! 18: along with the GNU MP Library; see the file COPYING.LIB. If not, write to
! 19: the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
! 20: MA 02111-1307, USA. */
! 21:
! 22: /* If den == quot, den needs temporary storage.
! 23: If den == rem, den needs temporary storage.
! 24: If num == quot, num needs temporary storage.
! 25: If den has temporary storage, it can be normalized while being copied,
! 26: i.e no extra storage should be allocated. */
! 27:
! 28: /* This is the function body of mdiv, mpz_divmod, and mpz_mod.
! 29:
! 30: If COMPUTE_QUOTIENT is defined, the quotient is put in the MP_INT
! 31: object quot, otherwise that variable is not referenced at all.
! 32:
! 33: The remainder is always computed, and the result is put in the MP_INT
! 34: object rem. */
! 35:
! 36: {
! 37: mp_ptr np, dp;
! 38: mp_ptr qp, rp;
! 39: mp_size_t nsize = num->_mp_size;
! 40: mp_size_t dsize = den->_mp_size;
! 41: mp_size_t qsize, rsize;
! 42: mp_size_t sign_remainder = nsize;
! 43: #ifdef COMPUTE_QUOTIENT
! 44: mp_size_t sign_quotient = nsize ^ dsize;
! 45: #endif
! 46: unsigned normalization_steps;
! 47: mp_limb_t q_limb;
! 48: TMP_DECL (marker);
! 49:
! 50: nsize = ABS (nsize);
! 51: dsize = ABS (dsize);
! 52:
! 53: /* Ensure space is enough for quotient and remainder. */
! 54:
! 55: /* We need space for an extra limb in the remainder, because it's
! 56: up-shifted (normalized) below. */
! 57: rsize = nsize + 1;
! 58: if (rem->_mp_alloc < rsize)
! 59: _mpz_realloc (rem, rsize);
! 60:
! 61: qsize = rsize - dsize; /* qsize cannot be bigger than this. */
! 62: if (qsize <= 0)
! 63: {
! 64: if (num != rem)
! 65: {
! 66: rem->_mp_size = num->_mp_size;
! 67: MPN_COPY (rem->_mp_d, num->_mp_d, nsize);
! 68: }
! 69: #ifdef COMPUTE_QUOTIENT
! 70: /* This needs to follow the assignment to rem, in case the
! 71: numerator and quotient are the same. */
! 72: quot->_mp_size = 0;
! 73: #endif
! 74: return;
! 75: }
! 76:
! 77: #ifdef COMPUTE_QUOTIENT
! 78: if (quot->_mp_alloc < qsize)
! 79: _mpz_realloc (quot, qsize);
! 80: #endif
! 81:
! 82: /* Read pointers here, when reallocation is finished. */
! 83: np = num->_mp_d;
! 84: dp = den->_mp_d;
! 85: rp = rem->_mp_d;
! 86:
! 87: /* Optimize division by a single-limb divisor. */
! 88: if (dsize == 1)
! 89: {
! 90: mp_limb_t rlimb;
! 91: #ifdef COMPUTE_QUOTIENT
! 92: qp = quot->_mp_d;
! 93: rlimb = mpn_divmod_1 (qp, np, nsize, dp[0]);
! 94: qsize -= qp[qsize - 1] == 0;
! 95: quot->_mp_size = sign_quotient >= 0 ? qsize : -qsize;
! 96: #else
! 97: rlimb = mpn_mod_1 (np, nsize, dp[0]);
! 98: #endif
! 99: rp[0] = rlimb;
! 100: rsize = rlimb != 0;
! 101: rem->_mp_size = sign_remainder >= 0 ? rsize : -rsize;
! 102: return;
! 103: }
! 104:
! 105: TMP_MARK (marker);
! 106:
! 107: #ifdef COMPUTE_QUOTIENT
! 108: qp = quot->_mp_d;
! 109:
! 110: /* Make sure QP and NP point to different objects. Otherwise the
! 111: numerator would be gradually overwritten by the quotient limbs. */
! 112: if (qp == np)
! 113: {
! 114: /* Copy NP object to temporary space. */
! 115: np = (mp_ptr) TMP_ALLOC (nsize * BYTES_PER_MP_LIMB);
! 116: MPN_COPY (np, qp, nsize);
! 117: }
! 118:
! 119: #else
! 120: /* Put quotient at top of remainder. */
! 121: qp = rp + dsize;
! 122: #endif
! 123:
! 124: count_leading_zeros (normalization_steps, dp[dsize - 1]);
! 125:
! 126: /* Normalize the denominator, i.e. make its most significant bit set by
! 127: shifting it NORMALIZATION_STEPS bits to the left. Also shift the
! 128: numerator the same number of steps (to keep the quotient the same!). */
! 129: if (normalization_steps != 0)
! 130: {
! 131: mp_ptr tp;
! 132: mp_limb_t nlimb;
! 133:
! 134: /* Shift up the denominator setting the most significant bit of
! 135: the most significant word. Use temporary storage not to clobber
! 136: the original contents of the denominator. */
! 137: tp = (mp_ptr) TMP_ALLOC (dsize * BYTES_PER_MP_LIMB);
! 138: mpn_lshift (tp, dp, dsize, normalization_steps);
! 139: dp = tp;
! 140:
! 141: /* Shift up the numerator, possibly introducing a new most
! 142: significant word. Move the shifted numerator in the remainder
! 143: meanwhile. */
! 144: nlimb = mpn_lshift (rp, np, nsize, normalization_steps);
! 145: if (nlimb != 0)
! 146: {
! 147: rp[nsize] = nlimb;
! 148: rsize = nsize + 1;
! 149: }
! 150: else
! 151: rsize = nsize;
! 152: }
! 153: else
! 154: {
! 155: /* The denominator is already normalized, as required. Copy it to
! 156: temporary space if it overlaps with the quotient or remainder. */
! 157: #ifdef COMPUTE_QUOTIENT
! 158: if (dp == rp || dp == qp)
! 159: #else
! 160: if (dp == rp)
! 161: #endif
! 162: {
! 163: mp_ptr tp;
! 164:
! 165: tp = (mp_ptr) TMP_ALLOC (dsize * BYTES_PER_MP_LIMB);
! 166: MPN_COPY (tp, dp, dsize);
! 167: dp = tp;
! 168: }
! 169:
! 170: /* Move the numerator to the remainder. */
! 171: if (rp != np)
! 172: MPN_COPY (rp, np, nsize);
! 173:
! 174: rsize = nsize;
! 175: }
! 176:
! 177: q_limb = mpn_divmod (qp, rp, rsize, dp, dsize);
! 178:
! 179: #ifdef COMPUTE_QUOTIENT
! 180: qsize = rsize - dsize;
! 181: if (q_limb)
! 182: {
! 183: qp[qsize] = q_limb;
! 184: qsize += 1;
! 185: }
! 186:
! 187: quot->_mp_size = sign_quotient >= 0 ? qsize : -qsize;
! 188: #endif
! 189:
! 190: rsize = dsize;
! 191: MPN_NORMALIZE (rp, rsize);
! 192:
! 193: if (normalization_steps != 0 && rsize != 0)
! 194: {
! 195: mpn_rshift (rp, rp, rsize, normalization_steps);
! 196: rsize -= rp[rsize - 1] == 0;
! 197: }
! 198:
! 199: rem->_mp_size = sign_remainder >= 0 ? rsize : -rsize;
! 200: TMP_FREE (marker);
! 201: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>