Annotation of 43BSDReno/games/primes/primes.c, revision 1.1.1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.