|
|
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 - metrics - 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');
}