Importing games/factor

Replaces commands/factor. No Minix specific changes needed.

Change-Id: Ie2a58534c59a1ebbf922d483fb27abd8dffd1f5f
This commit is contained in:
Thomas Cort 2014-03-15 16:05:49 -04:00 committed by Lionel Sambuc
parent d1878c29f6
commit c1f592a24c
11 changed files with 502 additions and 86 deletions

View file

@ -8,7 +8,7 @@ SUBDIR= add_route arp ash at backup btrace \
compress cp crc cron crontab \
dd decomp16 DESCRIBE devmand devsize dhcpd \
dhrystone diff diskctl \
eject factor fbdctl \
eject fbdctl \
find fix format fortune fsck.mfs \
gcov-pull grep host \
hostaddr ifconfig ifdef \

View file

@ -1,4 +0,0 @@
PROG= factor
MAN=
.include <bsd.prog.mk>

View file

@ -1,53 +0,0 @@
/* factor - print the prime factors of a number Author: Andy Tanenbaum */
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char **argv);
long first(long k);
int main(argc, argv)
int argc;
char *argv[];
{
/* Factor a number */
long i, n, flag = 0;
if (argc != 2 || (n = atol(argv[1])) < 2) {
printf("Usage: factor n (2 <= n < 2**31)\n");
exit(1);
}
if (n == 2) {
printf("2 is a prime\n");
exit(0);
}
while (1) {
i = first(n);
if (i == 0) {
if (flag == 0)
printf("%ld is a prime\n", n);
else
printf("%ld\n", n);
exit(0);
}
printf("%ld ", i);
n = n / i;
flag = 1;
}
}
long first(k)
long k;
{
/* Return the first factor of k. If it is a prime, return 0; */
long i;
if (k == 2) return(0);
if (k % 2 == 0) return (2);
for (i = 3; i <= k / 3; i += 2)
if (k % i == 0) return(i);
return(0);
}

View file

@ -289,7 +289,6 @@
./usr/bin/env minix-sys
./usr/bin/ex minix-sys
./usr/bin/expand minix-sys
./usr/bin/factor minix-sys
./usr/bin/false minix-sys
./usr/bin/fbdctl minix-sys
./usr/bin/fdisk minix-sys
@ -558,6 +557,7 @@
./usr/etc/rc minix-sys
./usr/games minix-sys
./usr/games/adventure minix-sys
./usr/games/factor minix-sys
./usr/games/hide minix-sys
./usr/games/primes minix-sys
./usr/include minix-sys
@ -2041,7 +2041,6 @@
./usr/man/man1/expand.1 minix-sys
./usr/man/man1/export.1 minix-sys
./usr/man/man1/expr.1 minix-sys
./usr/man/man1/factor.1 minix-sys
./usr/man/man1/false.1 minix-sys
./usr/man/man1/fetch.1 minix-sys
./usr/man/man1/fgrep.1 minix-sys
@ -4751,6 +4750,7 @@
./usr/man/man5/utmp.5 minix-sys
./usr/man/man6 minix-sys
./usr/man/man6/adventure.6 minix-sys
./usr/man/man6/factor.6 minix-sys
./usr/man/man6/primes.6 minix-sys
./usr/man/man7 minix-sys
./usr/man/man7/ascii.7 minix-sys

View file

@ -10,7 +10,7 @@
SUBDIR= adventure \
\
\
\
factor \
\
primes

22
games/factor/Makefile Normal file
View file

@ -0,0 +1,22 @@
# $NetBSD: Makefile,v 1.12 2005/03/09 03:11:21 christos Exp $
# @(#)Makefile 8.1 (Berkeley) 5/31/93
# For MKCRYPTO
.include <bsd.own.mk>
PRIMES= ${NETBSDSRCDIR}/games/primes
PROG= factor
SRCS= factor.c pr_tbl.c
CPPFLAGS+=-I${PRIMES}
.if (${MKCRYPTO} != "no")
CPPFLAGS+=-DHAVE_OPENSSL
LDADD+= -lcrypto -lcrypt
DPADD+= ${LIBCRYPTO} ${LIBCRYPT}
.endif
MAN= factor.6
.PATH: ${PRIMES}
.include <bsd.prog.mk>

97
games/factor/factor.6 Normal file
View file

