primes.c 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341
  1. /* $NetBSD: primes.c,v 1.12 2004/01/27 20:30:30 jsm Exp $ */
  2. /*
  3. * Copyright (c) 1989, 1993
  4. * The Regents of the University of California. All rights reserved.
  5. *
  6. * This code is derived from software contributed to Berkeley by
  7. * Landon Curt Noll.
  8. *
  9. * Redistribution and use in source and binary forms, with or without
  10. * modification, are permitted provided that the following conditions
  11. * are met:
  12. * 1. Redistributions of source code must retain the above copyright
  13. * notice, this list of conditions and the following disclaimer.
  14. * 2. Redistributions in binary form must reproduce the above copyright
  15. * notice, this list of conditions and the following disclaimer in the
  16. * documentation and/or other materials provided with the distribution.
  17. * 3. Neither the name of the University nor the names of its contributors
  18. * may be used to endorse or promote products derived from this software
  19. * without specific prior written permission.
  20. *
  21. * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  22. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24. * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  25. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31. * SUCH DAMAGE.
  32. */
  33. #include <sys/cdefs.h>
  34. #ifndef lint
  35. __COPYRIGHT("@(#) Copyright (c) 1989, 1993\n\
  36. The Regents of the University of California. All rights reserved.\n");
  37. #endif /* not lint */
  38. #ifndef lint
  39. #if 0
  40. static char sccsid[] = "@(#)primes.c 8.5 (Berkeley) 5/10/95";
  41. #else
  42. __RCSID("$NetBSD: primes.c,v 1.12 2004/01/27 20:30:30 jsm Exp $");
  43. #endif
  44. #endif /* not lint */
  45. /*
  46. * primes - generate a table of primes between two values
  47. *
  48. * By: Landon Curt Noll chongo@toad.com, ...!{sun,tolsoft}!hoptoad!chongo
  49. *
  50. * chongo <for a good prime call: 391581 * 2^216193 - 1> /\oo/\
  51. *
  52. * usage:
  53. * primes [start [stop]]
  54. *
  55. * Print primes >= start and < stop. If stop is omitted,
  56. * the value 4294967295 (2^32-1) is assumed. If start is
  57. * omitted, start is read from standard input.
  58. *
  59. * validation check: there are 664579 primes between 0 and 10^7
  60. */
  61. #include <ctype.h>
  62. #include <err.h>
  63. #include <errno.h>
  64. #include <limits.h>
  65. #include <math.h>
  66. #include <memory.h>
  67. #include <stdio.h>
  68. #include <stdlib.h>
  69. #include <unistd.h>
  70. #include "primes.h"
  71. /*
  72. * Eratosthenes sieve table
  73. *
  74. * We only sieve the odd numbers. The base of our sieve windows are always
  75. * odd. If the base of table is 1, table[i] represents 2*i-1. After the
  76. * sieve, table[i] == 1 if and only iff 2*i-1 is prime.
  77. *
  78. * We make TABSIZE large to reduce the overhead of inner loop setup.
  79. */
  80. char table[TABSIZE]; /* Eratosthenes sieve of odd numbers */
  81. /*
  82. * prime[i] is the (i-1)th prime.
  83. *
  84. * We are able to sieve 2^32-1 because this byte table yields all primes
  85. * up to 65537 and 65537^2 > 2^32-1.
  86. */
  87. extern const ubig prime[];
  88. extern const ubig *pr_limit; /* largest prime in the prime array */
  89. /*
  90. * To avoid excessive sieves for small factors, we use the table below to
  91. * setup our sieve blocks. Each element represents a odd number starting
  92. * with 1. All non-zero elements are factors of 3, 5, 7, 11 and 13.
  93. */
  94. extern const char pattern[];
  95. extern const int pattern_size; /* length of pattern array */
  96. int main(int, char *[]);
  97. void primes(ubig, ubig);
  98. ubig read_num_buf(void);
  99. void usage(void) __attribute__((__noreturn__));
  100. int
  101. main(argc, argv)
  102. int argc;
  103. char *argv[];
  104. {
  105. ubig start; /* where to start generating */
  106. ubig stop; /* don't generate at or above this value */
  107. int ch;
  108. char *p;
  109. /* Revoke setgid privileges */
  110. setregid(getgid(), getgid());
  111. while ((ch = getopt(argc, argv, "")) != -1)
  112. switch (ch) {
  113. case '?':
  114. default:
  115. usage();
  116. }
  117. argc -= optind;
  118. argv += optind;
  119. start = 0;
  120. stop = BIG;
  121. /*
  122. * Convert low and high args. Strtoul(3) sets errno to
  123. * ERANGE if the number is too large, but, if there's
  124. * a leading minus sign it returns the negation of the
  125. * result of the conversion, which we'd rather disallow.
  126. */
  127. switch (argc) {
  128. case 2:
  129. /* Start and stop supplied on the command line. */
  130. if (argv[0][0] == '-' || argv[1][0] == '-')
  131. errx(1, "negative numbers aren't permitted.");
  132. errno = 0;
  133. start = strtoul(argv[0], &p, 10);
  134. if (errno)
  135. err(1, "%s", argv[0]);
  136. if (*p != '\0')
  137. errx(1, "%s: illegal numeric format.", argv[0]);
  138. errno = 0;
  139. stop = strtoul(argv[1], &p, 10);
  140. if (errno)
  141. err(1, "%s", argv[1]);
  142. if (*p != '\0')
  143. errx(1, "%s: illegal numeric format.", argv[1]);
  144. break;
  145. case 1:
  146. /* Start on the command line. */
  147. if (argv[0][0] == '-')
  148. errx(1, "negative numbers aren't permitted.");
  149. errno = 0;
  150. start = strtoul(argv[0], &p, 10);
  151. if (errno)
  152. err(1, "%s", argv[0]);
  153. if (*p != '\0')
  154. errx(1, "%s: illegal numeric format.", argv[0]);
  155. break;
  156. case 0:
  157. start = read_num_buf();
  158. break;
  159. default:
  160. usage();
  161. }
  162. if (start > stop)
  163. errx(1, "start value must be less than stop value.");
  164. primes(start, stop);
  165. exit(0);
  166. }
  167. /*
  168. * read_num_buf --
  169. * This routine returns a number n, where 0 <= n && n <= BIG.
  170. */
  171. ubig
  172. read_num_buf()
  173. {
  174. ubig val;
  175. char *p, buf[100]; /* > max number of digits. */
  176. for (;;) {
  177. if (fgets(buf, sizeof(buf), stdin) == NULL) {
  178. if (ferror(stdin))
  179. err(1, "stdin");
  180. exit(0);
  181. }
  182. for (p = buf; isblank(*p); ++p);
  183. if (*p == '\n' || *p == '\0')
  184. continue;
  185. if (*p == '-')
  186. errx(1, "negative numbers aren't permitted.");
  187. errno = 0;
  188. val = strtoul(buf, &p, 10);
  189. if (errno)
  190. err(1, "%s", buf);
  191. if (*p != '\n')
  192. errx(1, "%s: illegal numeric format.", buf);
  193. return (val);
  194. }
  195. }
  196. /*
  197. * primes - sieve and print primes from start up to and but not including stop
  198. */
  199. void
  200. primes(start, stop)
  201. ubig start; /* where to start generating */
  202. ubig stop; /* don't generate at or above this value */
  203. {
  204. char *q; /* sieve spot */
  205. ubig factor; /* index and factor */
  206. char *tab_lim; /* the limit to sieve on the table */
  207. const ubig *p; /* prime table pointer */
  208. ubig fact_lim; /* highest prime for current block */
  209. ubig mod; /* temp storage for mod */
  210. /*
  211. * A number of systems can not convert double values into unsigned
  212. * longs when the values are larger than the largest signed value.
  213. * We don't have this problem, so we can go all the way to BIG.
  214. */
  215. if (start < 3) {
  216. start = (ubig)2;
  217. }
  218. if (stop < 3) {
  219. stop = (ubig)2;
  220. }
  221. if (stop <= start) {
  222. return;
  223. }
  224. /*
  225. * be sure that the values are odd, or 2
  226. */
  227. if (start != 2 && (start&0x1) == 0) {
  228. ++start;
  229. }
  230. if (stop != 2 && (stop&0x1) == 0) {
  231. ++stop;
  232. }
  233. /*
  234. * quick list of primes <= pr_limit
  235. */
  236. if (start <= *pr_limit) {
  237. /* skip primes up to the start value */
  238. for (p = &prime[0], factor = prime[0];
  239. factor < stop && p <= pr_limit; factor = *(++p)) {
  240. if (factor >= start) {
  241. printf("%lu\n", (unsigned long) factor);
  242. }
  243. }
  244. /* return early if we are done */
  245. if (p <= pr_limit) {
  246. return;
  247. }
  248. start = *pr_limit+2;
  249. }
  250. /*
  251. * we shall sieve a bytemap window, note primes and move the window
  252. * upward until we pass the stop point
  253. */
  254. while (start < stop) {
  255. /*
  256. * factor out 3, 5, 7, 11 and 13
  257. */
  258. /* initial pattern copy */
  259. factor = (start%(2*3*5*7*11*13))/2; /* starting copy spot */
  260. memcpy(table, &pattern[factor], pattern_size-factor);
  261. /* main block pattern copies */
  262. for (fact_lim=pattern_size-factor;
  263. fact_lim+pattern_size<=TABSIZE; fact_lim+=pattern_size) {
  264. memcpy(&table[fact_lim], pattern, pattern_size);
  265. }
  266. /* final block pattern copy */
  267. memcpy(&table[fact_lim], pattern, TABSIZE-fact_lim);
  268. /*
  269. * sieve for primes 17 and higher
  270. */
  271. /* note highest useful factor and sieve spot */
  272. if (stop-start > TABSIZE+TABSIZE) {
  273. tab_lim = &table[TABSIZE]; /* sieve it all */
  274. fact_lim = (int)sqrt(
  275. (double)(start)+TABSIZE+TABSIZE+1.0);
  276. } else {
  277. tab_lim = &table[(stop-start)/2]; /* partial sieve */
  278. fact_lim = (int)sqrt((double)(stop)+1.0);
  279. }
  280. /* sieve for factors >= 17 */
  281. factor = 17; /* 17 is first prime to use */
  282. p = &prime[7]; /* 19 is next prime, pi(19)=7 */
  283. do {
  284. /* determine the factor's initial sieve point */
  285. mod = start%factor;
  286. if (mod & 0x1) {
  287. q = &table[(factor-mod)/2];
  288. } else {
  289. q = &table[mod ? factor-(mod/2) : 0];
  290. }
  291. /* sive for our current factor */
  292. for ( ; q < tab_lim; q += factor) {
  293. *q = '\0'; /* sieve out a spot */
  294. }
  295. } while ((factor=(ubig)(*(p++))) <= fact_lim);
  296. /*
  297. * print generated primes
  298. */
  299. for (q = table; q < tab_lim; ++q, start+=2) {
  300. if (*q) {
  301. printf("%lu\n", (unsigned long) start);
  302. }
  303. }
  304. }
  305. }
  306. void
  307. usage()
  308. {
  309. (void)fprintf(stderr, "usage: primes [start [stop]]\n");
  310. exit(1);
  311. }