Correct PPTP server firewall rules chain.
[tomato/davidwu.git] / release / src / router / nettle / examples / eratosthenes.c
blob966506aa01aa556348ff3b2c384e929219639c50
1 /* eratosthenes.c
3 * An implementation of the sieve of Eratosthenes, to generate a list of primes.
5 */
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,
24 * MA 02111-1301, USA.
27 #if HAVE_CONFIG_H
28 # include "config.h"
29 #endif
31 #include <assert.h>
32 #include <limits.h>
33 #include <stdio.h>
34 #include <stdlib.h>
36 #include "getopt.h"
38 #ifdef SIZEOF_LONG
39 # define BITS_PER_LONG (CHAR_BIT * SIZEOF_LONG)
40 # if BITS_PER_LONG > 32
41 # define NEED_HANDLE_LARGE_LONG 1
42 # else
43 # define NEED_HANDLE_LARGE_LONG 0
44 # endif
45 #else
46 # define BITS_PER_LONG (CHAR_BIT * sizeof(unsigned long))
47 # define NEED_HANDLE_LARGE_LONG 1
48 #endif
51 static void
52 usage(void)
54 fprintf(stderr, "Usage: erathostenes [OPTIONS] [LIMIT]\n\n"
55 "Options:\n"
56 " -? Display this message.\n"
57 " -b SIZE Block size.\n"
58 " -v Verbose output.\n"
59 " -s No output.\n");
62 static unsigned
63 isqrt(unsigned long n)
65 unsigned long x;
67 /* FIXME: Better initialization. */
68 if (n < ULONG_MAX)
69 x = n;
70 else
71 /* Must avoid overflow in the first step. */
72 x = n-1;
74 for (;;)
76 unsigned long y = (x + n/x) / 2;
77 if (y >= x)
78 return x;
80 x = y;
84 /* Size is in bits */
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));
91 if (!vector)
93 fprintf(stderr, "Insufficient memory.\n");
94 exit(EXIT_FAILURE);
96 return vector;
99 static void
100 vector_init(unsigned long *vector, unsigned long size)
102 unsigned long end = (size + BITS_PER_LONG - 1) / BITS_PER_LONG;
103 unsigned long i;
105 for (i = 0; i < end; i++)
106 vector[i] = ~0;
109 static void
110 vector_clear_bits (unsigned long *vector, unsigned long step,
111 unsigned long start, unsigned long size)
113 unsigned long bit;
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);
120 vector[i] &= ~mask;
124 static unsigned
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,
148 unsigned i = 0;
150 /* Isolate least significant bit */
151 x &= -x;
153 #if NEED_HANDLE_LARGE_LONG
154 #ifndef SIZEOF_LONG
155 /* Can not be tested by the preprocessor. May generate warnings
156 when long is 32 bits. */
157 if (BITS_PER_LONG > 32)
158 #endif
159 while (x >= 0x100000000L)
161 x >>= 32;
162 i += 32;
164 #endif /* NEED_HANDLE_LARGE_LONG */
166 if (x >= 0x10000)
168 x >>= 16;
169 i += 16;
171 return i + table[128 + (x & 0xff) - (x >> 8)];
174 /* Returns size if there's no more bits set */
175 static unsigned long
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);
181 unsigned long word;
183 if (i >= end)
184 return size;
186 for (word = vector[i] & ~(mask - 1); !word; word = vector[i])
187 if (++i >= end)
188 return size;
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))
198 static long
199 atosize(const char *s)
201 char *end;
202 long value = strtol(s, &end, 10);
204 if (value <= 0)
205 return 0;
207 /* FIXME: Doesn't check for overflow. */
208 switch(*end)
210 default:
211 return 0;
212 case '\0':
213 break;
214 case 'k': case 'K':
215 value <<= 10;
216 break;
217 case 'M':
218 value <<= 20;
219 break;
221 return value;
225 main (int argc, char **argv)
227 /* Generate all primes p <= limit */
228 unsigned long limit;
229 unsigned long root;
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;
242 unsigned long bit;
243 int silent = 0;
244 int verbose = 0;
245 int c;
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' },
255 { NULL, 0, NULL, 0}
258 while ( (c = getopt_long(argc, argv, "svb:", options, NULL)) != -1)
259 switch (c)
261 case OPT_HELP:
262 usage();
263 return EXIT_SUCCESS;
264 case 'b':
265 block_nbits = CHAR_BIT * atosize(optarg);
266 if (!block_nbits)
268 usage();
269 return EXIT_FAILURE;
271 break;
273 case 'q':
274 silent = 1;
275 break;
277 case 'v':
278 verbose++;
279 break;
281 case '?':
282 return EXIT_FAILURE;
284 default:
285 abort();
288 argc -= optind;
289 argv += optind;
291 if (argc == 0)
292 limit = 1000;
293 else if (argc == 1)
295 limit = atol(argv[0]);
296 if (limit < 2)
297 return EXIT_SUCCESS;
299 else
301 usage();
302 return EXIT_FAILURE;
305 root = isqrt(limit);
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);
313 if (verbose)
314 fprintf(stderr, "Initial sieve using %lu bits.\n", sieve_nbits);
316 if (!silent)
317 printf("2\n");
319 if (limit == 2)
320 return EXIT_SUCCESS;
322 for (bit = 0;
323 bit < 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;
333 if (!silent)
334 printf("%lu\n", n);
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;
344 if (verbose)
346 double storage = block_nbits / 8.0;
347 unsigned shift = 0;
348 const char prefix[] = " KMG";
350 while (storage > 1024 && shift < 3)
352 storage /= 1024;
353 shift++;
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;
372 if (verbose > 1)
373 fprintf(stderr, "Next block, n = %lu\n", block_start);
375 /* Sieve */
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);
394 bit < block_nbits;
395 bit = vector_find_next(block, bit + 1, block_nbits))
397 unsigned long n = block_start + 2 * bit;
398 if (!silent)
399 printf("%lu\n", n);
403 free(sieve);
404 free(block);
406 return EXIT_SUCCESS;