github.com/aergoio/aergo@v1.3.1/libtool/src/gmp-6.1.2/primesieve.c (about) 1 /* primesieve (BIT_ARRAY, N) -- Fills the BIT_ARRAY with a mask for primes up to N. 2 3 Contributed to the GNU project by Marco Bodrato. 4 5 THE FUNCTION IN THIS FILE IS INTERNAL WITH A MUTABLE INTERFACE. 6 IT IS ONLY SAFE TO REACH IT THROUGH DOCUMENTED INTERFACES. 7 IN FACT, IT IS ALMOST GUARANTEED THAT IT WILL CHANGE OR 8 DISAPPEAR IN A FUTURE GNU MP RELEASE. 9 10 Copyright 2010-2012 Free Software Foundation, Inc. 11 12 This file is part of the GNU MP Library. 13 14 The GNU MP Library is free software; you can redistribute it and/or modify 15 it under the terms of either: 16 17 * the GNU Lesser General Public License as published by the Free 18 Software Foundation; either version 3 of the License, or (at your 19 option) any later version. 20 21 or 22 23 * the GNU General Public License as published by the Free Software 24 Foundation; either version 2 of the License, or (at your option) any 25 later version. 26 27 or both in parallel, as here. 28 29 The GNU MP Library is distributed in the hope that it will be useful, but 30 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 31 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 32 for more details. 33 34 You should have received copies of the GNU General Public License and the 35 GNU Lesser General Public License along with the GNU MP Library. If not, 36 see https://www.gnu.org/licenses/. */ 37 38 #include "gmp.h" 39 #include "gmp-impl.h" 40 41 /**************************************************************/ 42 /* Section macros: common macros, for mswing/fac/bin (&sieve) */ 43 /**************************************************************/ 44 45 #define LOOP_ON_SIEVE_CONTINUE(prime,end,sieve) \ 46 __max_i = (end); \ 47 \ 48 do { \ 49 ++__i; \ 50 if (((sieve)[__index] & __mask) == 0) \ 51 { \ 52 (prime) = id_to_n(__i) 53 54 #define LOOP_ON_SIEVE_BEGIN(prime,start,end,off,sieve) \ 55 do { \ 56 mp_limb_t __mask, __index, __max_i, __i; \ 57 \ 58 __i = (start)-(off); \ 59 __index = __i / GMP_LIMB_BITS; \ 60 __mask = CNST_LIMB(1) << (__i % GMP_LIMB_BITS); \ 61 __i += (off); \ 62 \ 63 LOOP_ON_SIEVE_CONTINUE(prime,end,sieve) 64 65 #define LOOP_ON_SIEVE_STOP \ 66 } \ 67 __mask = __mask << 1 | __mask >> (GMP_LIMB_BITS-1); \ 68 __index += __mask & 1; \ 69 } while (__i <= __max_i) \ 70 71 #define LOOP_ON_SIEVE_END \ 72 LOOP_ON_SIEVE_STOP; \ 73 } while (0) 74 75 /*********************************************************/ 76 /* Section sieve: sieving functions and tools for primes */ 77 /*********************************************************/ 78 79 #if 0 80 static mp_limb_t 81 bit_to_n (mp_limb_t bit) { return (bit*3+4)|1; } 82 #endif 83 84 /* id_to_n (x) = bit_to_n (x-1) = (id*3+1)|1*/ 85 static mp_limb_t 86 id_to_n (mp_limb_t id) { return id*3+1+(id&1); } 87 88 /* n_to_bit (n) = ((n-1)&(-CNST_LIMB(2)))/3U-1 */ 89 static mp_limb_t 90 n_to_bit (mp_limb_t n) { return ((n-5)|1)/3U; } 91 92 #if 0 93 static mp_size_t 94 primesieve_size (mp_limb_t n) { return n_to_bit(n) / GMP_LIMB_BITS + 1; } 95 #endif 96 97 #if GMP_LIMB_BITS > 61 98 #define SIEVE_SEED CNST_LIMB(0x3294C9E069128480) 99 #define SEED_LIMIT 202 100 #else 101 #if GMP_LIMB_BITS > 30 102 #define SIEVE_SEED CNST_LIMB(0x69128480) 103 #define SEED_LIMIT 114 104 #else 105 #if GMP_LIMB_BITS > 15 106 #define SIEVE_SEED CNST_LIMB(0x8480) 107 #define SEED_LIMIT 54 108 #else 109 #if GMP_LIMB_BITS > 7 110 #define SIEVE_SEED CNST_LIMB(0x80) 111 #define SEED_LIMIT 34 112 #else 113 #define SIEVE_SEED CNST_LIMB(0x0) 114 #define SEED_LIMIT 24 115 #endif /* 7 */ 116 #endif /* 15 */ 117 #endif /* 30 */ 118 #endif /* 61 */ 119 120 static void 121 first_block_primesieve (mp_ptr bit_array, mp_limb_t n) 122 { 123 mp_size_t bits, limbs; 124 125 ASSERT (n > 4); 126 127 bits = n_to_bit(n); 128 limbs = bits / GMP_LIMB_BITS + 1; 129 130 /* FIXME: We can skip 5 too, filling with a 5-part pattern. */ 131 MPN_ZERO (bit_array, limbs); 132 bit_array[0] = SIEVE_SEED; 133 134 if ((bits + 1) % GMP_LIMB_BITS != 0) 135 bit_array[limbs-1] |= MP_LIMB_T_MAX << ((bits + 1) % GMP_LIMB_BITS); 136 137 if (n > SEED_LIMIT) { 138 mp_limb_t mask, index, i; 139 140 ASSERT (n > 49); 141 142 mask = 1; 143 index = 0; 144 i = 1; 145 do { 146 if ((bit_array[index] & mask) == 0) 147 { 148 mp_size_t step, lindex; 149 mp_limb_t lmask; 150 unsigned maskrot; 151 152 step = id_to_n(i); 153 /* lindex = n_to_bit(id_to_n(i)*id_to_n(i)); */ 154 lindex = i*(step+1)-1+(-(i&1)&(i+1)); 155 /* lindex = i*(step+1+(i&1))-1+(i&1); */ 156 if (lindex > bits) 157 break; 158 159 step <<= 1; 160 maskrot = step % GMP_LIMB_BITS; 161 162 lmask = CNST_LIMB(1) << (lindex % GMP_LIMB_BITS); 163 do { 164 bit_array[lindex / GMP_LIMB_BITS] |= lmask; 165 lmask = lmask << maskrot | lmask >> (GMP_LIMB_BITS - maskrot); 166 lindex += step; 167 } while (lindex <= bits); 168 169 /* lindex = n_to_bit(id_to_n(i)*bit_to_n(i)); */ 170 lindex = i*(i*3+6)+(i&1); 171 172 lmask = CNST_LIMB(1) << (lindex % GMP_LIMB_BITS); 173 for ( ; lindex <= bits; lindex += step) { 174 bit_array[lindex / GMP_LIMB_BITS] |= lmask; 175 lmask = lmask << maskrot | lmask >> (GMP_LIMB_BITS - maskrot); 176 }; 177 } 178 mask = mask << 1 | mask >> (GMP_LIMB_BITS-1); 179 index += mask & 1; 180 i++; 181 } while (1); 182 } 183 } 184 185 static void 186 block_resieve (mp_ptr bit_array, mp_size_t limbs, mp_limb_t offset, 187 mp_srcptr sieve, mp_limb_t sieve_bits) 188 { 189 mp_size_t bits, step; 190 191 ASSERT (limbs > 0); 192 193 bits = limbs * GMP_LIMB_BITS - 1; 194 195 /* FIXME: We can skip 5 too, filling with a 5-part pattern. */ 196 MPN_ZERO (bit_array, limbs); 197 198 LOOP_ON_SIEVE_BEGIN(step,0,sieve_bits,0,sieve); 199 { 200 mp_size_t lindex; 201 mp_limb_t lmask; 202 unsigned maskrot; 203 204 /* lindex = n_to_bit(id_to_n(i)*id_to_n(i)); */ 205 lindex = __i*(step+1)-1+(-(__i&1)&(__i+1)); 206 /* lindex = __i*(step+1+(__i&1))-1+(__i&1); */ 207 if (lindex > bits + offset) 208 break; 209 210 step <<= 1; 211 maskrot = step % GMP_LIMB_BITS; 212 213 if (lindex < offset) 214 lindex += step * ((offset - lindex - 1) / step + 1); 215 216 lindex -= offset; 217 218 lmask = CNST_LIMB(1) << (lindex % GMP_LIMB_BITS); 219 for ( ; lindex <= bits; lindex += step) { 220 bit_array[lindex / GMP_LIMB_BITS] |= lmask; 221 lmask = lmask << maskrot | lmask >> (GMP_LIMB_BITS - maskrot); 222 }; 223 224 /* lindex = n_to_bit(id_to_n(i)*bit_to_n(i)); */ 225 lindex = __i*(__i*3+6)+(__i&1); 226 if (lindex > bits + offset) 227 continue; 228 229 if (lindex < offset) 230 lindex += step * ((offset - lindex - 1) / step + 1); 231 232 lindex -= offset; 233 234 lmask = CNST_LIMB(1) << (lindex % GMP_LIMB_BITS); 235 for ( ; lindex <= bits; lindex += step) { 236 bit_array[lindex / GMP_LIMB_BITS] |= lmask; 237 lmask = lmask << maskrot | lmask >> (GMP_LIMB_BITS - maskrot); 238 }; 239 } 240 LOOP_ON_SIEVE_END; 241 } 242 243 #define BLOCK_SIZE 2048 244 245 /* Fills bit_array with the characteristic function of composite 246 numbers up to the parameter n. I.e. a bit set to "1" represent a 247 composite, a "0" represent a prime. 248 249 The primesieve_size(n) limbs pointed to by bit_array are 250 overwritten. The returned value counts prime integers in the 251 interval [4, n]. Note that n > 4. 252 253 Even numbers and multiples of 3 are excluded "a priori", only 254 numbers equivalent to +/- 1 mod 6 have their bit in the array. 255 256 Once sieved, if the bit b is ZERO it represent a prime, the 257 represented prime is bit_to_n(b), if the LSbit is bit 0, or 258 id_to_n(b), if you call "1" the first bit. 259 */ 260 261 mp_limb_t 262 gmp_primesieve (mp_ptr bit_array, mp_limb_t n) 263 { 264 mp_size_t size; 265 mp_limb_t bits; 266 267 ASSERT (n > 4); 268 269 bits = n_to_bit(n); 270 size = bits / GMP_LIMB_BITS + 1; 271 272 if (size > BLOCK_SIZE * 2) { 273 mp_size_t off; 274 off = BLOCK_SIZE + (size % BLOCK_SIZE); 275 first_block_primesieve (bit_array, id_to_n (off * GMP_LIMB_BITS)); 276 for ( ; off < size; off += BLOCK_SIZE) 277 block_resieve (bit_array + off, BLOCK_SIZE, off * GMP_LIMB_BITS, bit_array, off * GMP_LIMB_BITS - 1); 278 } else { 279 first_block_primesieve (bit_array, n); 280 } 281 282 if ((bits + 1) % GMP_LIMB_BITS != 0) 283 bit_array[size-1] |= MP_LIMB_T_MAX << ((bits + 1) % GMP_LIMB_BITS); 284 285 286 return size * GMP_LIMB_BITS - mpn_popcount (bit_array, size); 287 } 288 289 #undef BLOCK_SIZE 290 #undef SEED_LIMIT 291 #undef SIEVE_SEED 292 #undef LOOP_ON_SIEVE_END 293 #undef LOOP_ON_SIEVE_STOP 294 #undef LOOP_ON_SIEVE_BEGIN 295 #undef LOOP_ON_SIEVE_CONTINUE