1 1.1 mrg /* 2 1.1 mrg Copyright 2018-2019 Free Software Foundation, Inc. 3 1.1 mrg 4 1.1 mrg This file is part of the GNU MP Library test suite. 5 1.1 mrg 6 1.1 mrg The GNU MP Library test suite is free software; you can redistribute it 7 1.1 mrg and/or modify it under the terms of the GNU General Public License as 8 1.1 mrg published by the Free Software Foundation; either version 3 of the License, 9 1.1 mrg or (at your option) any later version. 10 1.1 mrg 11 1.1 mrg The GNU MP Library test suite is distributed in the hope that it will be 12 1.1 mrg useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 13 1.1 mrg MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General 14 1.1 mrg Public License for more details. 15 1.1 mrg 16 1.1 mrg You should have received a copy of the GNU General Public License along with 17 1.1 mrg the GNU MP Library test suite. If not, see https://www.gnu.org/licenses/. */ 18 1.1 mrg 19 1.1 mrg /* Usage: 20 1.1 mrg 21 1.1 mrg ./primes [p|c] [n0] <nMax> 22 1.1 mrg 23 1.1 mrg Checks mpz_probab_prime_p(n, r) exhaustively, starting from n=n0 24 1.1 mrg up to nMax. 25 1.1 mrg If n0 * n0 > nMax, the intervall is sieved piecewise, else the 26 1.1 mrg full intervall [0..nMax] is sieved at once. 27 1.1 mrg With the parameter "p" (or nothing), tests all numbers. With "c" 28 1.1 mrg only composites are tested. 29 1.1 mrg 30 1.1 mrg ./primes n [n0] <nMax> 31 1.1 mrg 32 1.1 mrg Checks mpz_nextprime() exhaustively, starting from n=n0 up to 33 1.1 mrg nMax. 34 1.1 mrg 35 1.1 mrg WARNING: The full intervall [0..nMax] is sieved at once, even if 36 1.1 mrg only a piece is needed. This may require a lot of memory! 37 1.1 mrg 38 1.1 mrg */ 39 1.1 mrg 40 1.1 mrg #include <stdlib.h> 41 1.1 mrg #include <stdio.h> 42 1.1 mrg #include "gmp-impl.h" 43 1.1 mrg #include "longlong.h" 44 1.1 mrg #include "tests.h" 45 1.1 mrg #define STOP(x) return (x) 46 1.1 mrg /* #define STOP(x) x */ 47 1.1 mrg #define REPS 10 48 1.1 mrg /* #define TRACE(x,n) if ((n)>1) {x;} */ 49 1.1 mrg #define TRACE(x,n) 50 1.1 mrg 51 1.1 mrg /* The full primesieve.c is included, just for block_resieve, that 52 1.1 mrg is not exported ... */ 53 1.1 mrg #undef gmp_primesieve 54 1.1 mrg #include "../../primesieve.c" 55 1.1 mrg 56 1.1 mrg #ifndef BLOCK_SIZE 57 1.1 mrg #define BLOCK_SIZE 2048 58 1.1 mrg #endif 59 1.1 mrg 60 1.1 mrg /*********************************************************/ 61 1.1 mrg /* Section sieve: sieving functions and tools for primes */ 62 1.1 mrg /*********************************************************/ 63 1.1 mrg 64 1.1 mrg static mp_size_t 65 1.1 mrg primesieve_size (mp_limb_t n) { return n_to_bit(n) / GMP_LIMB_BITS + 1; } 66 1.1 mrg 67 1.1 mrg /*************************************************************/ 68 1.1 mrg /* Section macros: common macros, for swing/fac/bin (&sieve) */ 69 1.1 mrg /*************************************************************/ 70 1.1 mrg 71 1.1 mrg #define LOOP_ON_SIEVE_CONTINUE(prime,end,sieve) \ 72 1.1 mrg __max_i = (end); \ 73 1.1 mrg \ 74 1.1 mrg do { \ 75 1.1 mrg ++__i; \ 76 1.1 mrg if (((sieve)[__index] & __mask) == 0) \ 77 1.1 mrg { \ 78 1.1 mrg mp_limb_t prime; \ 79 1.1 mrg prime = id_to_n(__i) 80 1.1 mrg 81 1.1 mrg #define LOOP_ON_SIEVE_BEGIN(prime,start,end,off,sieve) \ 82 1.1 mrg do { \ 83 1.1 mrg mp_limb_t __mask, __index, __max_i, __i; \ 84 1.1 mrg \ 85 1.1 mrg __i = (start)-(off); \ 86 1.1 mrg __index = __i / GMP_LIMB_BITS; \ 87 1.1 mrg __mask = CNST_LIMB(1) << (__i % GMP_LIMB_BITS); \ 88 1.1 mrg __i += (off); \ 89 1.1 mrg \ 90 1.1 mrg LOOP_ON_SIEVE_CONTINUE(prime,end,sieve) 91 1.1 mrg 92 1.1 mrg #define LOOP_ON_SIEVE_STOP \ 93 1.1 mrg } \ 94 1.1 mrg __mask = __mask << 1 | __mask >> (GMP_LIMB_BITS-1); \ 95 1.1 mrg __index += __mask & 1; \ 96 1.1 mrg } while (__i <= __max_i) 97 1.1 mrg 98 1.1 mrg #define LOOP_ON_SIEVE_END \ 99 1.1 mrg LOOP_ON_SIEVE_STOP; \ 100 1.1 mrg } while (0) 101 1.1 mrg 102 1.1 mrg mpz_t g; 103 1.1 mrg 104 1.1 mrg int something_wrong (mpz_t er, int exp) 105 1.1 mrg { 106 1.1 mrg fprintf (stderr, "value = %lu , expected = %i\n", mpz_get_ui (er), exp); 107 1.1 mrg return -1; 108 1.1 mrg } 109 1.1 mrg 110 1.1 mrg int 111 1.1 mrg check_pprime (unsigned long begin, unsigned long end, int composites) 112 1.1 mrg { 113 1.1 mrg begin = (begin / 6U) * 6U; 114 1.1 mrg for (;(begin < 2) & (begin <= end); ++begin) 115 1.1 mrg { 116 1.1 mrg *(g->_mp_d) = begin; 117 1.1 mrg TRACE(printf ("-%li ", begin),1); 118 1.1 mrg if (mpz_probab_prime_p (g, REPS)) 119 1.1 mrg STOP (something_wrong (g, 0)); 120 1.1 mrg } 121 1.1 mrg for (;(begin < 4) & (begin <= end); ++begin) 122 1.1 mrg { 123 1.1 mrg *(g->_mp_d) = begin; 124 1.1 mrg TRACE(printf ("+%li ", begin),2); 125 1.1 mrg if (!composites && !mpz_probab_prime_p (g, REPS)) 126 1.1 mrg STOP (something_wrong (g, 1)); 127 1.1 mrg } 128 1.1 mrg if (end > 4) { 129 1.1 mrg if ((end > 10000) && (begin > end / begin)) 130 1.1 mrg { 131 1.1 mrg mp_limb_t *sieve, *primes; 132 1.1 mrg mp_size_t size_s, size_p, off; 133 1.1 mrg unsigned long start; 134 1.1 mrg 135 1.1 mrg mpz_set_ui (g, end); 136 1.1 mrg mpz_sqrt (g, g); 137 1.1 mrg start = mpz_get_ui (g) + GMP_LIMB_BITS; 138 1.1 mrg size_p = primesieve_size (start); 139 1.1 mrg 140 1.1 mrg primes = __GMP_ALLOCATE_FUNC_LIMBS (size_p); 141 1.1 mrg gmp_primesieve (primes, start); 142 1.1 mrg 143 1.1 mrg size_s = BLOCK_SIZE * 2; 144 1.1 mrg sieve = __GMP_ALLOCATE_FUNC_LIMBS (size_s); 145 1.1 mrg off = n_to_bit(begin) + (begin % 3 == 0); 146 1.1 mrg 147 1.1 mrg do { 148 1.1 mrg TRACE (printf ("off =%li\n", off),3); 149 1.1 mrg block_resieve (sieve, BLOCK_SIZE, off, primes); 150 1.1 mrg TRACE (printf ("LOOP =%li - %li\n", id_to_n (off+1), id_to_n (off + BLOCK_SIZE * GMP_LIMB_BITS)),3); 151 1.1 mrg LOOP_ON_SIEVE_BEGIN (prime, off, off + BLOCK_SIZE * GMP_LIMB_BITS - 1, 152 1.1 mrg off, sieve); 153 1.1 mrg 154 1.1 mrg do { 155 1.1 mrg *(g->_mp_d) = begin; 156 1.1 mrg TRACE(printf ("-%li ", begin),1); 157 1.1 mrg if (mpz_probab_prime_p (g, REPS)) 158 1.1 mrg STOP (something_wrong (g, 0)); 159 1.1 mrg if ((begin & 0xff) == 0) 160 1.1 mrg { 161 1.1 mrg spinner(); 162 1.1 mrg if ((begin & 0xfffffff) == 0) 163 1.1 mrg printf ("%li (0x%lx)\n", begin, begin); 164 1.1 mrg } 165 1.1 mrg } while (++begin < prime); 166 1.1 mrg 167 1.1 mrg *(g->_mp_d) = begin; 168 1.1 mrg TRACE(printf ("+%li ", begin),2); 169 1.1 mrg if (!composites && ! mpz_probab_prime_p (g, REPS)) 170 1.1 mrg STOP (something_wrong (g, 1)); 171 1.1 mrg ++begin; 172 1.1 mrg 173 1.1 mrg LOOP_ON_SIEVE_END; 174 1.1 mrg off += BLOCK_SIZE * GMP_LIMB_BITS; 175 1.1 mrg } while (begin < end); 176 1.1 mrg 177 1.1 mrg __GMP_FREE_FUNC_LIMBS (sieve, size_s); 178 1.1 mrg __GMP_FREE_FUNC_LIMBS (primes, size_p); 179 1.1 mrg } 180 1.1 mrg else 181 1.1 mrg { 182 1.1 mrg mp_limb_t *sieve; 183 1.1 mrg mp_size_t size; 184 1.1 mrg unsigned long start; 185 1.1 mrg 186 1.1 mrg size = primesieve_size (end); 187 1.1 mrg 188 1.1 mrg sieve = __GMP_ALLOCATE_FUNC_LIMBS (size); 189 1.1 mrg gmp_primesieve (sieve, end); 190 1.1 mrg start = MAX (begin, 5) | 1; 191 1.1 mrg LOOP_ON_SIEVE_BEGIN (prime, n_to_bit(start) + (start % 3 == 0), 192 1.1 mrg n_to_bit (end), 0, sieve); 193 1.1 mrg 194 1.1 mrg do { 195 1.1 mrg *(g->_mp_d) = begin; 196 1.1 mrg TRACE(printf ("-%li ", begin),1); 197 1.1 mrg if (mpz_probab_prime_p (g, REPS)) 198 1.1 mrg STOP (something_wrong (g, 0)); 199 1.1 mrg if ((begin & 0xff) == 0) 200 1.1 mrg { 201 1.1 mrg spinner(); 202 1.1 mrg if ((begin & 0xfffffff) == 0) 203 1.1 mrg printf ("%li (0x%lx)\n", begin, begin); 204 1.1 mrg } 205 1.1 mrg } while (++begin < prime); 206 1.1 mrg 207 1.1 mrg *(g->_mp_d) = begin; 208 1.1 mrg TRACE(printf ("+%li ", begin),2); 209 1.1 mrg if (!composites && ! mpz_probab_prime_p (g, REPS)) 210 1.1 mrg STOP (something_wrong (g, 1)); 211 1.1 mrg ++begin; 212 1.1 mrg 213 1.1 mrg LOOP_ON_SIEVE_END; 214 1.1 mrg 215 1.1 mrg __GMP_FREE_FUNC_LIMBS (sieve, size); 216 1.1 mrg } 217 1.1 mrg } 218 1.1 mrg 219 1.1 mrg for (;begin < end; ++begin) 220 1.1 mrg { 221 1.1 mrg *(g->_mp_d) = begin; 222 1.1 mrg TRACE(printf ("-%li ", begin),1); 223 1.1 mrg if (mpz_probab_prime_p (g, REPS)) 224 1.1 mrg STOP (something_wrong (g, 0)); 225 1.1 mrg } 226 1.1 mrg 227 1.1 mrg gmp_printf ("%Zd\n", g); 228 1.1 mrg return 0; 229 1.1 mrg } 230 1.1 mrg 231 1.1 mrg int 232 1.1 mrg check_nprime (unsigned long begin, unsigned long end) 233 1.1 mrg { 234 1.1 mrg if (begin < 2) 235 1.1 mrg { 236 1.1 mrg *(g->_mp_d) = begin; 237 1.1 mrg TRACE(printf ("%li ", begin),1); 238 1.1 mrg mpz_nextprime (g, g); 239 1.1 mrg if (mpz_cmp_ui (g, 2) != 0) 240 1.1 mrg STOP (something_wrong (g, -1)); 241 1.1 mrg begin = mpz_get_ui (g); 242 1.1 mrg } 243 1.1 mrg if (begin < 3) 244 1.1 mrg { 245 1.1 mrg *(g->_mp_d) = begin; 246 1.1 mrg TRACE(printf ("%li ", begin),1); 247 1.1 mrg mpz_nextprime (g, g); 248 1.1 mrg if (mpz_cmp_ui (g, 3) != 0) 249 1.1 mrg STOP (something_wrong (g, -1)); 250 1.1 mrg begin = mpz_get_ui (g); 251 1.1 mrg } 252 1.1 mrg if (end > 4) 253 1.1 mrg { 254 1.1 mrg mp_limb_t *sieve; 255 1.1 mrg mp_size_t size; 256 1.1 mrg unsigned long start; 257 1.1 mrg 258 1.1 mrg size = primesieve_size (end); 259 1.1 mrg 260 1.1 mrg sieve = __GMP_ALLOCATE_FUNC_LIMBS (size); 261 1.1 mrg gmp_primesieve (sieve, end); 262 1.1 mrg start = MAX (begin, 5) | 1; 263 1.1 mrg *(g->_mp_d) = begin; 264 1.1 mrg LOOP_ON_SIEVE_BEGIN (prime, n_to_bit(start) + (start % 3 == 0), 265 1.1 mrg n_to_bit (end), 0, sieve); 266 1.1 mrg 267 1.1 mrg mpz_nextprime (g, g); 268 1.1 mrg if (mpz_cmp_ui (g, prime) != 0) 269 1.1 mrg STOP (something_wrong (g, -1)); 270 1.1 mrg 271 1.1 mrg if (prime - start > 200) 272 1.1 mrg { 273 1.1 mrg start = prime; 274 1.1 mrg spinner(); 275 1.1 mrg if (prime - begin > 0xfffffff) 276 1.1 mrg { 277 1.1 mrg begin = prime; 278 1.1 mrg printf ("%li (0x%lx)\n", begin, begin); 279 1.1 mrg } 280 1.1 mrg } 281 1.1 mrg 282 1.1 mrg LOOP_ON_SIEVE_END; 283 1.1 mrg 284 1.1 mrg __GMP_FREE_FUNC_LIMBS (sieve, size); 285 1.1 mrg } 286 1.1 mrg 287 1.1 mrg if (mpz_cmp_ui (g, end) < 0) 288 1.1 mrg { 289 1.1 mrg mpz_nextprime (g, g); 290 1.1 mrg if (mpz_cmp_ui (g, end) <= 0) 291 1.1 mrg STOP (something_wrong (g, -1)); 292 1.1 mrg } 293 1.1 mrg 294 1.1 mrg gmp_printf ("%Zd\n", g); 295 1.1 mrg return 0; 296 1.1 mrg } 297 1.1 mrg 298 1.1 mrg int 299 1.1 mrg main (int argc, char **argv) 300 1.1 mrg { 301 1.1 mrg int ret, mode = 0; 302 1.1 mrg unsigned long begin = 0, end = 0; 303 1.1 mrg 304 1.1 mrg for (;argc > 1;--argc,++argv) 305 1.1 mrg switch (*argv[1]) { 306 1.1 mrg case 'p': 307 1.1 mrg mode = 0; 308 1.1 mrg break; 309 1.1 mrg case 'c': 310 1.1 mrg mode = 2; 311 1.1 mrg break; 312 1.1 mrg case 'n': 313 1.1 mrg mode = 1; 314 1.1 mrg break; 315 1.1 mrg default: 316 1.1 mrg begin = end; 317 1.1 mrg end = atol (argv[1]); 318 1.1 mrg } 319 1.1 mrg 320 1.1 mrg if (begin >= end) 321 1.1 mrg { 322 1.1 mrg fprintf (stderr, "usage: primes [n|p|c] [n0] <nMax>\n"); 323 1.1 mrg exit (1); 324 1.1 mrg } 325 1.1 mrg 326 1.1 mrg mpz_init_set_ui (g, ULONG_MAX); 327 1.1 mrg 328 1.1 mrg switch (mode) { 329 1.1 mrg case 1: 330 1.1 mrg ret = check_nprime (begin, end); 331 1.1 mrg break; 332 1.1 mrg default: 333 1.1 mrg ret = check_pprime (begin, end, mode); 334 1.1 mrg } 335 1.1 mrg 336 1.1 mrg mpz_clear (g); 337 1.1 mrg 338 1.1 mrg if (ret == 0) 339 1.1 mrg printf ("Prime tests checked in [%lu - %lu] [0x%lx - 0x%lx].\n", begin, end, begin, end); 340 1.1 mrg return ret; 341 1.1 mrg } 342