DataMuseum.dk

Presents historical artifacts from the history of:

Commodore CBM-900

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about Commodore CBM-900

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - download

⟦35244904e⟧ TextFile

    Length: 3058 (0xbf2)
    Types: TextFile
    Notes: UNIX file
    Names: »factor.c«

Derivation

└─⟦f27320a65⟧ Bits:30001972 Commodore 900 hard disk image with partial source code
    └─⟦f4b8d8c84⟧ UNIX V7 Filesystem
        └─ ⟦this⟧ »cmd/factor.c« 

TextFile

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