]>
git.cameronkatri.com Git - bsdgames-darwin.git/blob - factor/factor.c
2 * Copyright (c) 1989 The Regents of the University of California.
5 * This code is derived from software contributed to Berkeley by
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by the University of
19 * California, Berkeley and its contributors.
20 * 4. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
39 "@(#) Copyright (c) 1989 The Regents of the University of California.\n\
40 All rights reserved.\n";
44 static char sccsid
[] = "@(#)factor.c 4.4 (Berkeley) 6/1/90";
48 * factor - factor a number into primes
50 * By: Landon Curt Noll chongo@toad.com, ...!{sun,tolsoft}!hoptoad!chongo
52 * chongo <for a good prime call: 391581 * 2^216193 - 1> /\oo/\
57 * The form of the output is:
59 * number: factor1 factor1 factor2 factor3 factor3 factor3 ...
61 * where factor1 < factor2 < factor3 < ...
63 * If no args are given, the list of numbers are read from stdin.
71 * prime[i] is the (i-1)th prime.
73 * We are able to sieve 2^32-1 because this byte table yields all primes
74 * up to 65537 and 65537^2 > 2^32-1.
77 extern ubig
*pr_limit
; /* largest prime in the prime array */
79 #define MAX_LINE 255 /* max line allowed on stdin */
81 void pr_fact(); /* print factors of a value */
82 long small_fact(); /* find smallest factor of a value */
83 char *read_num_buf(); /* read a number buffer */
84 char *program
; /* name of this program */
87 int argc
; /* arg count */
88 char *argv
[]; /* the args */
90 int arg
; /* which arg to factor */
91 long val
; /* the value to factor */
92 char buf
[MAX_LINE
+1]; /* input buffer */
99 for (arg
=1; arg
< argc
; ++arg
) {
101 /* process the buffer */
102 if (read_num_buf(NULL
, argv
[arg
]) == NULL
) {
103 fprintf(stderr
, "%s: ouch\n", program
);
107 /* factor the argument */
108 if (sscanf(argv
[arg
], "%ld", &val
) == 1) {
111 fprintf(stderr
, "%s: ouch\n", program
);
116 /* no args supplied, read numbers from stdin */
119 * read asciii numbers from input
121 while (read_num_buf(stdin
, buf
) != NULL
) {
123 /* factor the argument */
124 if (sscanf(buf
, "%ld", &val
) == 1) {
133 * read_num_buf - read a number buffer from a stream
135 * Read a number on a line of the form:
137 * ^[ \t]*\([+-]?[0-9][0-9]\)*.*$
139 * where ? is a 1-or-0 operator and the number is within \( \).
141 * If does not match the above pattern, it is ignored and a new
142 * line is read. If the number is too large or small, we will
143 * print ouch and read a new line.
145 * We have to be very careful on how we check the magnitude of the
146 * input. We can not use numeric checks because of the need to
147 * check values against maximum numeric values.
149 * This routine will return a line containing a ascii number between
150 * NEG_SEMIBIG and SEMIBIG, or it will return NULL.
152 * If the stream is NULL then buf will be processed as if were
153 * a single line stream.
156 * char * pointer to leading digit, + or -
160 read_num_buf(input
, buf
)
161 FILE *input
; /* input stream or NULL */
162 char *buf
; /* input buffer */
164 static char limit
[MAX_LINE
+1]; /* ascii value of SEMIBIG */
165 static int limit_len
; /* digit count of limit */
166 static char neg_limit
[MAX_LINE
+1]; /* value of NEG_SEMIBIG */
167 static int neg_limit_len
; /* digit count of neg_limit */
168 int len
; /* digits in input (excluding +/-) */
169 char *s
; /* line start marker */
170 char *d
; /* first digit, skip +/- */
171 char *p
; /* scan pointer */
172 char *z
; /* zero scan pointer */
174 /* form the ascii value of SEMIBIG if needed */
175 if (!isascii(limit
[0]) || !isdigit(limit
[0])) {
176 sprintf(limit
, "%ld", SEMIBIG
);
177 limit_len
= strlen(limit
);
178 sprintf(neg_limit
, "%ld", NEG_SEMIBIG
);
179 neg_limit_len
= strlen(neg_limit
)-1; /* exclude - */
183 * the search for a good line
185 if (input
!= NULL
&& fgets(buf
, MAX_LINE
, input
) == NULL
) {
191 /* ignore leading whitespace */
192 for (s
=buf
; *s
&& s
< buf
+MAX_LINE
; ++s
) {
193 if (!isascii(*s
) || !isspace(*s
)) {
198 /* skip over any leading + or - */
199 if (*s
== '+' || *s
== '-') {
205 /* note leading zeros */
206 for (z
=d
; *z
&& z
< buf
+MAX_LINE
; ++z
) {
212 /* scan for the first non-digit */
213 for (p
=d
; *p
&& p
< buf
+MAX_LINE
; ++p
) {
214 if (!isascii(*p
) || !isdigit(*p
)) {
219 /* ignore empty lines */
225 /* object if too many digits */
227 len
= (len
<=0) ? 1 : len
;
229 /* accept if digit count is below limit */
230 if (len
< neg_limit_len
) {
231 /* we have good input */
234 /* reject very large numbers */
235 } else if (len
> neg_limit_len
) {
236 fprintf(stderr
, "%s: ouch\n", program
);
239 /* carefully check against near limit numbers */
240 } else if (strcmp(z
, neg_limit
+1) > 0) {
241 fprintf(stderr
, "%s: ouch\n", program
);
244 /* number is near limit, but is under it */
248 /* accept if digit count is below limit */
249 if (len
< limit_len
) {
250 /* we have good input */
253 /* reject very large numbers */
254 } else if (len
> limit_len
) {
255 fprintf(stderr
, "%s: ouch\n", program
);
258 /* carefully check against near limit numbers */
259 } else if (strcmp(z
, limit
) > 0) {
260 fprintf(stderr
, "%s: ouch\n", program
);
263 /* number is near limit, but is under it */
266 } while (input
!= NULL
&& fgets(buf
, MAX_LINE
, input
) != NULL
);
274 * pr_fact - print the factors of a number
276 * If the number is 0 or 1, then print the number and return.
277 * If the number is < 0, print -1, negate the number and continue
280 * Print the factors of the number, from the lowest to the highest.
281 * A factor will be printed numtiple times if it divides the value
284 * Factors are printed with leading tabs.
288 long val
; /* factor this value */
290 ubig
*fact
; /* the factor found */
292 /* firewall - catch 0 and 1 */
295 /* avoid negation problems */
296 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");
309 printf("%ld: -1", val
);
323 /* look for the smallest factor */
325 if (val
%(long)*fact
== 0) {
328 } while (++fact
<= pr_limit
);
330 /* watch for primes larger than the table */
331 if (fact
> pr_limit
) {
332 printf(" %ld\n", val
);
336 /* divide factor out until none are left */
338 printf(" %ld", *fact
);
340 } while ((val
% (long)*fact
) == 0);