Annotation of coherent/d/bin/factor.c, revision 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.