Annotation of coherent/d/bin/factor.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Factor prints out the prime factorization of numbers.  If there are
                      3:  * any arguments, then it factors these.  If there are no arguments,
                      4:  * then it reads stdin until either EOF or the number zero or a non-numeric
                      5:  * non-white-space character.  Since factor does all of its calculations
                      6:  * in double format, the largest number which can be handled is quite
                      7:  * large.
                      8:  */
                      9: #include <stdio.h>
                     10: #include <math.h>
                     11: #include <ctype.h>
                     12: 
                     13: 
                     14: #define        NUL     '\0'
                     15: #define        ERROR   0x10                    /* largest input base */
                     16: #define        MAXNUM  200                     /* max number of chars in number */
                     17: 
                     18: 
                     19: main(argc, argv)
                     20: int            argc;
                     21: register char  *argv[];
                     22: {
                     23:        register char   *chp;
                     24:        double          n;
                     25:        double          atod();
                     26:        char            *getnum();
                     27: 
                     28:        if (argc != 1)
                     29:                while ((chp=*++argv) != NULL && (n=atod(chp)) != 0)
                     30:                        factor(n);
                     31:        else
                     32:                while ((chp=getnum()) != NULL && (n=atod(chp)) != 0)
                     33:                        factor(n);
                     34:        return (0);
                     35: }
                     36: 
                     37: 
                     38: die(str)
                     39: char   *str;
                     40: {
                     41:        fprintf(stderr, "%r\n", &str);
                     42:        exit(1);
                     43: }
                     44: 
                     45: usage()
                     46: {
                     47:        die("usage: factor [number number ...]");
                     48: }
                     49: 
                     50: 
                     51: char   *
                     52: getnum()
                     53: {
                     54:        register char   *chp,
                     55:                        ch;
                     56:        static char     res[MAXNUM+1];
                     57: 
                     58:        do {
                     59:                ch = getchar();
                     60:        } while (isascii(ch) && isspace(ch));
                     61:        if (!isascii(ch) || todigit(ch) == ERROR)
                     62:                return (NULL);
                     63:        for (chp=res; isascii(ch) && !isspace(ch); ch=getchar())
                     64:                if (chp < &res[MAXNUM])
                     65:                        *chp++ = ch;
                     66:        if (chp >= &res[MAXNUM])
                     67:                die("Number too big");
                     68:        *chp++ = NUL;
                     69:        return (res);
                     70: }
                     71: 
                     72: 
                     73: /*
                     74:  * Atod converts the string `num' to a double and returns the value.
                     75:  * Note, that if there is a non-digit in the string, or if there is
                     76:  * an overflow, then it exits with an appropriate error message.
                     77:  * Also note that atod accepts leading zero for octal and leading
                     78:  * 0x for hexidecimal, and that in the latter case, a-f and A-F are
                     79:  * both accepted as digits.
                     80:  */
                     81: double
                     82: atod(num)
                     83: char   *num;
                     84: {
                     85:        register char   *str;
                     86:        register int    i;
                     87:        double          res     = 0,
                     88:                        base    = 10;
                     89: 
                     90:        str = num;
                     91:        i = *str++;
                     92:        if (i == '0')
                     93:                if ((i=*str++) == 'x') {
                     94:                        i = *str++;
                     95:                        base = 0x10;
                     96:                } else
                     97:                        base = 010;
                     98:        for (; i != '\0'; i=*str++) {
                     99:                i = todigit(i);
                    100:                if (i >= base)
                    101:                        die("bad number `%s'", num);
                    102:                res = res * base + i;
                    103:                if (res+1 == res)
                    104:                        die("Number too big `%s'", num);
                    105:        }
                    106:        return (res);
                    107: }
                    108: 
                    109: 
                    110: /*
                    111:  * Todigit converts the char `ch' to an integer equivalent, assuming
                    112:  * that `ch' is a digit or `a'-`f' or `A'-`F'.  If this is not true,
                    113:  * then it returns ERROR.
                    114:  */
                    115: todigit(ch)
                    116: register int   ch;
                    117: {
                    118:        if (!isascii(ch))
                    119:                return (ERROR);
                    120:        if (isdigit(ch))
                    121:                return (ch - '0' + 0);
                    122:        if (isupper(ch))
                    123:                ch = tolower(ch);
                    124:        if ('a' <= ch && ch <= 'f')
                    125:                return (ch - 'a' + 0xa);
                    126:        return (ERROR);
                    127: }
                    128: 
                    129: 
                    130: /*
                    131:  * Factor is the routine that actually factors the double `n'.
                    132:  * It writes the prime factors to standard output.
                    133:  */
                    134: factor(n)
                    135: double n;
                    136: {
                    137:        double          temp,
                    138:                        limit,
                    139:                        try;
                    140: 
                    141:        while (n > 1 && modf(n/2, &temp) == 0) {
                    142:                printf("2 ");
                    143:                n = temp;
                    144:        }
                    145:        limit = sqrt(n);
                    146:        for (try=3; try <= limit; try += 2) {
                    147:                if (modf(n/try, &temp) != 0)
                    148:                        continue;
                    149:                do {
                    150:                        printf("%.0f ", try);
                    151:                        n = temp;
                    152:                } while (modf(n/try, &temp) == 0);
                    153:                limit = sqrt(n);
                    154:        }
                    155:        if (n > 1)
                    156:                printf("%.0f", n);
                    157:        putchar('\n');
                    158: }

unix.superglobalmegacorp.com

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