|
|
1.1 root 1: /*
2: * Copyright (c) 1989 The Regents of the University of California.
3: * All rights reserved.
4: *
5: * This code is derived from software contributed to Berkeley by
6: * Landon Curt Noll.
7: *
8: * Redistribution and use in source and binary forms are permitted
9: * provided that: (1) source distributions retain this entire copyright
10: * notice and comment, and (2) distributions including binaries display
11: * the following acknowledgement: ``This product includes software
12: * developed by the University of California, Berkeley and its contributors''
13: * in the documentation or other materials provided with the distribution
14: * and in all advertising materials mentioning features or use of this
15: * software. Neither the name of the University nor the names of its
16: * contributors may be used to endorse or promote products derived
17: * from this software without specific prior written permission.
18: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
19: * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
20: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
21: */
22:
23: #ifndef lint
24: char copyright[] =
25: "@(#) Copyright (c) 1989 The Regents of the University of California.\n\
26: All rights reserved.\n";
27: #endif /* not lint */
28:
29: #ifndef lint
30: static char sccsid[] = "@(#)primes.c 5.4 (Berkeley) 6/1/90";
31: #endif /* not lint */
32:
33: /*
34: * primes - generate a table of primes between two values
35: *
36: * By: Landon Curt Noll [email protected], ...!{sun,tolsoft}!hoptoad!chongo
37: *
38: * chongo <for a good prime call: 391581 * 2^216193 - 1> /\oo/\
39: *
40: * usage:
41: * primes [start [stop]]
42: *
43: * Print primes >= start and < stop. If stop is omitted,
44: * the value 4294967295 (2^32-1) is assumed. If start is
45: * omitted, start is read from standard input.
46: *
47: * Prints "ouch" if start or stop is bogus.
48: *
49: * validation check: there are 664579 primes between 0 and 10^7
50: */
51:
52: #include <stdio.h>
53: #include <math.h>
54: #include <memory.h>
55: #include <ctype.h>
56: #include "primes.h"
57:
58: /*
59: * Eratosthenes sieve table
60: *
61: * We only sieve the odd numbers. The base of our sieve windows are always
62: * odd. If the base of table is 1, table[i] represents 2*i-1. After the
63: * sieve, table[i] == 1 if and only iff 2*i-1 is prime.
64: *
65: * We make TABSIZE large to reduce the overhead of inner loop setup.
66: */
67: char table[TABSIZE]; /* Eratosthenes sieve of odd numbers */
68:
69: /*
70: * prime[i] is the (i-1)th prime.
71: *
72: * We are able to sieve 2^32-1 because this byte table yields all primes
73: * up to 65537 and 65537^2 > 2^32-1.
74: */
75: extern ubig prime[];
76: extern ubig *pr_limit; /* largest prime in the prime array */
77:
78: /*
79: * To avoid excessive sieves for small factors, we use the table below to
80: * setup our sieve blocks. Each element represents a odd number starting
81: * with 1. All non-zero elements are factors of 3, 5, 7, 11 and 13.
82: */
83: extern char pattern[];
84: extern int pattern_size; /* length of pattern array */
85:
86: #define MAX_LINE 255 /* max line allowed on stdin */
87:
88: char *read_num_buf(); /* read a number buffer */
89: void primes(); /* print the primes in range */
90: char *program; /* our name */
91:
92: main(argc, argv)
93: int argc; /* arg count */
94: char *argv[]; /* args */
95: {
96: char buf[MAX_LINE+1]; /* input buffer */
97: char *ret; /* return result */
98: ubig start; /* where to start generating */
99: ubig stop; /* don't generate at or above this value */
100:
101: /*
102: * parse args
103: */
104: program = argv[0];
105: start = 0;
106: stop = BIG;
107: if (argc == 3) {
108: /* convert low and high args */
109: if (read_num_buf(NULL, argv[1]) == NULL) {
110: fprintf(stderr, "%s: ouch\n", program);
111: exit(1);
112: }
113: if (read_num_buf(NULL, argv[2]) == NULL) {
114: fprintf(stderr, "%s: ouch\n", program);
115: exit(1);
116: }
117: if (sscanf(argv[1], "%ld", &start) != 1) {
118: fprintf(stderr, "%s: ouch\n", program);
119: exit(1);
120: }
121: if (sscanf(argv[2], "%ld", &stop) != 1) {
122: fprintf(stderr, "%s: ouch\n", program);
123: exit(1);
124: }
125:
126: } else if (argc == 2) {
127: /* convert low arg */
128: if (read_num_buf(NULL, argv[1]) == NULL) {
129: fprintf(stderr, "%s: ouch\n", program);
130: exit(1);
131: }
132: if (sscanf(argv[1], "%ld", &start) != 1) {
133: fprintf(stderr, "%s: ouch\n", program);
134: exit(1);
135: }
136:
137: } else {
138: /* read input until we get a good line */
139: if (read_num_buf(stdin, buf) != NULL) {
140:
141: /* convert the buffer */
142: if (sscanf(buf, "%ld", &start) != 1) {
143: fprintf(stderr, "%s: ouch\n", program);
144: exit(1);
145: }
146: } else {
147: exit(0);
148: }
149: }
150: if (start > stop) {
151: fprintf(stderr, "%s: ouch\n", program);
152: exit(1);
153: }
154: primes(start, stop);
155: exit(0);
156: }
157:
158: /*
159: * read_num_buf - read a number buffer from a stream
160: *
161: * Read a number on a line of the form:
162: *
163: * ^[ \t]*\(+?[0-9][0-9]\)*.*$
164: *
165: * where ? is a 1-or-0 operator and the number is within \( \).
166: *
167: * If does not match the above pattern, it is ignored and a new
168: * line is read. If the number is too large or small, we will
169: * print ouch and read a new line.
170: *
171: * We have to be very careful on how we check the magnitude of the
172: * input. We can not use numeric checks because of the need to
173: * check values against maximum numeric values.
174: *
175: * This routine will return a line containing a ascii number between
176: * 0 and BIG, or it will return NULL.
177: *
178: * If the stream is NULL then buf will be processed as if were
179: * a single line stream.
180: *
181: * returns:
182: * char * pointer to leading digit or +
183: * NULL EOF or error
184: */
185: char *
186: read_num_buf(input, buf)
187: FILE *input; /* input stream or NULL */
188: char *buf; /* input buffer */
189: {
190: static char limit[MAX_LINE+1]; /* ascii value of BIG */
191: static int limit_len; /* digit count of limit */
192: int len; /* digits in input (excluding +/-) */
193: char *s; /* line start marker */
194: char *d; /* first digit, skip +/- */
195: char *p; /* scan pointer */
196: char *z; /* zero scan pointer */
197:
198: /* form the ascii value of SEMIBIG if needed */
199: if (!isascii(limit[0]) || !isdigit(limit[0])) {
200: sprintf(limit, "%ld", SEMIBIG);
201: limit_len = strlen(limit);
202: }
203:
204: /*
205: * the search for a good line
206: */
207: if (input != NULL && fgets(buf, MAX_LINE, input) == NULL) {
208: /* error or EOF */
209: return NULL;
210: }
211: do {
212:
213: /* ignore leading whitespace */
214: for (s=buf; *s && s < buf+MAX_LINE; ++s) {
215: if (!isascii(*s) || !isspace(*s)) {
216: break;
217: }
218: }
219:
220: /* object if - */
221: if (*s == '-') {
222: fprintf(stderr, "%s: ouch\n", program);
223: continue;
224: }
225:
226: /* skip over any leading + */
227: if (*s == '+') {
228: d = s+1;
229: } else {
230: d = s;
231: }
232:
233: /* note leading zeros */
234: for (z=d; *z && z < buf+MAX_LINE; ++z) {
235: if (*z != '0') {
236: break;
237: }
238: }
239:
240: /* scan for the first non-digit/non-plus/non-minus */
241: for (p=d; *p && p < buf+MAX_LINE; ++p) {
242: if (!isascii(*p) || !isdigit(*p)) {
243: break;
244: }
245: }
246:
247: /* ignore empty lines */
248: if (p == d) {
249: continue;
250: }
251: *p = '\0';
252:
253: /* object if too many digits */
254: len = strlen(z);
255: len = (len<=0) ? 1 : len;
256: /* accept if digit count is below limit */
257: if (len < limit_len) {
258: /* we have good input */
259: return s;
260:
261: /* reject very large numbers */
262: } else if (len > limit_len) {
263: fprintf(stderr, "%s: ouch\n", program);
264: continue;
265:
266: /* carefully check against near limit numbers */
267: } else if (strcmp(z, limit) > 0) {
268: fprintf(stderr, "%s: ouch\n", program);
269: continue;
270: }
271: /* number is near limit, but is under it */
272: return s;
273: } while (input != NULL && fgets(buf, MAX_LINE, input) != NULL);
274:
275: /* error or EOF */
276: return NULL;
277: }
278:
279: /*
280: * primes - sieve and print primes from start up to and but not including stop
281: */
282: void
283: primes(start, stop)
284: ubig start; /* where to start generating */
285: ubig stop; /* don't generate at or above this value */
286: {
287: register char *q; /* sieve spot */
288: register ubig factor; /* index and factor */
289: register char *tab_lim; /* the limit to sieve on the table */
290: register ubig *p; /* prime table pointer */
291: register ubig fact_lim; /* highest prime for current block */
292:
293: /*
294: * A number of systems can not convert double values
295: * into unsigned longs when the values are larger than
296: * the largest signed value. Thus we take case when
297: * the double is larger than the value SEMIBIG. *sigh*
298: */
299: if (start < 3) {
300: start = (ubig)2;
301: }
302: if (stop < 3) {
303: stop = (ubig)2;
304: }
305: if (stop <= start) {
306: return;
307: }
308:
309: /*
310: * be sure that the values are odd, or 2
311: */
312: if (start != 2 && (start&0x1) == 0) {
313: ++start;
314: }
315: if (stop != 2 && (stop&0x1) == 0) {
316: ++stop;
317: }
318:
319: /*
320: * quick list of primes <= pr_limit
321: */
322: if (start <= *pr_limit) {
323: /* skip primes up to the start value */
324: for (p = &prime[0], factor = prime[0];
325: factor < stop && p <= pr_limit;
326: factor = *(++p)) {
327: if (factor >= start) {
328: printf("%u\n", factor);
329: }
330: }
331: /* return early if we are done */
332: if (p <= pr_limit) {
333: return;
334: }
335: start = *pr_limit+2;
336: }
337:
338: /*
339: * we shall sieve a bytemap window, note primes and move the window
340: * upward until we pass the stop point
341: */
342: while (start < stop) {
343: /*
344: * factor out 3, 5, 7, 11 and 13
345: */
346: /* initial pattern copy */
347: factor = (start%(2*3*5*7*11*13))/2; /* starting copy spot */
348: memcpy(table, &pattern[factor], pattern_size-factor);
349: /* main block pattern copies */
350: for (fact_lim=pattern_size-factor;
351: fact_lim+pattern_size<=TABSIZE;
352: fact_lim+=pattern_size) {
353: memcpy(&table[fact_lim], pattern, pattern_size);
354: }
355: /* final block pattern copy */
356: memcpy(&table[fact_lim], pattern, TABSIZE-fact_lim);
357:
358: /*
359: * sieve for primes 17 and higher
360: */
361: /* note highest useful factor and sieve spot */
362: if (stop-start > TABSIZE+TABSIZE) {
363: tab_lim = &table[TABSIZE]; /* sieve it all */
364: fact_lim = (int)sqrt(
365: (double)(start)+TABSIZE+TABSIZE+1.0);
366: } else {
367: tab_lim = &table[(stop-start)/2]; /* partial sieve */
368: fact_lim = (int)sqrt((double)(stop)+1.0);
369: }
370: /* sieve for factors >= 17 */
371: factor = 17; /* 17 is first prime to use */
372: p = &prime[7]; /* 19 is next prime, pi(19)=7 */
373: do {
374: /* determine the factor's initial sieve point */
375: q = (char *)(start%factor); /* temp storage for mod */
376: if ((int)q & 0x1) {
377: q = &table[(factor-(int)q)/2];
378: } else {
379: q = &table[q ? factor-((int)q/2) : 0];
380: }
381: /* sive for our current factor */
382: for ( ; q < tab_lim; q += factor) {
383: *q = '\0'; /* sieve out a spot */
384: }
385: } while ((factor=(ubig)(*(p++))) <= fact_lim);
386:
387: /*
388: * print generated primes
389: */
390: for (q = table; q < tab_lim; ++q, start+=2) {
391: if (*q) {
392: printf("%u\n", start);
393: }
394: }
395: }
396: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.