@ -0,0 +1,97 @@
.\" $NetBSD: factor.6,v 1.12 2010/05/15 21:22:39 joerg Exp $
.\"
.\" Copyright (c) 1989, 1993
.\" The Regents of the University of California. All rights reserved.
.\"
.\" This code is derived from software contributed to Berkeley by
.\" Landon Curt Noll.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\" 3. Neither the name of the University nor the names of its contributors
.\" may be used to endorse or promote products derived from this software
.\" without specific prior written permission.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\" @(#)factor.6 8.1 (Berkeley) 5/31/93
.\"
.\"
.\" By: Landon Curt Noll chongo@toad.com, ...!{sun,tolsoft}!hoptoad!chongo
.\"
.\" chongo <for a good prime call: 391581 * 2^216193 - 1> /\oo/\
.\"
.Dd May 15, 2010
.Dt FACTOR 6
.Os
.Sh NAME
.Nm factor
.Nd factor a number
.Sh SYNOPSIS
.Nm
.Op Ar number ...
.Sh DESCRIPTION
The
.Nm
utility factors integers larger than 1.
When a number is factored, it is printed, followed by a
.Dq \&: ,
and the list of
.Pq prime
factors on a single line.
Factors are listed in ascending order, and are preceded by a space.
If a factor divides a value more than once, it will be printed more than once.
.Pp
When
.Nm
is invoked with one or more arguments, each argument will be factored.
.Pp
When
.Nm
is invoked with no arguments,
.Nm
reads numbers, one per line, from standard input, until end of file or error.
Leading white-space and empty lines are ignored.
Numbers may be preceded by a single +.
Integer less than 2 are rejected.
Numbers are terminated by a non-digit character (such as a newline).
After a number is read, it is factored.
Input lines must not be longer than
.Dv LINE_MAX \- 1
(currently 2047) characters.
.Pp
By default,
.Nm
is compiled against the OpenSSL bignum implementation
.Xr openssl_bn 3 ,
which lets it handle arbitrarily large values.
.Pq Note however that very large values can take a very long time to factor.
If
.Nm
is compiled without OpenSSL it is limited to the maximum value of
.Vt unsigned long .
.Sh DIAGNOSTICS
Out of range or invalid input results in
an appropriate error message
being written to standard error.
.\".Sh BUGS
.\".Nm
.\"cannot handle the
.\".Dq 10 most wanted
.\"factor list.

378
games/factor/factor.c Normal file
View file

