remove.c revision 1.1.1.1 1 1.1 mrg /* mpn_remove -- divide out all multiples of odd mpn number from another mpn
2 1.1 mrg number.
3 1.1 mrg
4 1.1 mrg Contributed to the GNU project by Torbjorn Granlund.
5 1.1 mrg
6 1.1 mrg THE FUNCTION IN THIS FILE IS INTERNAL WITH A MUTABLE INTERFACE. IT IS ONLY
7 1.1 mrg SAFE TO REACH IT THROUGH DOCUMENTED INTERFACES. IN FACT, IT IS ALMOST
8 1.1 mrg GUARANTEED THAT IT WILL CHANGE OR DISAPPEAR IN A FUTURE GMP RELEASE.
9 1.1 mrg
10 1.1 mrg Copyright 2009 Free Software Foundation, Inc.
11 1.1 mrg
12 1.1 mrg This file is part of the GNU MP Library.
13 1.1 mrg
14 1.1 mrg The GNU MP Library is free software; you can redistribute it and/or modify
15 1.1 mrg it under the terms of the GNU Lesser General Public License as published by
16 1.1 mrg the Free Software Foundation; either version 3 of the License, or (at your
17 1.1 mrg option) any later version.
18 1.1 mrg
19 1.1 mrg The GNU MP Library is distributed in the hope that it will be useful, but
20 1.1 mrg WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
21 1.1 mrg or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
22 1.1 mrg License for more details.
23 1.1 mrg
24 1.1 mrg You should have received a copy of the GNU Lesser General Public License
25 1.1 mrg along with the GNU MP Library. If not, see http://www.gnu.org/licenses/. */
26 1.1 mrg
27 1.1 mrg #include "gmp.h"
28 1.1 mrg #include "gmp-impl.h"
29 1.1 mrg
30 1.1 mrg #if GMP_LIMB_BITS > 50
31 1.1 mrg #define LOG 50
32 1.1 mrg #else
33 1.1 mrg #define LOG GMP_LIMB_BITS
34 1.1 mrg #endif
35 1.1 mrg
36 1.1 mrg
37 1.1 mrg /* Input: U = {up,un}, V = {vp,vn} must be odd, cap
38 1.1 mrg Ouput W = {wp,*wn} allocation need is exactly *wn
39 1.1 mrg
40 1.1 mrg Set W = U / V^k, where k is the largest integer <= cap such that the
41 1.1 mrg division yields an integer.
42 1.1 mrg
43 1.1 mrg FIXME: We currently allow any operand overlap. This is quite non mpn-ish
44 1.1 mrg and might be changed, since it cost significant temporary space.
45 1.1 mrg * If we require W to have space for un limbs, we could save qp or qp2 (but
46 1.1 mrg we will still need to copy things into wp 50% of the time).
47 1.1 mrg * If we allow ourselves to clobber U, we could save the other of qp and qp2.
48 1.1 mrg */
49 1.1 mrg
50 1.1 mrg mp_bitcnt_t
51 1.1 mrg mpn_remove (mp_ptr wp, mp_size_t *wn,
52 1.1 mrg mp_ptr up, mp_size_t un, mp_ptr vp, mp_size_t vn,
53 1.1 mrg mp_bitcnt_t cap)
54 1.1 mrg {
55 1.1 mrg mp_ptr pwpsp[LOG];
56 1.1 mrg mp_size_t pwpsn[LOG];
57 1.1 mrg mp_size_t npowers;
58 1.1 mrg mp_ptr tp, qp, np, pp, qp2, scratch_out;
59 1.1 mrg mp_size_t pn, nn, qn, i;
60 1.1 mrg mp_bitcnt_t pwr;
61 1.1 mrg TMP_DECL;
62 1.1 mrg
63 1.1 mrg ASSERT (un > 0);
64 1.1 mrg ASSERT (vn > 0);
65 1.1 mrg ASSERT (vp[0] % 2 != 0); /* 2-adic division wants odd numbers */
66 1.1 mrg ASSERT (vn > 1 || vp[0] > 1); /* else we would loop indefinitely */
67 1.1 mrg
68 1.1 mrg TMP_MARK;
69 1.1 mrg
70 1.1 mrg tp = TMP_ALLOC_LIMBS ((un + vn) / 2); /* remainder */
71 1.1 mrg qp = TMP_ALLOC_LIMBS (un); /* quotient, alternating */
72 1.1 mrg qp2 = TMP_ALLOC_LIMBS (un); /* quotient, alternating */
73 1.1 mrg np = TMP_ALLOC_LIMBS (un + LOG); /* powers of V */
74 1.1 mrg pp = vp;
75 1.1 mrg pn = vn;
76 1.1 mrg
77 1.1 mrg /* FIXME: This allocation need indicate a flaw in the current itch mechanism:
78 1.1 mrg Which operands not greater than un,un will incur the worst itch? We need
79 1.1 mrg a parallel foo_maxitch set of functions. */
80 1.1 mrg scratch_out = TMP_ALLOC_LIMBS (mpn_bdiv_qr_itch (un, un >> 1));
81 1.1 mrg
82 1.1 mrg MPN_COPY (qp, up, un);
83 1.1 mrg qn = un;
84 1.1 mrg
85 1.1 mrg npowers = 0;
86 1.1 mrg while (qn >= pn)
87 1.1 mrg {
88 1.1 mrg mpn_bdiv_qr (qp2, tp, qp, qn, pp, pn, scratch_out);
89 1.1 mrg if (!mpn_zero_p (tp, pn))
90 1.1 mrg break; /* could not divide by V^npowers */
91 1.1 mrg
92 1.1 mrg MP_PTR_SWAP (qp, qp2);
93 1.1 mrg qn = qn - pn;
94 1.1 mrg qn += qp[qn] != 0;
95 1.1 mrg
96 1.1 mrg pwpsp[npowers] = pp;
97 1.1 mrg pwpsn[npowers] = pn;
98 1.1 mrg npowers++;
99 1.1 mrg
100 1.1 mrg if (((mp_bitcnt_t) 2 << npowers) - 1 > cap)
101 1.1 mrg break;
102 1.1 mrg
103 1.1 mrg nn = 2 * pn - 1; /* next power will be at least this many limbs */
104 1.1 mrg if (nn > qn)
105 1.1 mrg break; /* next power would be overlarge */
106 1.1 mrg
107 1.1 mrg mpn_sqr (np, pp, pn);
108 1.1 mrg nn += np[nn] != 0;
109 1.1 mrg pp = np;
110 1.1 mrg pn = nn;
111 1.1 mrg np += nn;
112 1.1 mrg }
113 1.1 mrg
114 1.1 mrg pwr = ((mp_bitcnt_t) 1 << npowers) - 1;
115 1.1 mrg
116 1.1 mrg for (i = npowers - 1; i >= 0; i--)
117 1.1 mrg {
118 1.1 mrg pp = pwpsp[i];
119 1.1 mrg pn = pwpsn[i];
120 1.1 mrg if (qn < pn)
121 1.1 mrg continue;
122 1.1 mrg
123 1.1 mrg if (pwr + ((mp_bitcnt_t) 1 << i) > cap)
124 1.1 mrg continue; /* V^i would bring us past cap */
125 1.1 mrg
126 1.1 mrg mpn_bdiv_qr (qp2, tp, qp, qn, pp, pn, scratch_out);
127 1.1 mrg if (!mpn_zero_p (tp, pn))
128 1.1 mrg continue; /* could not divide by V^i */
129 1.1 mrg
130 1.1 mrg MP_PTR_SWAP (qp, qp2);
131 1.1 mrg qn = qn - pn;
132 1.1 mrg qn += qp[qn] != 0;
133 1.1 mrg
134 1.1 mrg pwr += (mp_bitcnt_t) 1 << i;
135 1.1 mrg }
136 1.1 mrg
137 1.1 mrg MPN_COPY (wp, qp, qn);
138 1.1 mrg *wn = qn;
139 1.1 mrg
140 1.1 mrg TMP_FREE;
141 1.1 mrg
142 1.1 mrg return pwr;
143 1.1 mrg }
144