divis.c revision 1.1.1.1.8.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.1.1.8.1 tls /* Determine whether A={ap,an} is divisible by D={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.1.1.8.1 tls 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.1.1.8.1 tls 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.1.1.8.1 tls When D must be normalized (shifted to low bit set), it's possible to supress
45 1.1.1.1.8.1 tls the bit-shifting of A down, as long as it's already been checked that A has
46 1.1.1.1.8.1 tls at least as many trailing zero bits as D. */
47 1.1 mrg
48 1.1 mrg int
49 1.1 mrg mpn_divisible_p (mp_srcptr ap, mp_size_t an,
50 1.1 mrg mp_srcptr dp, mp_size_t dn)
51 1.1 mrg {
52 1.1 mrg mp_limb_t alow, dlow, dmask;
53 1.1 mrg mp_ptr qp, rp, tp;
54 1.1 mrg mp_size_t i;
55 1.1 mrg mp_limb_t di;
56 1.1 mrg unsigned twos;
57 1.1 mrg TMP_DECL;
58 1.1 mrg
59 1.1 mrg ASSERT (an >= 0);
60 1.1 mrg ASSERT (an == 0 || ap[an-1] != 0);
61 1.1 mrg ASSERT (dn >= 1);
62 1.1 mrg ASSERT (dp[dn-1] != 0);
63 1.1 mrg ASSERT_MPN (ap, an);
64 1.1 mrg ASSERT_MPN (dp, dn);
65 1.1 mrg
66 1.1 mrg /* When a<d only a==0 is divisible.
67 1.1 mrg Notice this test covers all cases of an==0. */
68 1.1 mrg if (an < dn)
69 1.1 mrg return (an == 0);
70 1.1 mrg
71 1.1 mrg /* Strip low zero limbs from d, requiring a==0 on those. */
72 1.1 mrg for (;;)
73 1.1 mrg {
74 1.1 mrg alow = *ap;
75 1.1 mrg dlow = *dp;
76 1.1 mrg
77 1.1 mrg if (dlow != 0)
78 1.1 mrg break;
79 1.1 mrg
80 1.1 mrg if (alow != 0)
81 1.1 mrg return 0; /* a has fewer low zero limbs than d, so not divisible */
82 1.1 mrg
83 1.1 mrg /* a!=0 and d!=0 so won't get to n==0 */
84 1.1 mrg an--; ASSERT (an >= 1);
85 1.1 mrg dn--; ASSERT (dn >= 1);
86 1.1 mrg ap++;
87 1.1 mrg dp++;
88 1.1 mrg }
89 1.1 mrg
90 1.1 mrg /* a must have at least as many low zero bits as d */
91 1.1 mrg dmask = LOW_ZEROS_MASK (dlow);
92 1.1 mrg if ((alow & dmask) != 0)
93 1.1 mrg return 0;
94 1.1 mrg
95 1.1 mrg if (dn == 1)
96 1.1 mrg {
97 1.1 mrg if (ABOVE_THRESHOLD (an, BMOD_1_TO_MOD_1_THRESHOLD))
98 1.1 mrg return mpn_mod_1 (ap, an, dlow) == 0;
99 1.1 mrg
100 1.1 mrg count_trailing_zeros (twos, dlow);
101 1.1 mrg dlow >>= twos;
102 1.1 mrg return mpn_modexact_1_odd (ap, an, dlow) == 0;
103 1.1 mrg }
104 1.1 mrg
105 1.1 mrg if (dn == 2)
106 1.1 mrg {
107 1.1 mrg mp_limb_t dsecond = dp[1];
108 1.1 mrg if (dsecond <= dmask)
109 1.1 mrg {
110 1.1 mrg count_trailing_zeros (twos, dlow);
111 1.1 mrg dlow = (dlow >> twos) | (dsecond << (GMP_NUMB_BITS-twos));
112 1.1 mrg ASSERT_LIMB (dlow);
113 1.1 mrg return MPN_MOD_OR_MODEXACT_1_ODD (ap, an, dlow) == 0;
114 1.1 mrg }
115 1.1 mrg }
116 1.1 mrg
117 1.1 mrg /* Should we compute Q = A * D^(-1) mod B^k,
118 1.1 mrg R = A - Q * D mod B^k
119 1.1 mrg here, for some small values of k? Then check if R = 0 (mod B^k). */
120 1.1 mrg
121 1.1 mrg /* We could also compute A' = A mod T and D' = D mod P, for some
122 1.1 mrg P = 3 * 5 * 7 * 11 ..., and then check if any prime factor from P
123 1.1 mrg dividing D' also divides A'. */
124 1.1 mrg
125 1.1 mrg TMP_MARK;
126 1.1 mrg
127 1.1 mrg rp = TMP_ALLOC_LIMBS (an + 1);
128 1.1.1.1.8.1 tls qp = TMP_ALLOC_LIMBS (an - dn + 1); /* FIXME: Could we avoid this? */
129 1.1 mrg
130 1.1 mrg count_trailing_zeros (twos, dp[0]);
131 1.1 mrg
132 1.1 mrg if (twos != 0)
133 1.1 mrg {
134 1.1 mrg tp = TMP_ALLOC_LIMBS (dn);
135 1.1 mrg ASSERT_NOCARRY (mpn_rshift (tp, dp, dn, twos));
136 1.1 mrg dp = tp;
137 1.1 mrg
138 1.1 mrg ASSERT_NOCARRY (mpn_rshift (rp, ap, an, twos));
139 1.1 mrg }
140 1.1 mrg else
141 1.1 mrg {
142 1.1 mrg MPN_COPY (rp, ap, an);
143 1.1 mrg }
144 1.1 mrg if (rp[an - 1] >= dp[dn - 1])
145 1.1 mrg {
146 1.1 mrg rp[an] = 0;
147 1.1 mrg an++;
148 1.1 mrg }
149 1.1 mrg else if (an == dn)
150 1.1 mrg {
151 1.1 mrg TMP_FREE;
152 1.1 mrg return 0;
153 1.1 mrg }
154 1.1 mrg
155 1.1 mrg ASSERT (an > dn); /* requirement of functions below */
156 1.1 mrg
157 1.1 mrg if (BELOW_THRESHOLD (dn, DC_BDIV_QR_THRESHOLD) ||
158 1.1 mrg BELOW_THRESHOLD (an - dn, DC_BDIV_QR_THRESHOLD))
159 1.1 mrg {
160 1.1 mrg binvert_limb (di, dp[0]);
161 1.1 mrg mpn_sbpi1_bdiv_qr (qp, rp, an, dp, dn, -di);
162 1.1 mrg rp += an - dn;
163 1.1 mrg }
164 1.1 mrg else if (BELOW_THRESHOLD (dn, MU_BDIV_QR_THRESHOLD))
165 1.1 mrg {
166 1.1 mrg binvert_limb (di, dp[0]);
167 1.1 mrg mpn_dcpi1_bdiv_qr (qp, rp, an, dp, dn, -di);
168 1.1 mrg rp += an - dn;
169 1.1 mrg }
170 1.1 mrg else
171 1.1 mrg {
172 1.1 mrg tp = TMP_ALLOC_LIMBS (mpn_mu_bdiv_qr_itch (an, dn));
173 1.1 mrg mpn_mu_bdiv_qr (qp, rp, rp, an, dp, dn, tp);
174 1.1 mrg }
175 1.1 mrg
176 1.1 mrg /* test for {rp,dn} zero or non-zero */
177 1.1 mrg i = 0;
178 1.1 mrg do
179 1.1 mrg {
180 1.1 mrg if (rp[i] != 0)
181 1.1 mrg {
182 1.1 mrg TMP_FREE;
183 1.1 mrg return 0;
184 1.1 mrg }
185 1.1 mrg }
186 1.1 mrg while (++i < dn);
187 1.1 mrg
188 1.1 mrg TMP_FREE;
189 1.1 mrg return 1;
190 1.1 mrg }
191