|
DataMuseum.dkPresents historical artifacts from the history of: Commodore CBM-900 |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about Commodore CBM-900 Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - download
Length: 3058 (0xbf2) Types: TextFile Notes: UNIX file Names: »factor.c«
└─⟦f27320a65⟧ Bits:30001972 Commodore 900 hard disk image with partial source code └─⟦f4b8d8c84⟧ UNIX Filesystem └─ ⟦this⟧ »cmd/factor.c«
/* * Factor prints out the prime factorization of numbers. If there are * any arguments, then it factors these. If there are no arguments, * then it reads stdin until either EOF or the number zero or a non-numeric * non-white-space character. Since factor does all of its calculations * in double format, the largest number which can be handled is quite * large. */ #include <stdio.h> #include <math.h> #include <ctype.h> #define NUL '\0' #define ERROR 0x10 /* largest input base */ #define MAXNUM 200 /* max number of chars in number */ main(argc, argv) int argc; register char *argv[]; { register char *chp; double n; double atod(); char *getnum(); if (argc != 1) while ((chp=*++argv) != NULL && (n=atod(chp)) != 0) factor(n); else while ((chp=getnum()) != NULL && (n=atod(chp)) != 0) factor(n); return (0); } die(str) char *str; { fprintf(stderr, "%r\n", &str); exit(1); } usage() { die("usage: factor [number number ...]"); } char * getnum() { register char *chp, ch; static char res[MAXNUM+1]; do { ch = getchar(); } while (isascii(ch) && isspace(ch)); if (!isascii(ch) || todigit(ch) == ERROR) return (NULL); for (chp=res; isascii(ch) && !isspace(ch); ch=getchar()) if (chp < &res[MAXNUM]) *chp++ = ch; if (chp >= &res[MAXNUM]) die("Number too big"); *chp++ = NUL; return (res); } /* * Atod converts the string `num' to a double and returns the value. * Note, that if there is a non-digit in the string, or if there is * an overflow, then it exits with an appropriate error message. * Also note that atod accepts leading zero for octal and leading * 0x for hexidecimal, and that in the latter case, a-f and A-F are * both accepted as digits. */ double atod(num) char *num; { register char *str; register int i; double res = 0, base = 10; str = num; i = *str++; if (i == '0') if ((i=*str++) == 'x') { i = *str++; base = 0x10; } else base = 010; for (; i != NULL; i=*str++) { i = todigit(i); if (i >= base) die("bad number `%s'", num); res = res * base + i; if (res+1 == res) die("Number too big `%s'", num); } return (res); } /* * Todigit converts the char `ch' to an integer equivalent, assuming * that `ch' is a digit or `a'-`f' or `A'-`F'. If this is not true, * then it returns ERROR. */ todigit(ch) register int ch; { if (!isascii(ch)) return (ERROR); if (isdigit(ch)) return (ch - '0' + 0); if (isupper(ch)) ch = tolower(ch); if ('a' <= ch && ch <= 'f') return (ch - 'a' + 0xa); return (ERROR); } /* * Factor is the routine that actually factors the double `n'. * It writes the prime factors to standard output. */ factor(n) double n; { double temp, limit, try; while (n > 1 && modf(n/2, &temp) == 0) { printf("2 "); n = temp; } limit = sqrt(n); for (try=3; try <= limit; try += 2) { if (modf(n/try, &temp) != 0) continue; do { printf("%.0f ", try); n = temp; } while (modf(n/try, &temp) == 0); limit = sqrt(n); } if (n > 1) printf("%.0f", n); putchar('\n'); }