divis.c revision 1.1.1.1 1 1.1 mrg /* mpn_divisible_p -- mpn by mpn divisibility test
2 1.1 mrg
3 1.1 mrg THE FUNCTIONS IN THIS FILE ARE FOR INTERNAL USE ONLY. THEY'RE ALMOST
4 1.1 mrg CERTAIN TO BE SUBJECT TO INCOMPATIBLE CHANGES OR DISAPPEAR COMPLETELY IN
5 1.1 mrg FUTURE GNU MP RELEASES.
6 1.1 mrg
7 1.1 mrg Copyright 2001, 2002, 2005, 2009 Free Software Foundation, Inc.
8 1.1 mrg
9 1.1 mrg This file is part of the GNU MP Library.
10 1.1 mrg
11 1.1 mrg The GNU MP Library is free software; you can redistribute it and/or modify
12 1.1 mrg it under the terms of the GNU Lesser General Public License as published by
13 1.1 mrg the Free Software Foundation; either version 3 of the License, or (at your
14 1.1 mrg option) any later version.
15 1.1 mrg
16 1.1 mrg The GNU MP Library is distributed in the hope that it will be useful, but
17 1.1 mrg WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
18 1.1 mrg or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
19 1.1 mrg License for more details.
20 1.1 mrg
21 1.1 mrg You should have received a copy of the GNU Lesser General Public License
22 1.1 mrg along with the GNU MP Library. If not, see http://www.gnu.org/licenses/. */
23 1.1 mrg
24 1.1 mrg #include "gmp.h"
25 1.1 mrg #include "gmp-impl.h"
26 1.1 mrg #include "longlong.h"
27 1.1 mrg
28 1.1 mrg
29 1.1 mrg /* Determine whether {ap,an} is divisible by {dp,dn}. Must have both
30 1.1 mrg operands normalized, meaning high limbs non-zero, except that an==0 is
31 1.1 mrg allowed.
32 1.1 mrg
33 1.1 mrg There usually won't be many low zero bits on d, but the checks for this
34 1.1 mrg are fast and might pick up a few operand combinations, in particular they
35 1.1 mrg might reduce d to fit the single-limb mod_1/modexact_1 code.
36 1.1 mrg
37 1.1 mrg Future:
38 1.1 mrg
39 1.1 mrg Getting the remainder limb by limb would make an early exit possible on
40 1.1 mrg finding a non-zero. This would probably have to be bdivmod style so
41 1.1 mrg there's no addback, but it would need a multi-precision inverse and so
42 1.1 mrg might be slower than the plain method (on small sizes at least).
43 1.1 mrg
44 1.1 mrg When d must be normalized (shifted to high bit set), it's possible to
45 1.1 mrg just append a low zero limb to "a" rather than bit-shifting as
46 1.1 mrg mpn_tdiv_qr does internally, so long as it's already been checked that a
47 1.1 mrg has at least as many trailing zeros bits as d. Or equivalently, pass
48 1.1 mrg qxn==1 to mpn_tdiv_qr, if/when it accepts that. */
49 1.1 mrg
50 1.1 mrg int
51 1.1 mrg mpn_divisible_p (mp_srcptr ap, mp_size_t an,
52 1.1 mrg mp_srcptr dp, mp_size_t dn)
53 1.1 mrg {
54 1.1 mrg mp_limb_t alow, dlow, dmask;
55 1.1 mrg mp_ptr qp, rp, tp;
56 1.1 mrg mp_size_t i;
57 1.1 mrg mp_limb_t di;
58 1.1 mrg unsigned twos;
59 1.1 mrg TMP_DECL;
60 1.1 mrg
61 1.1 mrg ASSERT (an >= 0);
62 1.1 mrg ASSERT (an == 0 || ap[an-1] != 0);
63 1.1 mrg ASSERT (dn >= 1);
64 1.1 mrg ASSERT (dp[dn-1] != 0);
65 1.1 mrg ASSERT_MPN (ap, an);
66 1.1 mrg ASSERT_MPN (dp, dn);
67 1.1 mrg
68 1.1 mrg /* When a<d only a==0 is divisible.
69 1.1 mrg Notice this test covers all cases of an==0. */
70 1.1 mrg if (an < dn)
71 1.1 mrg return (an == 0);
72 1.1 mrg
73 1.1 mrg /* Strip low zero limbs from d, requiring a==0 on those. */
74 1.1 mrg for (;;)
75 1.1 mrg {
76 1.1 mrg alow = *ap;
77 1.1 mrg dlow = *dp;
78 1.1 mrg
79 1.1 mrg if (dlow != 0)
80 1.1 mrg break;
81 1.1 mrg
82 1.1 mrg if (alow != 0)
83 1.1 mrg return 0; /* a has fewer low zero limbs than d, so not divisible */
84 1.1 mrg
85 1.1 mrg /* a!=0 and d!=0 so won't get to n==0 */
86 1.1 mrg an--; ASSERT (an >= 1);
87 1.1 mrg dn--; ASSERT (dn >= 1);
88 1.1 mrg ap++;
89 1.1 mrg dp++;
90 1.1 mrg }
91 1.1 mrg
92 1.1 mrg /* a must have at least as many low zero bits as d */
93 1.1 mrg dmask = LOW_ZEROS_MASK (dlow);
94 1.1 mrg if ((alow & dmask) != 0)
95 1.1 mrg return 0;
96 1.1 mrg
97 1.1 mrg if (dn == 1)
98 1.1 mrg {
99 1.1 mrg if (ABOVE_THRESHOLD (an, BMOD_1_TO_MOD_1_THRESHOLD))
100 1.1 mrg return mpn_mod_1 (ap, an, dlow) == 0;
101 1.1 mrg
102 1.1 mrg count_trailing_zeros (twos, dlow);
103 1.1 mrg dlow >>= twos;
104 1.1 mrg return mpn_modexact_1_odd (ap, an, dlow) == 0;
105 1.1 mrg }
106 1.1 mrg
107 1.1 mrg if (dn == 2)
108 1.1 mrg {
109 1.1 mrg mp_limb_t dsecond = dp[1];
110 1.1 mrg if (dsecond <= dmask)
111 1.1 mrg {
112 1.1 mrg count_trailing_zeros (twos, dlow);
113 1.1 mrg dlow = (dlow >> twos) | (dsecond << (GMP_NUMB_BITS-twos));
114 1.1 mrg ASSERT_LIMB (dlow);
115 1.1 mrg return MPN_MOD_OR_MODEXACT_1_ODD (ap, an, dlow) == 0;
116 1.1 mrg }
117 1.1 mrg }
118 1.1 mrg
119 1.1 mrg /* Should we compute Q = A * D^(-1) mod B^k,
120 1.1 mrg R = A - Q * D mod B^k
121 1.1 mrg here, for some small values of k? Then check if R = 0 (mod B^k). */
122 1.1 mrg
123 1.1 mrg /* We could also compute A' = A mod T and D' = D mod P, for some
124 1.1 mrg P = 3 * 5 * 7 * 11 ..., and then check if any prime factor from P
125 1.1 mrg dividing D' also divides A'. */
126 1.1 mrg
127 1.1 mrg TMP_MARK;
128 1.1 mrg
129 1.1 mrg rp = TMP_ALLOC_LIMBS (an + 1);
130 1.1 mrg qp = TMP_ALLOC_LIMBS (an - dn + 1); /* FIXME: Could we avoid this */
131 1.1 mrg
132 1.1 mrg count_trailing_zeros (twos, dp[0]);
133 1.1 mrg
134 1.1 mrg if (twos != 0)
135 1.1 mrg {
136 1.1 mrg tp = TMP_ALLOC_LIMBS (dn);
137 1.1 mrg ASSERT_NOCARRY (mpn_rshift (tp, dp, dn, twos));
138 1.1 mrg dp = tp;
139 1.1 mrg
140 1.1 mrg ASSERT_NOCARRY (mpn_rshift (rp, ap, an, twos));
141 1.1 mrg }
142 1.1 mrg else
143 1.1 mrg {
144 1.1 mrg MPN_COPY (rp, ap, an);
145 1.1 mrg }
146 1.1 mrg if (rp[an - 1] >= dp[dn - 1])
147 1.1 mrg {
148 1.1 mrg rp[an] = 0;
149 1.1 mrg an++;
150 1.1 mrg }
151 1.1 mrg else if (an == dn)
152 1.1 mrg {
153 1.1 mrg TMP_FREE;
154 1.1 mrg return 0;
155 1.1 mrg }
156 1.1 mrg
157 1.1 mrg ASSERT (an > dn); /* requirement of functions below */
158 1.1 mrg
159 1.1 mrg if (BELOW_THRESHOLD (dn, DC_BDIV_QR_THRESHOLD) ||
160 1.1 mrg BELOW_THRESHOLD (an - dn, DC_BDIV_QR_THRESHOLD))
161 1.1 mrg {
162 1.1 mrg binvert_limb (di, dp[0]);
163 1.1 mrg mpn_sbpi1_bdiv_qr (qp, rp, an, dp, dn, -di);
164 1.1 mrg rp += an - dn;
165 1.1 mrg }
166 1.1 mrg else if (BELOW_THRESHOLD (dn, MU_BDIV_QR_THRESHOLD))
167 1.1 mrg {
168 1.1 mrg binvert_limb (di, dp[0]);
169 1.1 mrg mpn_dcpi1_bdiv_qr (qp, rp, an, dp, dn, -di);
170 1.1 mrg rp += an - dn;
171 1.1 mrg }
172 1.1 mrg else
173 1.1 mrg {
174 1.1 mrg tp = TMP_ALLOC_LIMBS (mpn_mu_bdiv_qr_itch (an, dn));
175 1.1 mrg mpn_mu_bdiv_qr (qp, rp, rp, an, dp, dn, tp);
176 1.1 mrg }
177 1.1 mrg
178 1.1 mrg /* test for {rp,dn} zero or non-zero */
179 1.1 mrg i = 0;
180 1.1 mrg do
181 1.1 mrg {
182 1.1 mrg if (rp[i] != 0)
183 1.1 mrg {
184 1.1 mrg TMP_FREE;
185 1.1 mrg return 0;
186 1.1 mrg }
187 1.1 mrg }
188 1.1 mrg while (++i < dn);
189 1.1 mrg
190 1.1 mrg TMP_FREE;
191 1.1 mrg return 1;
192 1.1 mrg }
193