3 * An implementation of the sieve of Eratosthenes, to generate a list of primes.
7 /* nettle, low-level cryptographics library
9 * Copyright (C) 2007 Niels Möller
11 * The nettle library is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License as published by
13 * the Free Software Foundation; either version 2.1 of the License, or (at your
14 * option) any later version.
16 * The nettle library is distributed in the hope that it will be useful, but
17 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
18 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
19 * License for more details.
21 * You should have received a copy of the GNU Lesser General Public License
22 * along with the nettle library; see the file COPYING.LIB. If not, write to
23 * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
39 # define BITS_PER_LONG (CHAR_BIT * SIZEOF_LONG)
40 # if BITS_PER_LONG > 32
41 # define NEED_HANDLE_LARGE_LONG 1
43 # define NEED_HANDLE_LARGE_LONG 0
46 # define BITS_PER_LONG (CHAR_BIT * sizeof(unsigned long))
47 # define NEED_HANDLE_LARGE_LONG 1
54 fprintf(stderr, "Usage: erathostenes [OPTIONS] [LIMIT]\n\n"
56 " -? Display this message.\n"
57 " -b SIZE Block size.\n"
58 " -v Verbose output.\n"
63 isqrt(unsigned long n)
67 /* FIXME: Better initialization. */
71 /* Must avoid overflow in the first step. */
76 unsigned long y = (x + n/x) / 2;
85 static unsigned long *
86 vector_alloc(unsigned long size)
88 unsigned long end = (size + BITS_PER_LONG - 1) / BITS_PER_LONG;
89 unsigned long *vector = malloc (end * sizeof(long));
93 fprintf(stderr, "Insufficient memory.\n");
100 vector_init(unsigned long *vector, unsigned long size)
102 unsigned long end = (size + BITS_PER_LONG - 1) / BITS_PER_LONG;
105 for (i = 0; i < end; i++)
110 vector_clear_bits (unsigned long *vector, unsigned long step,
111 unsigned long start, unsigned long size)
115 for (bit = start; bit < size; bit += step)
117 unsigned long i = bit / BITS_PER_LONG;
118 unsigned long mask = 1L << (bit % BITS_PER_LONG);
125 find_first_one (unsigned long x)
127 unsigned table[0x101] =
129 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
130 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
131 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
132 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
133 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
134 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
135 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
136 12, 0, 0, 0, 0, 0, 0, 0,11, 0, 0, 0,10, 0, 9, 8,
137 0, 0, 1, 0, 2, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0,
138 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
139 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
140 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
141 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
142 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
143 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
144 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
148 /* Isolate least significant bit */
152 #if NEED_HANDLE_LARGE_LONG
154 /* Can not be tested by the preprocessor. May generate warnings
155 when long is 32 bits. */
156 if (BITS_PER_LONG > 32)
158 while (x >= 0x100000000L)
163 #endif /* NEED_HANDLE_LARGE_LONG */
170 return i + table[128 + (x & 0xff) - (x >> 8)];
173 /* Returns size if there's no more bits set */
175 vector_find_next (const unsigned long *vector, unsigned long bit, unsigned long size)
177 unsigned long end = (size + BITS_PER_LONG - 1) / BITS_PER_LONG;
178 unsigned long i = bit / BITS_PER_LONG;
179 unsigned long mask = 1L << (bit % BITS_PER_LONG);
185 for (word = vector[i] & ~(mask - 1); !word; word = vector[i])
189 /* Next bit is the least significant bit of word */
190 return i * BITS_PER_LONG + find_first_one(word);
193 /* For benchmarking, define to do nothing (otherwise, most of the time
194 will be spent converting the output to decimal). */
195 #define OUTPUT(n) printf("%lu\n", (n))
198 atosize(const char *s)
201 long value = strtol(s, &end, 10);
206 /* FIXME: Doesn't check for overflow. */
224 main (int argc, char **argv)
226 /* Generate all primes p <= limit */
230 unsigned long limit_nbits;
232 /* Represents numbers up to sqrt(limit) */
233 unsigned long sieve_nbits;
234 unsigned long *sieve;
235 /* Block for the rest of the sieving. Size should match the cache,
236 the default value corresponds to 64 KB. */
237 unsigned long block_nbits = 64L << 13;
238 unsigned long block_start_bit;
239 unsigned long *block;
246 while ( (c = getopt(argc, argv, "?svb:")) != -1)
253 block_nbits = CHAR_BIT * atosize(optarg);
280 limit = atol(argv[0]);
291 /* Round down to odd */
292 root = (root - 1) | 1;
293 /* Represents odd numbers from 3 up. */
294 sieve_nbits = (root - 1) / 2;
295 sieve = vector_alloc(sieve_nbits );
296 vector_init(sieve, sieve_nbits);
299 fprintf(stderr, "Initial sieve using %lu bits.\n", sieve_nbits);
309 bit = vector_find_next(sieve, bit + 1, sieve_nbits))
311 unsigned long n = 3 + 2 * bit;
312 /* First bit to clear corresponds to n^2, which is bit
314 (n^2 - 3) / 2 = (n + 3) * bit + 3
316 unsigned long n2_bit = (n+3)*bit + 3;
321 vector_clear_bits (sieve, n, n2_bit, sieve_nbits);
324 limit_nbits = (limit - 1) / 2;
326 if (sieve_nbits + block_nbits > limit_nbits)
327 block_nbits = limit_nbits - sieve_nbits;
331 double storage = block_nbits / 8.0;
333 const char prefix[] = " KMG";
335 while (storage > 1024 && shift < 3)
340 fprintf(stderr, "Blockwise sieving using blocks of %lu bits (%.3g %cByte)\n",
341 block_nbits, storage, prefix[shift]);
344 block = vector_alloc(block_nbits);
346 for (block_start_bit = bit; block_start_bit < limit_nbits; block_start_bit += block_nbits)
348 unsigned long block_start;
350 if (block_start_bit + block_nbits > limit_nbits)
351 block_nbits = limit_nbits - block_start_bit;
353 vector_init(block, block_nbits);
355 block_start = 3 + 2*block_start_bit;
358 fprintf(stderr, "Next block, n = %lu\n", block_start);
361 for (bit = 0; bit < sieve_nbits;
362 bit = vector_find_next(sieve, bit + 1, sieve_nbits))
364 unsigned long n = 3 + 2 * bit;
365 unsigned long sieve_start_bit = (n + 3) * bit + 3;
367 if (sieve_start_bit < block_start_bit)
369 unsigned long k = (block_start + n - 1) / (2*n);
370 sieve_start_bit = n * k + bit;
372 assert(sieve_start_bit < block_start_bit + n);
374 assert(sieve_start_bit >= block_start_bit);
376 vector_clear_bits(block, n, sieve_start_bit - block_start_bit, block_nbits);
378 for (bit = vector_find_next(block, 0, block_nbits);
380 bit = vector_find_next(block, bit + 1, block_nbits))
382 unsigned long n = block_start + 2 * bit;