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