github.com/aergoio/aergo@v1.3.1/libtool/src/gmp-6.1.2/mpn/generic/divis.c (about) 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 Free Software Foundation, Inc. 8 9 This file is part of the GNU MP Library. 10 11 The GNU MP Library is free software; you can redistribute it and/or modify 12 it under the terms of either: 13 14 * the GNU Lesser General Public License as published by the Free 15 Software Foundation; either version 3 of the License, or (at your 16 option) any later version. 17 18 or 19 20 * the GNU General Public License as published by the Free Software 21 Foundation; either version 2 of the License, or (at your option) any 22 later version. 23 24 or both in parallel, as here. 25 26 The GNU MP Library is distributed in the hope that it will be useful, but 27 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 28 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 29 for more details. 30 31 You should have received copies of the GNU General Public License and the 32 GNU Lesser General Public License along with the GNU MP Library. If not, 33 see https://www.gnu.org/licenses/. */ 34 35 #include "gmp.h" 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 { 63 mp_limb_t alow, dlow, dmask; 64 mp_ptr qp, rp, tp; 65 mp_size_t i; 66 mp_limb_t di; 67 unsigned twos; 68 TMP_DECL; 69 70 ASSERT (an >= 0); 71 ASSERT (an == 0 || ap[an-1] != 0); 72 ASSERT (dn >= 1); 73 ASSERT (dp[dn-1] != 0); 74 ASSERT_MPN (ap, an); 75 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 if (an < dn) 80 return (an == 0); 81 82 /* Strip low zero limbs from d, requiring a==0 on those. */ 83 for (;;) 84 { 85 alow = *ap; 86 dlow = *dp; 87 88 if (dlow != 0) 89 break; 90 91 if (alow != 0) 92 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 an--; ASSERT (an >= 1); 96 dn--; ASSERT (dn >= 1); 97 ap++; 98 dp++; 99 } 100 101 /* a must have at least as many low zero bits as d */ 102 dmask = LOW_ZEROS_MASK (dlow); 103 if ((alow & dmask) != 0) 104 return 0; 105 106 if (dn == 1) 107 { 108 if (ABOVE_THRESHOLD (an, BMOD_1_TO_MOD_1_THRESHOLD)) 109 return mpn_mod_1 (ap, an, dlow) == 0; 110 111 count_trailing_zeros (twos, dlow); 112 dlow >>= twos; 113 return mpn_modexact_1_odd (ap, an, dlow) == 0; 114 } 115 116 count_trailing_zeros (twos, dlow); 117 if (dn == 2) 118 { 119 mp_limb_t dsecond = dp[1]; 120 if (dsecond <= dmask) 121 { 122 dlow = (dlow >> twos) | (dsecond << (GMP_NUMB_BITS-twos)); 123 ASSERT_LIMB (dlow); 124 return MPN_MOD_OR_MODEXACT_1_ODD (ap, an, dlow) == 0; 125 } 126 } 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 TMP_MARK; 137 138 TMP_ALLOC_LIMBS_2 (rp, an + 1, 139 qp, an - dn + 1); /* FIXME: Could we avoid this? */ 140 141 if (twos != 0) 142 { 143 tp = TMP_ALLOC_LIMBS (dn); 144 ASSERT_NOCARRY (mpn_rshift (tp, dp, dn, twos)); 145 dp = tp; 146 147 ASSERT_NOCARRY (mpn_rshift (rp, ap, an, twos)); 148 } 149 else 150 { 151 MPN_COPY (rp, ap, an); 152 } 153 if (rp[an - 1] >= dp[dn - 1]) 154 { 155 rp[an] = 0; 156 an++; 157 } 158 else if (an == dn) 159 { 160 TMP_FREE; 161 return 0; 162 } 163 164 ASSERT (an > dn); /* requirement of functions below */ 165 166 if (BELOW_THRESHOLD (dn, DC_BDIV_QR_THRESHOLD) || 167 BELOW_THRESHOLD (an - dn, DC_BDIV_QR_THRESHOLD)) 168 { 169 binvert_limb (di, dp[0]); 170 mpn_sbpi1_bdiv_qr (qp, rp, an, dp, dn, -di); 171 rp += an - dn; 172 } 173 else if (BELOW_THRESHOLD (dn, MU_BDIV_QR_THRESHOLD)) 174 { 175 binvert_limb (di, dp[0]); 176 mpn_dcpi1_bdiv_qr (qp, rp, an, dp, dn, -di); 177 rp += an - dn; 178 } 179 else 180 { 181 tp = TMP_ALLOC_LIMBS (mpn_mu_bdiv_qr_itch (an, dn)); 182 mpn_mu_bdiv_qr (qp, rp, rp, an, dp, dn, tp); 183 } 184 185 /* test for {rp,dn} zero or non-zero */ 186 i = 0; 187 do 188 { 189 if (rp[i] != 0) 190 { 191 TMP_FREE; 192 return 0; 193 } 194 } 195 while (++i < dn); 196 197 TMP_FREE; 198 return 1; 199 }