Annotation of OpenXM_contrib/gmp/mpn/generic/bdivmod.c, Revision 1.1.1.2
1.1 maekawa 1: /* mpn/bdivmod.c: mpn_bdivmod for computing U/V mod 2^d.
2:
1.1.1.2 ! maekawa 3: Copyright (C) 1991, 1993, 1994, 1995, 1996, 1999, 2000 Free Software
! 4: Foundation, Inc.
1.1 maekawa 5:
6: This file is part of the GNU MP Library.
7:
8: The GNU MP Library is free software; you can redistribute it and/or modify
1.1.1.2 ! maekawa 9: it under the terms of the GNU Lesser General Public License as published by
! 10: the Free Software Foundation; either version 2.1 of the License, or (at your
1.1 maekawa 11: option) any later version.
12:
13: The GNU MP Library is distributed in the hope that it will be useful, but
14: WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
1.1.1.2 ! maekawa 15: or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
1.1 maekawa 16: License for more details.
17:
1.1.1.2 ! maekawa 18: You should have received a copy of the GNU Lesser General Public License
1.1 maekawa 19: along with the GNU MP Library; see the file COPYING.LIB. If not, write to
20: the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
21: MA 02111-1307, USA. */
22:
23: /* q_high = mpn_bdivmod (qp, up, usize, vp, vsize, d).
24:
25: Puts the low d/BITS_PER_MP_LIMB limbs of Q = U / V mod 2^d at qp, and
26: returns the high d%BITS_PER_MP_LIMB bits of Q as the result.
27:
28: Also, U - Q * V mod 2^(usize*BITS_PER_MP_LIMB) is placed at up. Since the
29: low d/BITS_PER_MP_LIMB limbs of this difference are zero, the code allows
30: the limb vectors at qp to overwrite the low limbs at up, provided qp <= up.
31:
32: Preconditions:
33: 1. V is odd.
34: 2. usize * BITS_PER_MP_LIMB >= d.
35: 3. If Q and U overlap, qp <= up.
36:
37: Ken Weber (kweber@mat.ufrgs.br, kweber@mcs.kent.edu)
38:
39: Funding for this work has been partially provided by Conselho Nacional
40: de Desenvolvimento Cienti'fico e Tecnolo'gico (CNPq) do Brazil, Grant
41: 301314194-2, and was done while I was a visiting reseacher in the Instituto
42: de Matema'tica at Universidade Federal do Rio Grande do Sul (UFRGS).
43:
44: References:
45: T. Jebelean, An algorithm for exact division, Journal of Symbolic
46: Computation, v. 15, 1993, pp. 169-180.
47:
48: K. Weber, The accelerated integer GCD algorithm, ACM Transactions on
49: Mathematical Software, v. 21 (March), 1995, pp. 111-122. */
50:
51: #include "gmp.h"
52: #include "gmp-impl.h"
53: #include "longlong.h"
54:
55: mp_limb_t
56: #if __STDC__
57: mpn_bdivmod (mp_ptr qp, mp_ptr up, mp_size_t usize,
58: mp_srcptr vp, mp_size_t vsize, unsigned long int d)
59: #else
60: mpn_bdivmod (qp, up, usize, vp, vsize, d)
61: mp_ptr qp;
62: mp_ptr up;
63: mp_size_t usize;
64: mp_srcptr vp;
65: mp_size_t vsize;
66: unsigned long int d;
67: #endif
68: {
1.1.1.2 ! maekawa 69: mp_limb_t v_inv;
1.1 maekawa 70:
1.1.1.2 ! maekawa 71: /* 1/V mod 2^BITS_PER_MP_LIMB. */
! 72: modlimb_invert (v_inv, vp[0]);
1.1 maekawa 73:
1.1.1.2 ! maekawa 74: /* Fast code for two cases previously used by the accel part of mpn_gcd.
! 75: (Could probably remove this now it's inlined there.) */
1.1 maekawa 76: if (usize == 2 && vsize == 2 &&
77: (d == BITS_PER_MP_LIMB || d == 2*BITS_PER_MP_LIMB))
78: {
79: mp_limb_t hi, lo;
80: mp_limb_t q = up[0] * v_inv;
81: umul_ppmm (hi, lo, q, vp[0]);
82: up[0] = 0, up[1] -= hi + q*vp[1], qp[0] = q;
83: if (d == 2*BITS_PER_MP_LIMB)
84: q = up[1] * v_inv, up[1] = 0, qp[1] = q;
85: return 0;
86: }
87:
88: /* Main loop. */
89: while (d >= BITS_PER_MP_LIMB)
90: {
91: mp_limb_t q = up[0] * v_inv;
92: mp_limb_t b = mpn_submul_1 (up, vp, MIN (usize, vsize), q);
93: if (usize > vsize)
94: mpn_sub_1 (up + vsize, up + vsize, usize - vsize, b);
95: d -= BITS_PER_MP_LIMB;
96: up += 1, usize -= 1;
97: *qp++ = q;
98: }
99:
100: if (d)
101: {
102: mp_limb_t b;
103: mp_limb_t q = (up[0] * v_inv) & (((mp_limb_t)1<<d) - 1);
1.1.1.2 ! maekawa 104: if (q <= 1)
1.1 maekawa 105: {
1.1.1.2 ! maekawa 106: if (q == 0)
! 107: return 0;
! 108: else
! 109: b = mpn_sub_n (up, up, vp, MIN (usize, vsize));
1.1 maekawa 110: }
1.1.1.2 ! maekawa 111: else
! 112: b = mpn_submul_1 (up, vp, MIN (usize, vsize), q);
! 113:
1.1 maekawa 114: if (usize > vsize)
115: mpn_sub_1 (up + vsize, up + vsize, usize - vsize, b);
116: return q;
117: }
118:
119: return 0;
120: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>