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., 51 Franklin Street, Fifth Floor, 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 static const unsigned char 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,
150 /* Isolate least significant bit */
153 #if NEED_HANDLE_LARGE_LONG
155 /* Can not be tested by the preprocessor. May generate warnings
156 when long is 32 bits. */
157 if (BITS_PER_LONG
> 32)
159 while (x
>= 0x100000000L
)
164 #endif /* NEED_HANDLE_LARGE_LONG */
171 return i
+ table
[128 + (x
& 0xff) - (x
>> 8)];
174 /* Returns size if there's no more bits set */
176 vector_find_next (const unsigned long *vector
, unsigned long bit
, unsigned long size
)
178 unsigned long end
= (size
+ BITS_PER_LONG
- 1) / BITS_PER_LONG
;
179 unsigned long i
= bit
/ BITS_PER_LONG
;
180 unsigned long mask
= 1L << (bit
% BITS_PER_LONG
);
186 for (word
= vector
[i
] & ~(mask
- 1); !word
; word
= vector
[i
])
190 /* Next bit is the least significant bit of word */
191 return i
* BITS_PER_LONG
+ find_first_one(word
);
194 /* For benchmarking, define to do nothing (otherwise, most of the time
195 will be spent converting the output to decimal). */
196 #define OUTPUT(n) printf("%lu\n", (n))
199 atosize(const char *s
)
202 long value
= strtol(s
, &end
, 10);
207 /* FIXME: Doesn't check for overflow. */
225 main (int argc
, char **argv
)
227 /* Generate all primes p <= limit */
231 unsigned long limit_nbits
;
233 /* Represents numbers up to sqrt(limit) */
234 unsigned long sieve_nbits
;
235 unsigned long *sieve
;
236 /* Block for the rest of the sieving. Size should match the cache,
237 the default value corresponds to 64 KB. */
238 unsigned long block_nbits
= 64L << 13;
239 unsigned long block_start_bit
;
240 unsigned long *block
;
247 enum { OPT_HELP
= 300 };
248 static const struct option options
[] =
250 /* Name, args, flag, val */
251 { "help", no_argument
, NULL
, OPT_HELP
},
252 { "verbose", no_argument
, NULL
, 'v' },
253 { "block-size", required_argument
, NULL
, 'b' },
254 { "quiet", required_argument
, NULL
, 'q' },
258 while ( (c
= getopt_long(argc
, argv
, "svb:", options
, NULL
)) != -1)
265 block_nbits
= CHAR_BIT
* atosize(optarg
);
295 limit
= atol(argv
[0]);
306 /* Round down to odd */
307 root
= (root
- 1) | 1;
308 /* Represents odd numbers from 3 up. */
309 sieve_nbits
= (root
- 1) / 2;
310 sieve
= vector_alloc(sieve_nbits
);
311 vector_init(sieve
, sieve_nbits
);
314 fprintf(stderr
, "Initial sieve using %lu bits.\n", sieve_nbits
);
324 bit
= vector_find_next(sieve
, bit
+ 1, sieve_nbits
))
326 unsigned long n
= 3 + 2 * bit
;
327 /* First bit to clear corresponds to n^2, which is bit
329 (n^2 - 3) / 2 = (n + 3) * bit + 3
331 unsigned long n2_bit
= (n
+3)*bit
+ 3;
336 vector_clear_bits (sieve
, n
, n2_bit
, sieve_nbits
);
339 limit_nbits
= (limit
- 1) / 2;
341 if (sieve_nbits
+ block_nbits
> limit_nbits
)
342 block_nbits
= limit_nbits
- sieve_nbits
;
346 double storage
= block_nbits
/ 8.0;
348 const char prefix
[] = " KMG";
350 while (storage
> 1024 && shift
< 3)
355 fprintf(stderr
, "Blockwise sieving using blocks of %lu bits (%.3g %cByte)\n",
356 block_nbits
, storage
, prefix
[shift
]);
359 block
= vector_alloc(block_nbits
);
361 for (block_start_bit
= bit
; block_start_bit
< limit_nbits
; block_start_bit
+= block_nbits
)
363 unsigned long block_start
;
365 if (block_start_bit
+ block_nbits
> limit_nbits
)
366 block_nbits
= limit_nbits
- block_start_bit
;
368 vector_init(block
, block_nbits
);
370 block_start
= 3 + 2*block_start_bit
;
373 fprintf(stderr
, "Next block, n = %lu\n", block_start
);
376 for (bit
= 0; bit
< sieve_nbits
;
377 bit
= vector_find_next(sieve
, bit
+ 1, sieve_nbits
))
379 unsigned long n
= 3 + 2 * bit
;
380 unsigned long sieve_start_bit
= (n
+ 3) * bit
+ 3;
382 if (sieve_start_bit
< block_start_bit
)
384 unsigned long k
= (block_start
+ n
- 1) / (2*n
);
385 sieve_start_bit
= n
* k
+ bit
;
387 assert(sieve_start_bit
< block_start_bit
+ n
);
389 assert(sieve_start_bit
>= block_start_bit
);
391 vector_clear_bits(block
, n
, sieve_start_bit
- block_start_bit
, block_nbits
);
393 for (bit
= vector_find_next(block
, 0, block_nbits
);
395 bit
= vector_find_next(block
, bit
+ 1, block_nbits
))
397 unsigned long n
= block_start
+ 2 * bit
;