Annotation of 43BSDReno/games/primes/primes.c, revision 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.