remove.c revision 1.1.1.2 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.1.2 mrg Copyright 2009, 2012 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.1.2 mrg /* FIXME: We need to wrap mpn_bdiv_qr due to the itch interface. This need
51 1.1.1.2 mrg indicates a flaw in the current itch mechanism: Which operands not greater
52 1.1.1.2 mrg than un,un will incur the worst itch? We need a parallel foo_maxitch set
53 1.1.1.2 mrg of functions. */
54 1.1.1.2 mrg static void
55 1.1.1.2 mrg mpn_bdiv_qr_wrap (mp_ptr qp, mp_ptr rp,
56 1.1.1.2 mrg mp_srcptr np, mp_size_t nn,
57 1.1.1.2 mrg mp_srcptr dp, mp_size_t dn)
58 1.1.1.2 mrg {
59 1.1.1.2 mrg mp_ptr scratch_out;
60 1.1.1.2 mrg TMP_DECL;
61 1.1.1.2 mrg
62 1.1.1.2 mrg TMP_MARK;
63 1.1.1.2 mrg scratch_out = TMP_ALLOC_LIMBS (mpn_bdiv_qr_itch (nn, dn));
64 1.1.1.2 mrg mpn_bdiv_qr (qp, rp, np, nn, dp, dn, scratch_out);
65 1.1.1.2 mrg
66 1.1.1.2 mrg TMP_FREE;
67 1.1.1.2 mrg }
68 1.1.1.2 mrg
69 1.1 mrg mp_bitcnt_t
70 1.1 mrg mpn_remove (mp_ptr wp, mp_size_t *wn,
71 1.1 mrg mp_ptr up, mp_size_t un, mp_ptr vp, mp_size_t vn,
72 1.1 mrg mp_bitcnt_t cap)
73 1.1 mrg {
74 1.1 mrg mp_ptr pwpsp[LOG];
75 1.1 mrg mp_size_t pwpsn[LOG];
76 1.1 mrg mp_size_t npowers;
77 1.1.1.2 mrg mp_ptr tp, qp, np, pp, qp2;
78 1.1 mrg mp_size_t pn, nn, qn, i;
79 1.1 mrg mp_bitcnt_t pwr;
80 1.1 mrg TMP_DECL;
81 1.1 mrg
82 1.1 mrg ASSERT (un > 0);
83 1.1 mrg ASSERT (vn > 0);
84 1.1 mrg ASSERT (vp[0] % 2 != 0); /* 2-adic division wants odd numbers */
85 1.1 mrg ASSERT (vn > 1 || vp[0] > 1); /* else we would loop indefinitely */
86 1.1 mrg
87 1.1 mrg TMP_MARK;
88 1.1 mrg
89 1.1.1.2 mrg tp = TMP_ALLOC_LIMBS ((un + 1 + vn) / 2); /* remainder */
90 1.1.1.2 mrg qp = TMP_ALLOC_LIMBS (un + 1); /* quotient, alternating */
91 1.1.1.2 mrg qp2 = TMP_ALLOC_LIMBS (un + 1); /* quotient, alternating */
92 1.1 mrg np = TMP_ALLOC_LIMBS (un + LOG); /* powers of V */
93 1.1 mrg pp = vp;
94 1.1 mrg pn = vn;
95 1.1 mrg
96 1.1 mrg MPN_COPY (qp, up, un);
97 1.1 mrg qn = un;
98 1.1 mrg
99 1.1 mrg npowers = 0;
100 1.1 mrg while (qn >= pn)
101 1.1 mrg {
102 1.1.1.2 mrg qp[qn] = 0;
103 1.1.1.2 mrg mpn_bdiv_qr_wrap (qp2, tp, qp, qn + 1, pp, pn);
104 1.1 mrg if (!mpn_zero_p (tp, pn))
105 1.1 mrg break; /* could not divide by V^npowers */
106 1.1 mrg
107 1.1 mrg MP_PTR_SWAP (qp, qp2);
108 1.1 mrg qn = qn - pn;
109 1.1 mrg qn += qp[qn] != 0;
110 1.1 mrg
111 1.1 mrg pwpsp[npowers] = pp;
112 1.1 mrg pwpsn[npowers] = pn;
113 1.1 mrg npowers++;
114 1.1 mrg
115 1.1 mrg if (((mp_bitcnt_t) 2 << npowers) - 1 > cap)
116 1.1 mrg break;
117 1.1 mrg
118 1.1.1.2 mrg nn = 2 * pn - 1; /* next power will be at least this large */
119 1.1 mrg if (nn > qn)
120 1.1 mrg break; /* next power would be overlarge */
121 1.1 mrg
122 1.1 mrg mpn_sqr (np, pp, pn);
123 1.1 mrg nn += np[nn] != 0;
124 1.1 mrg pp = np;
125 1.1 mrg pn = nn;
126 1.1 mrg np += nn;
127 1.1 mrg }
128 1.1 mrg
129 1.1 mrg pwr = ((mp_bitcnt_t) 1 << npowers) - 1;
130 1.1 mrg
131 1.1 mrg for (i = npowers - 1; i >= 0; i--)
132 1.1 mrg {
133 1.1 mrg pp = pwpsp[i];
134 1.1 mrg pn = pwpsn[i];
135 1.1 mrg if (qn < pn)
136 1.1 mrg continue;
137 1.1 mrg
138 1.1 mrg if (pwr + ((mp_bitcnt_t) 1 << i) > cap)
139 1.1 mrg continue; /* V^i would bring us past cap */
140 1.1 mrg
141 1.1.1.2 mrg qp[qn] = 0;
142 1.1.1.2 mrg mpn_bdiv_qr_wrap (qp2, tp, qp, qn + 1, pp, pn);
143 1.1 mrg if (!mpn_zero_p (tp, pn))
144 1.1 mrg continue; /* could not divide by V^i */
145 1.1 mrg
146 1.1 mrg MP_PTR_SWAP (qp, qp2);
147 1.1 mrg qn = qn - pn;
148 1.1 mrg qn += qp[qn] != 0;
149 1.1 mrg
150 1.1 mrg pwr += (mp_bitcnt_t) 1 << i;
151 1.1 mrg }
152 1.1 mrg
153 1.1 mrg MPN_COPY (wp, qp, qn);
154 1.1 mrg *wn = qn;
155 1.1 mrg
156 1.1 mrg TMP_FREE;
157 1.1 mrg
158 1.1 mrg return pwr;
159 1.1 mrg }
160