@ -0,0 +1,378 @@
/* $NetBSD: factor.c,v 1.26 2011/11/09 20:17:44 drochner Exp $ */
/*
* Copyright (c) 1989, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Landon Curt Noll.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
#ifndef lint
__COPYRIGHT("@(#) Copyright (c) 1989, 1993\
The Regents of the University of California. All rights reserved.");
#endif /* not lint */
#ifndef lint
#if 0
static char sccsid[] = "@(#)factor.c 8.4 (Berkeley) 5/4/95";
#else
__RCSID("$NetBSD: factor.c,v 1.26 2011/11/09 20:17:44 drochner Exp $");
#endif
#endif /* not lint */
/*
* factor - factor a number into primes
*
* By: Landon Curt Noll chongo@toad.com, ...!{sun,tolsoft}!hoptoad!chongo
*
* chongo <for a good prime call: 391581 * 2^216193 - 1> /\oo/\
*
* usage:
* factor [number] ...
*
* The form of the output is:
*
* number: factor1 factor1 factor2 factor3 factor3 factor3 ...
*
* where factor1 <= factor2 <= factor3 <= ...
*
* If no args are given, the list of numbers are read from stdin.
*/
#include <ctype.h>
#include <err.h>
#include <errno.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#ifdef HAVE_OPENSSL
#include <openssl/bn.h>
#else
typedef long BIGNUM;
typedef u_long BN_ULONG;
static int BN_dec2bn(BIGNUM **a, const char *str);
#define BN_new() ((BIGNUM *)calloc(sizeof(BIGNUM), 1))
#define BN_is_zero(v) (*(v) == 0)
#define BN_is_one(v) (*(v) == 1)
#define BN_mod_word(a, b) (*(a) % (b))
#endif
#include "primes.h"
/*
* prime[i] is the (i-1)th prime.
*
* We are able to sieve 2^32-1 because this byte table yields all primes
* up to 65537 and 65537^2 > 2^32-1.
*/
extern const ubig prime[];
extern const ubig *pr_limit; /* largest prime in the prime array */
#if 0 /* debugging: limit table use to stress the "pollard" code */
#define pr_limit &prime[0]
#endif
#define PRIME_CHECKS 5
#ifdef HAVE_OPENSSL
static BN_CTX *ctx; /* just use a global context */
#endif
static void pr_fact(BIGNUM *); /* print factors of a value */
static void BN_print_dec_fp(FILE *, const BIGNUM *);
static void usage(void) __dead;
#ifdef HAVE_OPENSSL
static void pollard_rho(BIGNUM *); /* print factors for big numbers */
#else
static char *BN_bn2dec(const BIGNUM *);
static BN_ULONG BN_div_word(BIGNUM *, BN_ULONG);
#endif
#ifndef HAVE_OPENSSL
static int
BN_dec2bn(BIGNUM **a, const char *str)
{
char *p;
errno = 0;
**a = strtoul(str, &p, 10);
if (errno)
err(1, "%s", str);
return (*p == '\n' || *p == '\0');
}
#endif
int
main(int argc, char *argv[])
{
BIGNUM *val;
int ch;
char *p, buf[LINE_MAX]; /* > max number of digits. */
#ifdef HAVE_OPENSSL
ctx = BN_CTX_new();
#endif
val = BN_new();
if (val == NULL)
errx(1, "can't initialise bignum");
while ((ch = getopt(argc, argv, "")) != -1)
switch (ch) {
case '?':
default:
usage();
}
argc -= optind;
argv += optind;
/* No args supplied, read numbers from stdin. */
if (argc == 0)
for (;;) {
if (fgets(buf, sizeof(buf), stdin) == NULL) {
if (ferror(stdin))
err(1, "stdin");
exit (0);
}
for (p = buf; isblank((unsigned char)*p); ++p);
if (*p == '\n' || *p == '\0')
continue;
if (*p == '-')
errx(1, "negative numbers aren't permitted.");
if (BN_dec2bn(&val, buf) == 0)
errx(1, "%s: illegal numeric format.", argv[0]);
pr_fact(val);
}
/* Factor the arguments. */
else
for (; *argv != NULL; ++argv) {
if (argv[0][0] == '-')
errx(1, "numbers <= 1 aren't permitted.");
if (BN_dec2bn(&val, argv[0]) == 0)
errx(1, "%s: illegal numeric format.", argv[0]);
pr_fact(val);
}
exit(0);
}
/*
* pr_fact - print the factors of a number
*
* If the number is 0 or 1, then print the number and return.
* If the number is < 0, print -1, negate the number and continue
* processing.
*
* Print the factors of the number, from the lowest to the highest.
* A factor will be printed numtiple times if it divides the value
* multiple times.
*
* Factors are printed with leading tabs.
*/
static void
pr_fact(BIGNUM *val)
{
const ubig *fact; /* The factor found. */
/* Firewall - catch 0 and 1. */
if (BN_is_zero(val) || BN_is_one(val))
errx(1, "numbers <= 1 aren't permitted.");
/* Factor value. */
BN_print_dec_fp(stdout, val);
putchar(':');
for (fact = &prime[0]; !BN_is_one(val); ++fact) {
/* Look for the smallest factor. */
while (fact <= pr_limit) {
if (BN_mod_word(val, (BN_ULONG)*fact) == 0)
break;
fact++;
}
/* Watch for primes larger than the table. */
if (fact > pr_limit) {
#ifdef HAVE_OPENSSL
BIGNUM *bnfact;
bnfact = BN_new();
BN_set_word(bnfact, (BN_ULONG)*(fact - 1));
BN_sqr(bnfact, bnfact, ctx);
if (BN_cmp(bnfact, val) > 0
|| BN_is_prime(val, PRIME_CHECKS, NULL, NULL,
NULL) == 1) {
putchar(' ');
BN_print_dec_fp(stdout, val);
} else
pollard_rho(val);
#else
printf(" %s", BN_bn2dec(val));
#endif
break;
}
/* Divide factor out until none are left. */
do {
printf(" %lu", *fact);
BN_div_word(val, (BN_ULONG)*fact);
} while (BN_mod_word(val, (BN_ULONG)*fact) == 0);
/* Let the user know we're doing something. */
fflush(stdout);
}
putchar('\n');
}
/*
* Sigh.. No _decimal_ output to file functions in BN.
*/
static void
BN_print_dec_fp(FILE *fp, const BIGNUM *num)
{
char *buf;
buf = BN_bn2dec(num);
if (buf == NULL)
return; /* XXX do anything here? */
fprintf(fp, "%s", buf);
free(buf);
}
void
usage(void)
{
fprintf(stderr, "usage: factor [value ...]\n");
exit (0);
}
#ifdef HAVE_OPENSSL
static void
pollard_rho(BIGNUM *val)
{
BIGNUM *x, *y, *tmp, *num;
BN_ULONG a;
unsigned int steps_taken, steps_limit;
x = BN_new();
y = BN_new();
tmp = BN_new();
num = BN_new();
a = 1;
restart:
steps_taken = 0;
steps_limit = 2;
BN_set_word(x, 1);
BN_copy(y, x);
for (;;) {
BN_sqr(tmp, x, ctx);
BN_add_word(tmp, a);
BN_mod(x, tmp, val, ctx);
BN_sub(tmp, x, y);
if (BN_is_zero(tmp)) {
#ifdef DEBUG
printf(" (loop)");
#endif
a++;
goto restart;
}
BN_gcd(tmp, tmp, val, ctx);
if (!BN_is_one(tmp)) {
if (BN_is_prime(tmp, PRIME_CHECKS, NULL, NULL,
NULL) == 1) {
putchar(' ');
BN_print_dec_fp(stdout, tmp);
} else {
#ifdef DEBUG
printf(" (recurse for ");
BN_print_dec_fp(stdout, tmp);
putchar(')');
#endif
pollard_rho(BN_dup(tmp));
#ifdef DEBUG
printf(" (back)");
#endif
}
fflush(stdout);
BN_div(num, NULL, val, tmp, ctx);
if (BN_is_one(num))
return;
if (BN_is_prime(num, PRIME_CHECKS, NULL, NULL,
NULL) == 1) {
putchar(' ');
BN_print_dec_fp(stdout, num);
fflush(stdout);
return;
}
BN_copy(val, num);
goto restart;
}
steps_taken++;
if (steps_taken == steps_limit) {
BN_copy(y, x); /* teleport the turtle */
steps_taken = 0;
steps_limit *= 2;
if (steps_limit == 0) {
#ifdef DEBUG
printf(" (overflow)");
#endif
a++;
goto restart;
}
}
}
}
#else
char *
BN_bn2dec(const BIGNUM *val)
{
char *buf;
buf = malloc(100);
if (!buf)
return buf;
snprintf(buf, 100, "%ld", (long)*val);
return buf;
}
static BN_ULONG
BN_div_word(BIGNUM *a, BN_ULONG b)
{
BN_ULONG mod;
mod = *a % b;
*a /= b;
return mod;
}
#endif

