Home | History | Annotate | Line # | Download | only in factor
factor.c revision 1.5
      1  1.5  cgd /*	$NetBSD: factor.c,v 1.5 1995/03/23 08:28:07 cgd Exp $	*/
      2  1.5  cgd 
      3  1.1  cgd /*
      4  1.5  cgd  * Copyright (c) 1989, 1993
      5  1.5  cgd  *	The Regents of the University of California.  All rights reserved.
      6  1.1  cgd  *
      7  1.1  cgd  * This code is derived from software contributed to Berkeley by
      8  1.1  cgd  * Landon Curt Noll.
      9  1.1  cgd  *
     10  1.1  cgd  * Redistribution and use in source and binary forms, with or without
     11  1.1  cgd  * modification, are permitted provided that the following conditions
     12  1.1  cgd  * are met:
     13  1.1  cgd  * 1. Redistributions of source code must retain the above copyright
     14  1.1  cgd  *    notice, this list of conditions and the following disclaimer.
     15  1.1  cgd  * 2. Redistributions in binary form must reproduce the above copyright
     16  1.1  cgd  *    notice, this list of conditions and the following disclaimer in the
     17  1.1  cgd  *    documentation and/or other materials provided with the distribution.
     18  1.1  cgd  * 3. All advertising materials mentioning features or use of this software
     19  1.1  cgd  *    must display the following acknowledgement:
     20  1.1  cgd  *	This product includes software developed by the University of
     21  1.1  cgd  *	California, Berkeley and its contributors.
     22  1.1  cgd  * 4. Neither the name of the University nor the names of its contributors
     23  1.1  cgd  *    may be used to endorse or promote products derived from this software
     24  1.1  cgd  *    without specific prior written permission.
     25  1.1  cgd  *
     26  1.1  cgd  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     27  1.1  cgd  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     28  1.1  cgd  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     29  1.1  cgd  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     30  1.1  cgd  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     31  1.1  cgd  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     32  1.1  cgd  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     33  1.1  cgd  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     34  1.1  cgd  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     35  1.1  cgd  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     36  1.1  cgd  * SUCH DAMAGE.
     37  1.1  cgd  */
     38  1.1  cgd 
     39  1.1  cgd #ifndef lint
     40  1.5  cgd static char copyright[] =
     41  1.5  cgd "@(#) Copyright (c) 1989, 1993\n\
     42  1.5  cgd 	The Regents of the University of California.  All rights reserved.\n";
     43  1.1  cgd #endif /* not lint */
     44  1.1  cgd 
     45  1.1  cgd #ifndef lint
     46  1.5  cgd #if 0
     47  1.5  cgd static char sccsid[] = "@(#)factor.c	8.3 (Berkeley) 3/30/94";
     48  1.5  cgd #else
     49  1.5  cgd static char rcsid[] = "$NetBSD: factor.c,v 1.5 1995/03/23 08:28:07 cgd Exp $";
     50  1.5  cgd #endif
     51  1.1  cgd #endif /* not lint */
     52  1.1  cgd 
     53  1.1  cgd /*
     54  1.1  cgd  * factor - factor a number into primes
     55  1.1  cgd  *
     56  1.1  cgd  * By: Landon Curt Noll   chongo (at) toad.com,   ...!{sun,tolsoft}!hoptoad!chongo
     57  1.1  cgd  *
     58  1.1  cgd  *   chongo <for a good prime call: 391581 * 2^216193 - 1> /\oo/\
     59  1.1  cgd  *
     60  1.1  cgd  * usage:
     61  1.1  cgd  *	factor [number] ...
     62  1.1  cgd  *
     63  1.1  cgd  * The form of the output is:
     64  1.1  cgd  *
     65  1.1  cgd  *	number: factor1 factor1 factor2 factor3 factor3 factor3 ...
     66  1.1  cgd  *
     67  1.1  cgd  * where factor1 < factor2 < factor3 < ...
     68  1.1  cgd  *
     69  1.1  cgd  * If no args are given, the list of numbers are read from stdin.
     70  1.1  cgd  */
     71  1.1  cgd 
     72  1.5  cgd #include <err.h>
     73  1.5  cgd #include <ctype.h>
     74  1.5  cgd #include <errno.h>
     75  1.5  cgd #include <limits.h>
     76  1.1  cgd #include <stdio.h>
     77  1.5  cgd #include <stdlib.h>
     78  1.5  cgd 
     79  1.1  cgd #include "primes.h"
     80  1.1  cgd 
     81  1.1  cgd /*
     82  1.1  cgd  * prime[i] is the (i-1)th prime.
     83  1.1  cgd  *
     84  1.1  cgd  * We are able to sieve 2^32-1 because this byte table yields all primes
     85  1.1  cgd  * up to 65537 and 65537^2 > 2^32-1.
     86  1.1  cgd  */
     87  1.1  cgd extern ubig prime[];
     88  1.5  cgd extern ubig *pr_limit;		/* largest prime in the prime array */
     89  1.1  cgd 
     90  1.5  cgd void	pr_fact __P((ubig));	/* print factors of a value */
     91  1.5  cgd void	usage __P((void));
     92  1.1  cgd 
     93  1.5  cgd int
     94  1.1  cgd main(argc, argv)
     95  1.5  cgd 	int argc;
     96  1.5  cgd 	char *argv[];
     97  1.1  cgd {
     98  1.5  cgd 	ubig val;
     99  1.5  cgd 	int ch;
    100  1.5  cgd 	char *p, buf[100];		/* > max number of digits. */
    101  1.5  cgd 
    102  1.5  cgd 	while ((ch = getopt(argc, argv, "")) != EOF)
    103  1.5  cgd 		switch (ch) {
    104  1.5  cgd 		case '?':
    105  1.5  cgd 		default:
    106  1.5  cgd 			usage();
    107  1.5  cgd 		}
    108  1.5  cgd 	argc -= optind;
    109  1.5  cgd 	argv += optind;
    110  1.5  cgd 
    111  1.5  cgd 	/* No args supplied, read numbers from stdin. */
    112  1.5  cgd 	if (argc == 0)
    113  1.5  cgd 		for (;;) {
    114  1.5  cgd 			if (fgets(buf, sizeof(buf), stdin) == NULL) {
    115  1.5  cgd 				if (ferror(stdin))
    116  1.5  cgd 					err(1, "stdin");
    117  1.5  cgd 				exit (0);
    118  1.5  cgd 			}
    119  1.5  cgd 			for (p = buf; isblank(*p); ++p);
    120  1.5  cgd 			if (*p == '\n' || *p == '\0')
    121  1.5  cgd 				continue;
    122  1.5  cgd 			if (*p == '-')
    123  1.5  cgd 				errx(1, "negative numbers aren't permitted.");
    124  1.5  cgd 			errno = 0;
    125  1.5  cgd 			val = strtoul(buf, &p, 10);
    126  1.5  cgd 			if (errno)
    127  1.5  cgd 				err(1, "%s", buf);
    128  1.5  cgd 			if (*p != '\n')
    129  1.5  cgd 				errx(1, "%s: illegal numeric format.", buf);
    130  1.5  cgd 			pr_fact(val);
    131  1.5  cgd 		}
    132  1.5  cgd 	/* Factor the arguments. */
    133  1.5  cgd 	else
    134  1.5  cgd 		for (; *argv != NULL; ++argv) {
    135  1.5  cgd 			if (argv[0][0] == '-')
    136  1.5  cgd 				errx(1, "negative numbers aren't permitted.");
    137  1.5  cgd 			errno = 0;
    138  1.5  cgd 			val = strtoul(argv[0], &p, 10);
    139  1.5  cgd 			if (errno)
    140  1.5  cgd 				err(1, "%s", argv[0]);
    141  1.5  cgd 			if (*p != '\0')
    142  1.5  cgd 				errx(1, "%s: illegal numeric format.", argv[0]);
    143  1.5  cgd 			pr_fact(val);
    144  1.1  cgd 		}
    145  1.1  cgd 	exit(0);
    146  1.1  cgd }
    147  1.1  cgd 
    148  1.1  cgd /*
    149  1.1  cgd  * pr_fact - print the factors of a number
    150  1.1  cgd  *
    151  1.1  cgd  * If the number is 0 or 1, then print the number and return.
    152  1.1  cgd  * If the number is < 0, print -1, negate the number and continue
    153  1.1  cgd  * processing.
    154  1.1  cgd  *
    155  1.1  cgd  * Print the factors of the number, from the lowest to the highest.
    156  1.1  cgd  * A factor will be printed numtiple times if it divides the value
    157  1.1  cgd  * multiple times.
    158  1.1  cgd  *
    159  1.1  cgd  * Factors are printed with leading tabs.
    160  1.1  cgd  */
    161  1.1  cgd void
    162  1.1  cgd pr_fact(val)
    163  1.5  cgd 	ubig val;		/* Factor this value. */
    164  1.1  cgd {
    165  1.5  cgd 	ubig *fact;		/* The factor found. */
    166  1.1  cgd 
    167  1.5  cgd 	/* Firewall - catch 0 and 1. */
    168  1.5  cgd 	if (val == 0)		/* Historical practice; 0 just exits. */
    169  1.1  cgd 		exit(0);
    170  1.5  cgd 	if (val == 1) {
    171  1.5  cgd 		(void)printf("1: 1\n");
    172  1.1  cgd 		return;
    173  1.1  cgd 	}
    174  1.1  cgd 
    175  1.5  cgd 	/* Factor value. */
    176  1.5  cgd 	(void)printf("%lu:", val);
    177  1.5  cgd 	for (fact = &prime[0]; val > 1; ++fact) {
    178  1.5  cgd 		/* Look for the smallest factor. */
    179  1.1  cgd 		do {
    180  1.5  cgd 			if (val % (long)*fact == 0)
    181  1.1  cgd 				break;
    182  1.1  cgd 		} while (++fact <= pr_limit);
    183  1.1  cgd 
    184  1.5  cgd 		/* Watch for primes larger than the table. */
    185  1.1  cgd 		if (fact > pr_limit) {
    186  1.5  cgd 			(void)printf(" %lu", val);
    187  1.5  cgd 			break;
    188  1.1  cgd 		}
    189  1.1  cgd 
    190  1.5  cgd 		/* Divide factor out until none are left. */
    191  1.1  cgd 		do {
    192  1.5  cgd 			(void)printf(" %lu", *fact);
    193  1.1  cgd 			val /= (long)*fact;
    194  1.1  cgd 		} while ((val % (long)*fact) == 0);
    195  1.5  cgd 
    196  1.5  cgd 		/* Let the user know we're doing something. */
    197  1.5  cgd 		(void)fflush(stdout);
    198  1.1  cgd 	}
    199  1.5  cgd 	(void)putchar('\n');
    200  1.5  cgd }
    201  1.5  cgd 
    202  1.5  cgd void
    203  1.5  cgd usage()
    204  1.5  cgd {
    205  1.5  cgd 	(void)fprintf(stderr, "usage: factor [value ...]\n");
    206  1.5  cgd 	exit (0);
    207  1.1  cgd }
    208