mirror of
git://git.sv.gnu.org/coreutils.git
synced 2026-02-21 23:02:05 +02:00
factor: remove --bignum and --no-bignum options
Here's a patch to remove the --bignum and --no-bignum options from 'factor'. The case for removing --bignum isn't as strong as that for 'expr', but still, it seems to me that these options are not needed and complicate the documentation unnecessarily. * doc/coreutils.texi (factor invocation): Remove --bignum, --no-bignum. * src/factor.c (algorithm, ALGORITHM_CHOICE, USE_BIGNUM, NO_USE_BIGNUM): Remove; all uses removed. (extract_factors_multi): Remove, replacing with.... (print_factors_multi): New function, with signature similar to that of new signature of print_factors_single. (print_factors_single): Migrate checking code to caller. (print_factors): Use GMP if it's available; don't bother asking user. Improve accuracy of check for "large" numbers. (long_options, main): Remove support for --bignum.
This commit is contained in:
committed by
Jim Meyering
parent
407e8f0fdd
commit
fec0e89c20
@@ -14654,15 +14654,6 @@ The @command{factor} command supports only a small number of options:
|
||||
Print a short help on standard output, then exit without further
|
||||
processing.
|
||||
|
||||
@item --bignum
|
||||
Always use unlimited precision arithmetic via the GNU MP library.
|
||||
By default, @command{factor} selects between using GNU MP and using
|
||||
native operations on the basis of the length of the number to be factored.
|
||||
|
||||
@item --no-bignum
|
||||
Always use limited-precision native operations, not GNU MP.
|
||||
This causes @command{factor} to fail for larger inputs.
|
||||
|
||||
@item --version
|
||||
Print the program version on standard output, then exit without further
|
||||
processing.
|
||||
|
||||
183
src/factor.c
183
src/factor.c
@@ -49,15 +49,6 @@
|
||||
|
||||
static bool verbose = false;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
ALGO_AUTOSELECT, /* default */
|
||||
ALGO_GMP, /* --bignum */
|
||||
ALGO_SINGLE /* --no-bignum */
|
||||
} ALGORITHM_CHOICE;
|
||||
static ALGORITHM_CHOICE algorithm = ALGO_AUTOSELECT;
|
||||
|
||||
|
||||
#if HAVE_GMP
|
||||
static mpz_t *factor = NULL;
|
||||
static size_t nfactors_found = 0;
|
||||
@@ -266,52 +257,6 @@ S4:
|
||||
mpz_clear (x);
|
||||
mpz_clear (y);
|
||||
}
|
||||
|
||||
/* Arbitrary-precision factoring */
|
||||
static bool
|
||||
extract_factors_multi (char const *s)
|
||||
{
|
||||
unsigned int division_limit;
|
||||
size_t n_bits;
|
||||
mpz_t t;
|
||||
|
||||
mpz_init (t);
|
||||
if (1 != gmp_sscanf (s, "%Zd", t))
|
||||
{
|
||||
error (0, 0, _("%s is not a valid positive integer"), quote (s));
|
||||
return false;
|
||||
}
|
||||
|
||||
printf ("%s:", s);
|
||||
|
||||
if (mpz_sgn (t) == 0)
|
||||
{
|
||||
mpz_clear (t);
|
||||
return true; /* 0; no factors */
|
||||
}
|
||||
|
||||
/* Set the trial division limit according to the size of t. */
|
||||
n_bits = mpz_sizeinbase (t, 2);
|
||||
division_limit = MIN (n_bits, 1000);
|
||||
division_limit *= division_limit;
|
||||
|
||||
factor_using_division (t, division_limit);
|
||||
|
||||
if (mpz_cmp_ui (t, 1) != 0)
|
||||
{
|
||||
debug ("[is number prime?] ");
|
||||
if (mpz_probab_prime_p (t, 3))
|
||||
{
|
||||
emit_factor (t);
|
||||
}
|
||||
else
|
||||
{
|
||||
factor_using_pollard_rho (t, 1);
|
||||
}
|
||||
}
|
||||
mpz_clear (t);
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* The maximum number of factors, including -1, for negative numbers. */
|
||||
@@ -379,30 +324,18 @@ factor_wheel (uintmax_t n0, size_t max_n_factors, uintmax_t *factors)
|
||||
}
|
||||
|
||||
/* Single-precision factoring */
|
||||
static bool
|
||||
print_factors_single (char const *s)
|
||||
static void
|
||||
print_factors_single (uintmax_t n)
|
||||
{
|
||||
uintmax_t factors[MAX_N_FACTORS];
|
||||
uintmax_t n;
|
||||
size_t n_factors;
|
||||
size_t n_factors = factor_wheel (n, MAX_N_FACTORS, factors);
|
||||
size_t i;
|
||||
char buf[INT_BUFSIZE_BOUND (uintmax_t)];
|
||||
strtol_error err;
|
||||
|
||||
if ((err = xstrtoumax (s, NULL, 10, &n, "")) != LONGINT_OK)
|
||||
{
|
||||
if (err == LONGINT_OVERFLOW)
|
||||
error (0, 0, _("%s is too large"), quote (s));
|
||||
else
|
||||
error (0, 0, _("%s is not a valid positive integer"), quote (s));
|
||||
return false;
|
||||
}
|
||||
n_factors = factor_wheel (n, MAX_N_FACTORS, factors);
|
||||
printf ("%s:", umaxtostr (n, buf));
|
||||
for (i = 0; i < n_factors; i++)
|
||||
printf (" %s", umaxtostr (factors[i], buf));
|
||||
putchar ('\n');
|
||||
return true;
|
||||
}
|
||||
|
||||
#if HAVE_GMP
|
||||
@@ -450,67 +383,93 @@ free_factors (void)
|
||||
nfactors_found = 0;
|
||||
}
|
||||
|
||||
/* Arbitrary-precision factoring */
|
||||
static void
|
||||
print_factors_multi (mpz_t t)
|
||||
{
|
||||
mpz_out_str (stdout, 10, t);
|
||||
putchar (':');
|
||||
|
||||
if (mpz_sgn (t) != 0)
|
||||
{
|
||||
/* Set the trial division limit according to the size of t. */
|
||||
size_t n_bits = mpz_sizeinbase (t, 2);
|
||||
unsigned int division_limit = MIN (n_bits, 1000);
|
||||
division_limit *= division_limit;
|
||||
|
||||
factor_using_division (t, division_limit);
|
||||
|
||||
if (mpz_cmp_ui (t, 1) != 0)
|
||||
{
|
||||
debug ("[is number prime?] ");
|
||||
if (mpz_probab_prime_p (t, 3))
|
||||
emit_factor (t);
|
||||
else
|
||||
factor_using_pollard_rho (t, 1);
|
||||
}
|
||||
}
|
||||
|
||||
mpz_clear (t);
|
||||
sort_and_print_factors ();
|
||||
free_factors ();
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/* Emit the factors of the indicated number. If we have the option of using
|
||||
either algorithm, we select on the basis of the length of the number.
|
||||
For longer numbers, we prefer the MP algorithm even if the native algorithm
|
||||
has enough digits, because the algorithm is better. The turnover point
|
||||
depends on the value as well as the length, but since we don't already know
|
||||
if the number presented has small factors, we just switch over at 6 digits.
|
||||
*/
|
||||
has enough digits, because the algorithm is better. The turnover point
|
||||
depends on the value. */
|
||||
static bool
|
||||
print_factors (char const *s)
|
||||
{
|
||||
if (ALGO_AUTOSELECT == algorithm)
|
||||
uintmax_t n;
|
||||
strtol_error err = xstrtoumax (s, NULL, 10, &n, "");
|
||||
|
||||
#if HAVE_GMP
|
||||
enum { GMP_TURNOVER_POINT = 100000 };
|
||||
|
||||
if (err == LONGINT_OVERFLOW
|
||||
|| (err == LONGINT_OK && GMP_TURNOVER_POINT <= n))
|
||||
{
|
||||
const size_t digits = strlen (s); /* upper limit on number of digits */
|
||||
algorithm = digits < 6 ? ALGO_SINGLE : ALGO_GMP;
|
||||
}
|
||||
if (ALGO_GMP == algorithm)
|
||||
{
|
||||
debug ("[%s]", _("using arbitrary-precision arithmetic"));
|
||||
if (extract_factors_multi (s))
|
||||
mpz_t t;
|
||||
mpz_init (t);
|
||||
if (gmp_sscanf (s, "%Zd", t) == 1)
|
||||
{
|
||||
sort_and_print_factors ();
|
||||
free_factors ();
|
||||
debug ("[%s]", _("using arbitrary-precision arithmetic"));
|
||||
print_factors_multi (t);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
err = LONGINT_INVALID;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
|
||||
switch (err)
|
||||
{
|
||||
case LONGINT_OK:
|
||||
debug ("[%s]", _("using single-precision arithmetic"));
|
||||
return print_factors_single (s);
|
||||
}
|
||||
}
|
||||
#else
|
||||
static bool
|
||||
print_factors (const char *s) /* Single-precision only. */
|
||||
{
|
||||
if (ALGO_GMP == algorithm)
|
||||
{
|
||||
error (0, 0, _("arbitrary-precision arithmetic is not available"));
|
||||
print_factors_single (n);
|
||||
return true;
|
||||
|
||||
case LONGINT_OVERFLOW:
|
||||
error (0, 0, _("%s is too large"), quote (s));
|
||||
return false;
|
||||
|
||||
default:
|
||||
error (0, 0, _("%s is not a valid positive integer"), quote (s));
|
||||
return false;
|
||||
}
|
||||
return print_factors_single (s);
|
||||
}
|
||||
#endif
|
||||
|
||||
enum
|
||||
{
|
||||
VERBOSE_OPTION = CHAR_MAX + 1,
|
||||
USE_BIGNUM,
|
||||
NO_USE_BIGNUM
|
||||
VERBOSE_OPTION = CHAR_MAX + 1
|
||||
};
|
||||
|
||||
static struct option const long_options[] =
|
||||
{
|
||||
{"verbose", no_argument, NULL, VERBOSE_OPTION},
|
||||
{"bignum", no_argument, NULL, USE_BIGNUM},
|
||||
{"no-bignum", no_argument, NULL, NO_USE_BIGNUM},
|
||||
{GETOPT_HELP_OPTION_DECL},
|
||||
{GETOPT_VERSION_OPTION_DECL},
|
||||
{NULL, 0, NULL, 0}
|
||||
@@ -534,10 +493,6 @@ Print the prime factors of each specified integer NUMBER. If none\n\
|
||||
are specified on the command line, read them from standard input.\n\
|
||||
\n\
|
||||
"), stdout);
|
||||
fputs (_("\
|
||||
--bignum always use arbitrary-precision arithmetic\n\
|
||||
--no-bignum always use single-precision arithmetic\n"),
|
||||
stdout);
|
||||
fputs (HELP_OPTION_DESCRIPTION, stdout);
|
||||
fputs (VERSION_OPTION_DESCRIPTION, stdout);
|
||||
emit_bug_reporting_address ();
|
||||
@@ -588,14 +543,6 @@ main (int argc, char **argv)
|
||||
verbose = true;
|
||||
break;
|
||||
|
||||
case USE_BIGNUM:
|
||||
algorithm = ALGO_GMP;
|
||||
break;
|
||||
|
||||
case NO_USE_BIGNUM:
|
||||
algorithm = ALGO_SINGLE;
|
||||
break;
|
||||
|
||||
case_GETOPT_HELP_CHAR;
|
||||
|
||||
case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
|
||||
|
||||
Reference in New Issue
Block a user