|
|
1.1 root 1: /*
2: * Copyright (c) 1989 The Regents of the University of California.
3: * All rights reserved.
4: *
5: * This code is derived from software contributed to Berkeley by
6: * Landon Curt Noll.
7: *
8: * Redistribution and use in source and binary forms are permitted
9: * provided that: (1) source distributions retain this entire copyright
10: * notice and comment, and (2) distributions including binaries display
11: * the following acknowledgement: ``This product includes software
12: * developed by the University of California, Berkeley and its contributors''
13: * in the documentation or other materials provided with the distribution
14: * and in all advertising materials mentioning features or use of this
15: * software. Neither the name of the University nor the names of its
16: * contributors may be used to endorse or promote products derived
17: * from this software without specific prior written permission.
18: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
19: * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
20: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
21: */
22:
23: #ifndef lint
24: char copyright[] =
25: "@(#) Copyright (c) 1989 The Regents of the University of California.\n\
26: All rights reserved.\n";
27: #endif /* not lint */
28:
29: #ifndef lint
30: static char sccsid[] = "@(#)factor.c 4.4 (Berkeley) 6/1/90";
31: #endif /* not lint */
32:
33: /*
34: * factor - factor a number into primes
35: *
36: * By: Landon Curt Noll [email protected], ...!{sun,tolsoft}!hoptoad!chongo
37: *
38: * chongo <for a good prime call: 391581 * 2^216193 - 1> /\oo/\
39: *
40: * usage:
41: * factor [number] ...
42: *
43: * The form of the output is:
44: *
45: * number: factor1 factor1 factor2 factor3 factor3 factor3 ...
46: *
47: * where factor1 < factor2 < factor3 < ...
48: *
49: * If no args are given, the list of numbers are read from stdin.
50: */
51:
52: #include <stdio.h>
53: #include <ctype.h>
54: #include "primes.h"
55:
56: /*
57: * prime[i] is the (i-1)th prime.
58: *
59: * We are able to sieve 2^32-1 because this byte table yields all primes
60: * up to 65537 and 65537^2 > 2^32-1.
61: */
62: extern ubig prime[];
63: extern ubig *pr_limit; /* largest prime in the prime array */
64:
65: #define MAX_LINE 255 /* max line allowed on stdin */
66:
67: void pr_fact(); /* print factors of a value */
68: long small_fact(); /* find smallest factor of a value */
69: char *read_num_buf(); /* read a number buffer */
70: char *program; /* name of this program */
71:
72: main(argc, argv)
73: int argc; /* arg count */
74: char *argv[]; /* the args */
75: {
76: int arg; /* which arg to factor */
77: long val; /* the value to factor */
78: char buf[MAX_LINE+1]; /* input buffer */
79:
80: /* parse args */
81: program = argv[0];
82: if (argc >= 2) {
83:
84: /* factor each arg */
85: for (arg=1; arg < argc; ++arg) {
86:
87: /* process the buffer */
88: if (read_num_buf(NULL, argv[arg]) == NULL) {
89: fprintf(stderr, "%s: ouch\n", program);
90: exit(1);
91: }
92:
93: /* factor the argument */
94: if (sscanf(argv[arg], "%ld", &val) == 1) {
95: pr_fact(val);
96: } else {
97: fprintf(stderr, "%s: ouch\n", program);
98: exit(1);
99: }
100: }
101:
102: /* no args supplied, read numbers from stdin */
103: } else {
104: /*
105: * read asciii numbers from input
106: */
107: while (read_num_buf(stdin, buf) != NULL) {
108:
109: /* factor the argument */
110: if (sscanf(buf, "%ld", &val) == 1) {
111: pr_fact(val);
112: }
113: }
114: }
115: exit(0);
116: }
117:
118: /*
119: * read_num_buf - read a number buffer from a stream
120: *
121: * Read a number on a line of the form:
122: *
123: * ^[ \t]*\([+-]?[0-9][0-9]\)*.*$
124: *
125: * where ? is a 1-or-0 operator and the number is within \( \).
126: *
127: * If does not match the above pattern, it is ignored and a new
128: * line is read. If the number is too large or small, we will
129: * print ouch and read a new line.
130: *
131: * We have to be very careful on how we check the magnitude of the
132: * input. We can not use numeric checks because of the need to
133: * check values against maximum numeric values.
134: *
135: * This routine will return a line containing a ascii number between
136: * NEG_SEMIBIG and SEMIBIG, or it will return NULL.
137: *
138: * If the stream is NULL then buf will be processed as if were
139: * a single line stream.
140: *
141: * returns:
142: * char * pointer to leading digit, + or -
143: * NULL EOF or error
144: */
145: char *
146: read_num_buf(input, buf)
147: FILE *input; /* input stream or NULL */
148: char *buf; /* input buffer */
149: {
150: static char limit[MAX_LINE+1]; /* ascii value of SEMIBIG */
151: static int limit_len; /* digit count of limit */
152: static char neg_limit[MAX_LINE+1]; /* value of NEG_SEMIBIG */
153: static int neg_limit_len; /* digit count of neg_limit */
154: int len; /* digits in input (excluding +/-) */
155: char *s; /* line start marker */
156: char *d; /* first digit, skip +/- */
157: char *p; /* scan pointer */
158: char *z; /* zero scan pointer */
159:
160: /* form the ascii value of SEMIBIG if needed */
161: if (!isascii(limit[0]) || !isdigit(limit[0])) {
162: sprintf(limit, "%ld", SEMIBIG);
163: limit_len = strlen(limit);
164: sprintf(neg_limit, "%ld", NEG_SEMIBIG);
165: neg_limit_len = strlen(neg_limit)-1; /* exclude - */
166: }
167:
168: /*
169: * the search for a good line
170: */
171: if (input != NULL && fgets(buf, MAX_LINE, input) == NULL) {
172: /* error or EOF */
173: return NULL;
174: }
175: do {
176:
177: /* ignore leading whitespace */
178: for (s=buf; *s && s < buf+MAX_LINE; ++s) {
179: if (!isascii(*s) || !isspace(*s)) {
180: break;
181: }
182: }
183:
184: /* skip over any leading + or - */
185: if (*s == '+' || *s == '-') {
186: d = s+1;
187: } else {
188: d = s;
189: }
190:
191: /* note leading zeros */
192: for (z=d; *z && z < buf+MAX_LINE; ++z) {
193: if (*z != '0') {
194: break;
195: }
196: }
197:
198: /* scan for the first non-digit */
199: for (p=d; *p && p < buf+MAX_LINE; ++p) {
200: if (!isascii(*p) || !isdigit(*p)) {
201: break;
202: }
203: }
204:
205: /* ignore empty lines */
206: if (p == d) {
207: continue;
208: }
209: *p = '\0';
210:
211: /* object if too many digits */
212: len = strlen(z);
213: len = (len<=0) ? 1 : len;
214: if (*s == '-') {
215: /* accept if digit count is below limit */
216: if (len < neg_limit_len) {
217: /* we have good input */
218: return s;
219:
220: /* reject very large numbers */
221: } else if (len > neg_limit_len) {
222: fprintf(stderr, "%s: ouch\n", program);
223: exit(1);
224:
225: /* carefully check against near limit numbers */
226: } else if (strcmp(z, neg_limit+1) > 0) {
227: fprintf(stderr, "%s: ouch\n", program);
228: exit(1);
229: }
230: /* number is near limit, but is under it */
231: return s;
232:
233: } else {
234: /* accept if digit count is below limit */
235: if (len < limit_len) {
236: /* we have good input */
237: return s;
238:
239: /* reject very large numbers */
240: } else if (len > limit_len) {
241: fprintf(stderr, "%s: ouch\n", program);
242: exit(1);
243:
244: /* carefully check against near limit numbers */
245: } else if (strcmp(z, limit) > 0) {
246: fprintf(stderr, "%s: ouch\n", program);
247: exit(1);
248: }
249: /* number is near limit, but is under it */
250: return s;
251: }
252: } while (input != NULL && fgets(buf, MAX_LINE, input) != NULL);
253:
254: /* error or EOF */
255: return NULL;
256: }
257:
258:
259: /*
260: * pr_fact - print the factors of a number
261: *
262: * If the number is 0 or 1, then print the number and return.
263: * If the number is < 0, print -1, negate the number and continue
264: * processing.
265: *
266: * Print the factors of the number, from the lowest to the highest.
267: * A factor will be printed numtiple times if it divides the value
268: * multiple times.
269: *
270: * Factors are printed with leading tabs.
271: */
272: void
273: pr_fact(val)
274: long val; /* factor this value */
275: {
276: ubig *fact; /* the factor found */
277:
278: /* firewall - catch 0 and 1 */
279: switch (val) {
280: case -2147483648:
281: /* avoid negation problems */
282: puts("-2147483648: -1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2\n");
283: return;
284: case -1:
285: puts("-1: -1\n");
286: return;
287: case 0:
288: exit(0);
289: case 1:
290: puts("1: 1\n");
291: return;
292: default:
293: if (val < 0) {
294: val = -val;
295: printf("%ld: -1", val);
296: } else {
297: printf("%ld:", val);
298: }
299: fflush(stdout);
300: break;
301: }
302:
303: /*
304: * factor value
305: */
306: fact = &prime[0];
307: while (val > 1) {
308:
309: /* look for the smallest factor */
310: do {
311: if (val%(long)*fact == 0) {
312: break;
313: }
314: } while (++fact <= pr_limit);
315:
316: /* watch for primes larger than the table */
317: if (fact > pr_limit) {
318: printf(" %ld\n", val);
319: return;
320: }
321:
322: /* divide factor out until none are left */
323: do {
324: printf(" %ld", *fact);
325: val /= (long)*fact;
326: } while ((val % (long)*fact) == 0);
327: fflush(stdout);
328: ++fact;
329: }
330: putchar('\n');
331: return;
332: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.