View file

@ -4,7 +4,6 @@ MAN= ash.1 at.1 \
cp.1 crc.1 crontab.1 dd.1 \
dhrystone.1 dosdir.1 dosread.1 doswrite.1 \
eject.1 \
factor.1 \
flexdoc.1 format.1 fortune.1 \
fsck.mfs.1 host.1 hostaddr.1 ifdef.1 \
isodir.1 isoinfo.1 isoread.1 \

View file

@ -1,24 +0,0 @@
.TH FACTOR 1
.SH NAME
factor \- factor an integer less than 2**31
.SH SYNOPSIS
\fBfactor \fInumber\fR
.br
.de FL
.TP
\\fB\\$1\\fR
\\$2
..
.de EX
.TP 20
\\fB\\$1\\fR
# \\$2
..
.SH EXAMPLES
.TP 20
.B factor 450180
# Print the prime factors of 450180
.SH DESCRIPTION
.PP
\fIFactor\fR prints the prime factors of its argument in increasing order.
Each factor is printed as many times as it appears in the number.

View file

@ -69,6 +69,7 @@
2013/12/1 12:00:00,external/public-domain
2013/12/1 12:00:00,external/README
2013/12/1 12:00:00,games/adventure
2013/12/1 12:00:00,games/factor
2013/12/1 12:00:00,games/Makefile
2013/12/1 12:00:00,games/Makefile.inc
2013/12/1 12:00:00,games/primes