mirror of
git://git.sv.gnu.org/coreutils.git
synced 2026-06-01 23:36:29 +02:00
maint: use Gnulib libgmp module
This lets use assume multiple-precision arithmetic on all platforms, simplifying the code. * bootstrap.conf (gnulib_modules): Add libgmp. * configure.ac: Don’t call cu_GMP, as this is now done by Gnulib. * m4/gmp.m4: Remove. * src/expr.c, src/factor.c: Use gmp.h unconditionally. * src/factor.c: Use the simpler ‘#ifndef mpz_inits’ to determine whether there is an mpz_inits macro.
This commit is contained in:
@@ -144,6 +144,7 @@ gnulib_modules="
|
||||
lchown
|
||||
ldtoastr
|
||||
lib-ignore
|
||||
libgmp
|
||||
linebuffer
|
||||
link
|
||||
link-follow
|
||||
|
||||
@@ -474,8 +474,6 @@ AC_CHECK_DECLS([strsignal, sys_siglist, _sys_siglist, __sys_siglist], , ,
|
||||
[AC_INCLUDES_DEFAULT
|
||||
#include <signal.h>])
|
||||
|
||||
cu_GMP
|
||||
|
||||
# Build df only if there's a point to it.
|
||||
if test $gl_cv_list_mounted_fs = yes && test $gl_cv_fs_space = yes; then
|
||||
gl_ADD_PROG([optional_bin_progs], [df])
|
||||
|
||||
@@ -1,48 +0,0 @@
|
||||
# Tests for GNU GMP (or any compatible replacement).
|
||||
|
||||
dnl Copyright (C) 2008-2020 Free Software Foundation, Inc.
|
||||
|
||||
dnl This file is free software; the Free Software Foundation
|
||||
dnl gives unlimited permission to copy and/or distribute it,
|
||||
dnl with or without modifications, as long as this notice is preserved.
|
||||
|
||||
dnl Written by James Youngman.
|
||||
|
||||
dnl Check for libgmp. We avoid use of AC_CHECK_LIBS because we don't want to
|
||||
dnl add this to $LIBS for all targets.
|
||||
AC_DEFUN([cu_GMP],
|
||||
[
|
||||
LIB_GMP=
|
||||
AC_SUBST([LIB_GMP])
|
||||
|
||||
AC_ARG_WITH([gmp],
|
||||
AS_HELP_STRING([--without-gmp],
|
||||
[do not use the GNU MP library for arbitrary precision
|
||||
calculation (default: use it if available)]),
|
||||
[cu_use_gmp=$withval],
|
||||
[cu_use_gmp=auto])
|
||||
|
||||
if test $cu_use_gmp != no; then
|
||||
dnl It was noticed on one MacOS X 10.5.8 system at least
|
||||
dnl that the libs were available but the header wasn't
|
||||
HAVE_GMP=0
|
||||
AC_CHECK_HEADERS_ONCE([gmp.h])
|
||||
if test $ac_cv_header_gmp_h = yes; then
|
||||
cu_saved_libs=$LIBS
|
||||
AC_SEARCH_LIBS([__gmpz_init], [gmp],
|
||||
[test "$ac_cv_search___gmpz_init" = "none required" ||
|
||||
LIB_GMP=$ac_cv_search___gmpz_init
|
||||
AC_DEFINE([HAVE_GMP], [1],
|
||||
[Define if you have GNU libgmp (or replacement)])
|
||||
HAVE_GMP=1
|
||||
# This only available in GMP >= 5
|
||||
AC_CHECK_DECLS([mpz_inits], [], [], [[#include <gmp.h>]])
|
||||
])
|
||||
LIBS=$cu_saved_libs
|
||||
fi
|
||||
if test $HAVE_GMP != 1; then
|
||||
AC_MSG_WARN([libgmp development library was not found or not usable.])
|
||||
AC_MSG_WARN([AC_PACKAGE_NAME will be built without GMP support.])
|
||||
fi
|
||||
fi
|
||||
])
|
||||
+2
-109
@@ -33,6 +33,7 @@
|
||||
#include <sys/types.h>
|
||||
#include "system.h"
|
||||
|
||||
#include <gmp.h>
|
||||
#include <regex.h>
|
||||
#include "die.h"
|
||||
#include "error.h"
|
||||
@@ -45,105 +46,6 @@
|
||||
int, the widest unsigned type that GMP supports. */
|
||||
verify (SIZE_MAX <= ULONG_MAX);
|
||||
|
||||
#ifndef HAVE_GMP
|
||||
# define HAVE_GMP 0
|
||||
#endif
|
||||
|
||||
#if HAVE_GMP
|
||||
# include <gmp.h>
|
||||
#else
|
||||
static void integer_overflow (char) ATTRIBUTE_NORETURN;
|
||||
/* Approximate gmp.h well enough for expr.c's purposes. */
|
||||
typedef intmax_t mpz_t[1];
|
||||
static void mpz_clear (mpz_t z) { (void) z; }
|
||||
static void mpz_init_set_ui (mpz_t z, unsigned long int i) { z[0] = i; }
|
||||
static int
|
||||
mpz_init_set_str (mpz_t z, char *s, int base)
|
||||
{
|
||||
return xstrtoimax (s, NULL, base, z, "") == LONGINT_OK ? 0 : -1;
|
||||
}
|
||||
static void
|
||||
mpz_add (mpz_t r, mpz_t a0, mpz_t b0)
|
||||
{
|
||||
intmax_t a = a0[0];
|
||||
intmax_t b = b0[0];
|
||||
intmax_t val = a + b;
|
||||
if ((val < a) != (b < 0))
|
||||
integer_overflow ('+');
|
||||
r[0] = val;
|
||||
}
|
||||
static void
|
||||
mpz_sub (mpz_t r, mpz_t a0, mpz_t b0)
|
||||
{
|
||||
intmax_t a = a0[0];
|
||||
intmax_t b = b0[0];
|
||||
intmax_t val = a - b;
|
||||
if ((a < val) != (b < 0))
|
||||
integer_overflow ('-');
|
||||
r[0] = val;
|
||||
}
|
||||
static void
|
||||
mpz_mul (mpz_t r, mpz_t a0, mpz_t b0)
|
||||
{
|
||||
intmax_t a = a0[0];
|
||||
intmax_t b = b0[0];
|
||||
intmax_t val = a * b;
|
||||
if (! (a == 0 || b == 0
|
||||
|| ((val < 0) == ((a < 0) ^ (b < 0)) && val / a == b)))
|
||||
integer_overflow ('*');
|
||||
r[0] = val;
|
||||
}
|
||||
static void
|
||||
mpz_tdiv_q (mpz_t r, mpz_t a0, mpz_t b0)
|
||||
{
|
||||
intmax_t a = a0[0];
|
||||
intmax_t b = b0[0];
|
||||
|
||||
/* Some x86-style hosts raise an exception for INT_MIN / -1. */
|
||||
if (a < - INTMAX_MAX && b == -1)
|
||||
integer_overflow ('/');
|
||||
r[0] = a / b;
|
||||
}
|
||||
static void
|
||||
mpz_tdiv_r (mpz_t r, mpz_t a0, mpz_t b0)
|
||||
{
|
||||
intmax_t a = a0[0];
|
||||
intmax_t b = b0[0];
|
||||
|
||||
/* Some x86-style hosts raise an exception for INT_MIN % -1. */
|
||||
r[0] = a < - INTMAX_MAX && b == -1 ? 0 : a % b;
|
||||
}
|
||||
static char * _GL_ATTRIBUTE_MALLOC
|
||||
mpz_get_str (char const *str, int base, mpz_t z)
|
||||
{
|
||||
(void) str; (void) base;
|
||||
char buf[INT_BUFSIZE_BOUND (intmax_t)];
|
||||
return xstrdup (imaxtostr (z[0], buf));
|
||||
}
|
||||
static int
|
||||
mpz_sgn (mpz_t z)
|
||||
{
|
||||
return z[0] < 0 ? -1 : 0 < z[0];
|
||||
}
|
||||
static int
|
||||
mpz_fits_ulong_p (mpz_t z)
|
||||
{
|
||||
return 0 <= z[0] && z[0] <= ULONG_MAX;
|
||||
}
|
||||
static unsigned long int
|
||||
mpz_get_ui (mpz_t z)
|
||||
{
|
||||
return z[0];
|
||||
}
|
||||
static int
|
||||
mpz_out_str (FILE *stream, int base, mpz_t z)
|
||||
{
|
||||
(void) base;
|
||||
char buf[INT_BUFSIZE_BOUND (intmax_t)];
|
||||
return fputs (imaxtostr (z[0], buf), stream) != EOF;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* The official name of this program (e.g., no 'g' prefix). */
|
||||
#define PROGRAM_NAME "expr"
|
||||
|
||||
@@ -414,15 +316,6 @@ or 0, 2 if EXPRESSION is syntactically invalid, and 3 if an error occurred.\n\
|
||||
}
|
||||
|
||||
|
||||
#if ! HAVE_GMP
|
||||
/* Report an integer overflow for operation OP and exit. */
|
||||
static void
|
||||
integer_overflow (char op)
|
||||
{
|
||||
die (EXPR_FAILURE, ERANGE, "%c", op);
|
||||
}
|
||||
#endif
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
@@ -603,7 +496,7 @@ toarith (VALUE *v)
|
||||
|
||||
if (! looks_like_integer (s))
|
||||
return false;
|
||||
if (mpz_init_set_str (v->u.i, s, 10) != 0 && !HAVE_GMP)
|
||||
if (mpz_init_set_str (v->u.i, s, 10) != 0)
|
||||
die (EXPR_FAILURE, ERANGE, "%s", (s));
|
||||
free (s);
|
||||
v->type = integer;
|
||||
|
||||
+6
-36
@@ -35,12 +35,6 @@
|
||||
The factoring code for two words will fall into the code for one word when
|
||||
progress allows that.
|
||||
|
||||
Using GMP is optional. Define HAVE_GMP to make this code include GMP
|
||||
factoring code. The GMP factoring code is based on GMP's demos/factorize.c
|
||||
(last synced 2012-09-07). The GMP-based factoring code will stay in GMP
|
||||
factoring code even if numbers get small enough for using the two-word
|
||||
code.
|
||||
|
||||
Algorithm:
|
||||
|
||||
(1) Perform trial division using a small primes table, but without hardware
|
||||
@@ -104,13 +98,7 @@
|
||||
#include <config.h>
|
||||
#include <getopt.h>
|
||||
#include <stdio.h>
|
||||
#if HAVE_GMP
|
||||
# include <gmp.h>
|
||||
# if !HAVE_DECL_MPZ_INITS
|
||||
# include <stdarg.h>
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#include <gmp.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "system.h"
|
||||
@@ -246,14 +234,12 @@ struct factors
|
||||
unsigned char nfactors;
|
||||
};
|
||||
|
||||
#if HAVE_GMP
|
||||
struct mp_factors
|
||||
{
|
||||
mpz_t *p;
|
||||
unsigned long int *e;
|
||||
unsigned long int nfactors;
|
||||
};
|
||||
#endif
|
||||
|
||||
static void factor (uintmax_t, uintmax_t, struct factors *);
|
||||
|
||||
@@ -570,12 +556,12 @@ factor_insert_large (struct factors *factors,
|
||||
factor_insert (factors, p0);
|
||||
}
|
||||
|
||||
#if HAVE_GMP
|
||||
#ifndef mpz_inits
|
||||
|
||||
# if !HAVE_DECL_MPZ_INITS
|
||||
# include <stdarg.h>
|
||||
|
||||
# define mpz_inits(...) mpz_va_init (mpz_init, __VA_ARGS__)
|
||||
# define mpz_clears(...) mpz_va_init (mpz_clear, __VA_ARGS__)
|
||||
# define mpz_inits(...) mpz_va_init (mpz_init, __VA_ARGS__)
|
||||
# define mpz_clears(...) mpz_va_init (mpz_clear, __VA_ARGS__)
|
||||
|
||||
static void
|
||||
mpz_va_init (void (*mpz_single_init)(mpz_t), ...)
|
||||
@@ -590,7 +576,7 @@ mpz_va_init (void (*mpz_single_init)(mpz_t), ...)
|
||||
|
||||
va_end (ap);
|
||||
}
|
||||
# endif
|
||||
#endif
|
||||
|
||||
static void mp_factor (mpz_t, struct mp_factors *);
|
||||
|
||||
@@ -660,7 +646,6 @@ mp_factor_insert_ui (struct mp_factors *factors, unsigned long int prime)
|
||||
mp_factor_insert (factors, pz);
|
||||
mpz_clear (pz);
|
||||
}
|
||||
#endif /* HAVE_GMP */
|
||||
|
||||
|
||||
/* Number of bits in an uintmax_t. */
|
||||
@@ -835,7 +820,6 @@ factor_using_division (uintmax_t *t1p, uintmax_t t1, uintmax_t t0,
|
||||
return t0;
|
||||
}
|
||||
|
||||
#if HAVE_GMP
|
||||
static void
|
||||
mp_factor_using_division (mpz_t t, struct mp_factors *factors)
|
||||
{
|
||||
@@ -872,7 +856,6 @@ mp_factor_using_division (mpz_t t, struct mp_factors *factors)
|
||||
|
||||
mpz_clear (q);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Entry i contains (2i+1)^(-1) mod 2^8. */
|
||||
static const unsigned char binvert_table[128] =
|
||||
@@ -1171,7 +1154,6 @@ millerrabin2 (const uintmax_t *np, uintmax_t ni, const uintmax_t *bp,
|
||||
return false;
|
||||
}
|
||||
|
||||
#if HAVE_GMP
|
||||
static bool
|
||||
mp_millerrabin (mpz_srcptr n, mpz_srcptr nm1, mpz_ptr x, mpz_ptr y,
|
||||
mpz_srcptr q, unsigned long int k)
|
||||
@@ -1191,7 +1173,6 @@ mp_millerrabin (mpz_srcptr n, mpz_srcptr nm1, mpz_ptr x, mpz_ptr y,
|
||||
}
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Lucas' prime test. The number of iterations vary greatly, up to a few dozen
|
||||
have been observed. The average seem to be about 2. */
|
||||
@@ -1377,7 +1358,6 @@ prime2_p (uintmax_t n1, uintmax_t n0)
|
||||
abort ();
|
||||
}
|
||||
|
||||
#if HAVE_GMP
|
||||
static bool
|
||||
mp_prime_p (mpz_t n)
|
||||
{
|
||||
@@ -1460,7 +1440,6 @@ mp_prime_p (mpz_t n)
|
||||
|
||||
return is_prime;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
factor_using_pollard_rho (uintmax_t n, unsigned long int a,
|
||||
@@ -1669,7 +1648,6 @@ factor_using_pollard_rho2 (uintmax_t n1, uintmax_t n0, unsigned long int a,
|
||||
}
|
||||
}
|
||||
|
||||
#if HAVE_GMP
|
||||
static void
|
||||
mp_factor_using_pollard_rho (mpz_t n, unsigned long int a,
|
||||
struct mp_factors *factors)
|
||||
@@ -1761,7 +1739,6 @@ mp_factor_using_pollard_rho (mpz_t n, unsigned long int a,
|
||||
|
||||
mpz_clears (P, t2, t, z, x, y, NULL);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if USE_SQUFOF
|
||||
/* FIXME: Maybe better to use an iteration converging to 1/sqrt(n)? If
|
||||
@@ -2251,7 +2228,6 @@ factor (uintmax_t t1, uintmax_t t0, struct factors *factors)
|
||||
}
|
||||
}
|
||||
|
||||
#if HAVE_GMP
|
||||
/* Use Pollard-rho to compute the prime factors of
|
||||
arbitrary-precision T, and put the results in FACTORS. */
|
||||
static void
|
||||
@@ -2273,7 +2249,6 @@ mp_factor (mpz_t t, struct mp_factors *factors)
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static strtol_error
|
||||
strto2uintmax (uintmax_t *hip, uintmax_t *lop, const char *s)
|
||||
@@ -2526,7 +2501,6 @@ print_factors (const char *input)
|
||||
return false;
|
||||
}
|
||||
|
||||
#if HAVE_GMP
|
||||
devmsg ("[using arbitrary-precision arithmetic] ");
|
||||
mpz_t t;
|
||||
struct mp_factors factors;
|
||||
@@ -2545,10 +2519,6 @@ print_factors (const char *input)
|
||||
putchar ('\n');
|
||||
fflush (stdout);
|
||||
return true;
|
||||
#else
|
||||
error (0, 0, _("%s is too large"), quote (input));
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
Reference in New Issue
Block a user