Commit c8b6006d authored by Paul Eggert's avatar Paul Eggert
Browse files

Use Gnulib libgmp module

Instead of doing GMP by hand, use the Gnulib libgmp module.
* .gitignore: Add lib/gmp.h.
* admin/merge-gnulib (GNULIB_MODULES): Add libgmp.
* configure.ac (GMP_LIB, GMP_OBJ): Remove.  Gnulib uses the name
LIB_GMP, so all uses changed.  All uses of GMP_OBJ removed.
(HAVE_GMP): Set this from Gnulib’s variables.
* lib/gnulib.mk.in, m4/gnulib-comp.m4: Regenerate.
* lib/mini-gmp-gnulib.c, lib/mini-gmp.c, lib/mini-gmp.h, m4/libgmp.m4:
New files, copied from Gnulib.
* src/bignum.h, test/data/emacs-module/mod-test.c:
Include gmp.h unconditionally.
* src/mini-gmp-emacs.c, src/mini-gmp.c, src/mini-gmp.h:
Remove.  This moves these files from src to lib, and
updates them to the current GMP version.
* test/Makefile.in (GMP_H): New macro.
($(test_module)): Use it to decide whether to compile
mini-gmp-gnulib.c too.
parent 50130655
...@@ -60,6 +60,7 @@ lib/execinfo.h ...@@ -60,6 +60,7 @@ lib/execinfo.h
lib/fcntl.h lib/fcntl.h
lib/getopt.h lib/getopt.h
lib/getopt-cdefs.h lib/getopt-cdefs.h
lib/gmp.h
lib/ieee754.h lib/ieee754.h
lib/inttypes.h lib/inttypes.h
lib/libgnu.a lib/libgnu.a
......
...@@ -36,7 +36,7 @@ GNULIB_MODULES=' ...@@ -36,7 +36,7 @@ GNULIB_MODULES='
fchmodat fcntl fcntl-h fdopendir fchmodat fcntl fcntl-h fdopendir
filemode filename filevercmp flexmember fpieee fstatat fsusage fsync futimens filemode filename filevercmp flexmember fpieee fstatat fsusage fsync futimens
getloadavg getopt-gnu getrandom gettime gettimeofday gitlog-to-changelog getloadavg getopt-gnu getrandom gettime gettimeofday gitlog-to-changelog
ieee754-h ignore-value intprops largefile lstat ieee754-h ignore-value intprops largefile libgmp lstat
manywarnings memmem-simple mempcpy memrchr minmax mkostemp mktime nstrftime manywarnings memmem-simple mempcpy memrchr minmax mkostemp mktime nstrftime
pathmax pipe2 pselect pthread_sigmask pathmax pipe2 pselect pthread_sigmask
qcopy-acl readlink readlinkat regex qcopy-acl readlink readlinkat regex
......
...@@ -4507,32 +4507,6 @@ AC_SUBST(KRB5LIB) ...@@ -4507,32 +4507,6 @@ AC_SUBST(KRB5LIB)
AC_SUBST(DESLIB) AC_SUBST(DESLIB)
AC_SUBST(KRB4LIB) AC_SUBST(KRB4LIB)
AC_ARG_WITH([libgmp],
[AS_HELP_STRING([--without-libgmp],
[don't use the GNU Multiple Precision (GMP) library;
this is the default on systems lacking libgmp.])])
GMP_LIB=
GMP_OBJ=mini-gmp-emacs.o
HAVE_GMP=no
case $with_libgmp in
no) ;;
yes) HAVE_GMP=yes GMP_LIB=-lgmp;;
*) AC_CHECK_HEADERS([gmp.h],
[OLIBS=$LIBS
AC_SEARCH_LIBS([__gmpz_roinit_n], [gmp])
LIBS=$OLIBS
case $ac_cv_search___gmpz_roinit_n in
'none needed') HAVE_GMP=yes;;
-*) HAVE_GMP=yes GMP_LIB=$ac_cv_search___gmpz_roinit_n;;
esac]);;
esac
if test "$HAVE_GMP" = yes; then
GMP_OBJ=
AC_DEFINE([HAVE_GMP], 1, [Define to 1 if you have recent-enough GMP.])
fi
AC_SUBST([GMP_LIB])
AC_SUBST([GMP_OBJ])
AC_CHECK_HEADERS(valgrind/valgrind.h) AC_CHECK_HEADERS(valgrind/valgrind.h)
AC_CHECK_MEMBERS([struct unipair.unicode], [], [], [[#include <linux/kd.h>]]) AC_CHECK_MEMBERS([struct unipair.unicode], [], [], [[#include <linux/kd.h>]])
...@@ -5700,6 +5674,11 @@ done ...@@ -5700,6 +5674,11 @@ done
AC_DEFINE_UNQUOTED(EMACS_CONFIG_FEATURES, "${emacs_config_features}", AC_DEFINE_UNQUOTED(EMACS_CONFIG_FEATURES, "${emacs_config_features}",
[Summary of some of the main features enabled by configure.]) [Summary of some of the main features enabled by configure.])
if test -z "$GMP_H"; then
HAVE_GMP=yes
else
HAVE_GMP=no
fi
AS_ECHO([" Does Emacs use -lXaw3d? ${HAVE_XAW3D} AS_ECHO([" Does Emacs use -lXaw3d? ${HAVE_XAW3D}
Does Emacs use -lXpm? ${HAVE_XPM} Does Emacs use -lXpm? ${HAVE_XPM}
Does Emacs use -ljpeg? ${HAVE_JPEG} Does Emacs use -ljpeg? ${HAVE_JPEG}
...@@ -5728,7 +5707,7 @@ AS_ECHO([" Does Emacs use -lXaw3d? ${HAVE_XAW3D ...@@ -5728,7 +5707,7 @@ AS_ECHO([" Does Emacs use -lXaw3d? ${HAVE_XAW3D
Does Emacs use -lxft? ${HAVE_XFT} Does Emacs use -lxft? ${HAVE_XFT}
Does Emacs use -lsystemd? ${HAVE_LIBSYSTEMD} Does Emacs use -lsystemd? ${HAVE_LIBSYSTEMD}
Does Emacs use -ljansson? ${HAVE_JSON} Does Emacs use -ljansson? ${HAVE_JSON}
Does Emacs use -lgmp? ${HAVE_GMP} Does Emacs use the GMP library? ${HAVE_GMP}
Does Emacs directly use zlib? ${HAVE_ZLIB} Does Emacs directly use zlib? ${HAVE_ZLIB}
Does Emacs have dynamic modules support? ${HAVE_MODULES} Does Emacs have dynamic modules support? ${HAVE_MODULES}
Does Emacs use toolkit scroll bars? ${USE_TOOLKIT_SCROLL_BARS} Does Emacs use toolkit scroll bars? ${USE_TOOLKIT_SCROLL_BARS}
......
...@@ -117,6 +117,7 @@ ...@@ -117,6 +117,7 @@
# ignore-value \ # ignore-value \
# intprops \ # intprops \
# largefile \ # largefile \
# libgmp \
# lstat \ # lstat \
# manywarnings \ # manywarnings \
# memmem-simple \ # memmem-simple \
...@@ -245,14 +246,14 @@ GL_GENERATE_ALLOCA_H = @GL_GENERATE_ALLOCA_H@ ...@@ -245,14 +246,14 @@ GL_GENERATE_ALLOCA_H = @GL_GENERATE_ALLOCA_H@
GL_GENERATE_BYTESWAP_H = @GL_GENERATE_BYTESWAP_H@ GL_GENERATE_BYTESWAP_H = @GL_GENERATE_BYTESWAP_H@
GL_GENERATE_ERRNO_H = @GL_GENERATE_ERRNO_H@ GL_GENERATE_ERRNO_H = @GL_GENERATE_ERRNO_H@
GL_GENERATE_EXECINFO_H = @GL_GENERATE_EXECINFO_H@ GL_GENERATE_EXECINFO_H = @GL_GENERATE_EXECINFO_H@
GL_GENERATE_GMP_H = @GL_GENERATE_GMP_H@
GL_GENERATE_IEEE754_H = @GL_GENERATE_IEEE754_H@ GL_GENERATE_IEEE754_H = @GL_GENERATE_IEEE754_H@
GL_GENERATE_LIMITS_H = @GL_GENERATE_LIMITS_H@ GL_GENERATE_LIMITS_H = @GL_GENERATE_LIMITS_H@
GL_GENERATE_STDALIGN_H = @GL_GENERATE_STDALIGN_H@ GL_GENERATE_STDALIGN_H = @GL_GENERATE_STDALIGN_H@
GL_GENERATE_STDDEF_H = @GL_GENERATE_STDDEF_H@ GL_GENERATE_STDDEF_H = @GL_GENERATE_STDDEF_H@
GL_GENERATE_STDINT_H = @GL_GENERATE_STDINT_H@ GL_GENERATE_STDINT_H = @GL_GENERATE_STDINT_H@
GMALLOC_OBJ = @GMALLOC_OBJ@ GMALLOC_OBJ = @GMALLOC_OBJ@
GMP_LIB = @GMP_LIB@ GMP_H = @GMP_H@
GMP_OBJ = @GMP_OBJ@
GNULIB_ACCESS = @GNULIB_ACCESS@ GNULIB_ACCESS = @GNULIB_ACCESS@
GNULIB_ALPHASORT = @GNULIB_ALPHASORT@ GNULIB_ALPHASORT = @GNULIB_ALPHASORT@
GNULIB_ATOLL = @GNULIB_ATOLL@ GNULIB_ATOLL = @GNULIB_ATOLL@
...@@ -760,6 +761,7 @@ LIB_CLOCK_GETTIME = @LIB_CLOCK_GETTIME@ ...@@ -760,6 +761,7 @@ LIB_CLOCK_GETTIME = @LIB_CLOCK_GETTIME@
LIB_EACCESS = @LIB_EACCESS@ LIB_EACCESS = @LIB_EACCESS@
LIB_EXECINFO = @LIB_EXECINFO@ LIB_EXECINFO = @LIB_EXECINFO@
LIB_GETRANDOM = @LIB_GETRANDOM@ LIB_GETRANDOM = @LIB_GETRANDOM@
LIB_GMP = @LIB_GMP@
LIB_MATH = @LIB_MATH@ LIB_MATH = @LIB_MATH@
LIB_PTHREAD = @LIB_PTHREAD@ LIB_PTHREAD = @LIB_PTHREAD@
LIB_PTHREAD_SIGMASK = @LIB_PTHREAD_SIGMASK@ LIB_PTHREAD_SIGMASK = @LIB_PTHREAD_SIGMASK@
...@@ -2014,6 +2016,29 @@ EXTRA_DIST += cdefs.h libc-config.h ...@@ -2014,6 +2016,29 @@ EXTRA_DIST += cdefs.h libc-config.h
endif endif
## end gnulib module libc-config ## end gnulib module libc-config
## begin gnulib module libgmp
ifeq (,$(OMIT_GNULIB_MODULE_libgmp))
BUILT_SOURCES += $(GMP_H)
# Build gmp.h as a wrapper for mini-gmp.h when using mini-gmp.
ifneq (,$(GL_GENERATE_GMP_H))
gmp.h: $(top_builddir)/config.status
echo '#include "mini-gmp.h"' >$@-t
mv $@-t $@
else
gmp.h: $(top_builddir)/config.status
rm -f $@
endif
MOSTLYCLEANFILES += gmp.h gmp.h-t
EXTRA_DIST += mini-gmp-gnulib.c mini-gmp.c mini-gmp.h
EXTRA_libgnu_a_SOURCES += mini-gmp-gnulib.c mini-gmp.c
endif
## end gnulib module libgmp
## begin gnulib module limits-h ## begin gnulib module limits-h
ifeq (,$(OMIT_GNULIB_MODULE_limits-h)) ifeq (,$(OMIT_GNULIB_MODULE_limits-h))
......
/* Tailor mini-gmp.c for Gnulib-using applications.
Copyright 2018-2020 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. */
#include <config.h>
#include <stddef.h>
#include <stdio.h>
#include "mini-gmp.h"
/* Pacify GCC -Wsuggest-attribute=const, malloc, pure. */
#if 4 < __GNUC__ + (6 <= __GNUC_MINOR__)
# pragma GCC diagnostic ignored "-Wsuggest-attribute=const"
# pragma GCC diagnostic ignored "-Wsuggest-attribute=malloc"
# pragma GCC diagnostic ignored "-Wsuggest-attribute=pure"
#endif
/* Pacify GCC -Wunused-variable for variables used only in 'assert' calls. */
#if defined NDEBUG && 4 < __GNUC__ + (6 <= __GNUC_MINOR__)
# pragma GCC diagnostic ignored "-Wunused-variable"
#endif
#include "mini-gmp.c"
...@@ -2,21 +2,21 @@ ...@@ -2,21 +2,21 @@
Contributed to the GNU project by Niels Möller Contributed to the GNU project by Niels Möller
Copyright 1991-1997, 1999-2019 Free Software Foundation, Inc. Copyright 1991-1997, 1999-2020 Free Software Foundation, Inc.
This file is part of the GNU MP Library. This file is part of the GNU MP Library.
The GNU MP Library is free software; you can redistribute it and/or modify The GNU MP Library is free software; you can redistribute it and/or modify
it under the terms of either: it under the terms of either:
* the GNU Lesser General Public License as published by the Free * the GNU General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your Software Foundation; either version 3 of the License, or (at your
option) any later version. option) any later version.
or or
* the GNU General Public License as published by the Free Software * the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any Foundation; either version 3 of the License, or (at your option) any
later version. later version.
or both in parallel, as here. or both in parallel, as here.
...@@ -27,7 +27,7 @@ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ...@@ -27,7 +27,7 @@ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details. for more details.
You should have received copies of the GNU General Public License and the You should have received copies of the GNU General Public License and the
GNU Lesser General Public License along with the GNU MP Library. If not, GNU General Public License along with the GNU MP Library. If not,
see https://www.gnu.org/licenses/. */ see https://www.gnu.org/licenses/. */
/* NOTE: All functions in this file which are not declared in /* NOTE: All functions in this file which are not declared in
...@@ -351,20 +351,27 @@ mp_set_memory_functions (void *(*alloc_func) (size_t), ...@@ -351,20 +351,27 @@ mp_set_memory_functions (void *(*alloc_func) (size_t),
gmp_free_func = free_func; gmp_free_func = free_func;
} }
#define gmp_xalloc(size) ((*gmp_allocate_func)((size))) #define gmp_alloc(size) ((*gmp_allocate_func)((size)))
#define gmp_free(p) ((*gmp_free_func) ((p), 0)) #define gmp_free(p, size) ((*gmp_free_func) ((p), (size)))
#define gmp_realloc(ptr, old_size, size) ((*gmp_reallocate_func)(ptr, old_size, size))
static mp_ptr static mp_ptr
gmp_xalloc_limbs (mp_size_t size) gmp_alloc_limbs (mp_size_t size)
{ {
return (mp_ptr) gmp_xalloc (size * sizeof (mp_limb_t)); return (mp_ptr) gmp_alloc (size * sizeof (mp_limb_t));
} }
static mp_ptr static mp_ptr
gmp_xrealloc_limbs (mp_ptr old, mp_size_t size) gmp_realloc_limbs (mp_ptr old, mp_size_t old_size, mp_size_t size)
{ {
assert (size > 0); assert (size > 0);
return (mp_ptr) (*gmp_reallocate_func) (old, 0, size * sizeof (mp_limb_t)); return (mp_ptr) gmp_realloc (old, old_size * sizeof (mp_limb_t), size * sizeof (mp_limb_t));
}
static void
gmp_free_limbs (mp_ptr old, mp_size_t size)
{
gmp_free (old, size * sizeof (mp_limb_t));
} }
...@@ -956,11 +963,17 @@ mpn_div_qr_1_preinv (mp_ptr qp, mp_srcptr np, mp_size_t nn, ...@@ -956,11 +963,17 @@ mpn_div_qr_1_preinv (mp_ptr qp, mp_srcptr np, mp_size_t nn,
mp_limb_t d, di; mp_limb_t d, di;
mp_limb_t r; mp_limb_t r;
mp_ptr tp = NULL; mp_ptr tp = NULL;
mp_size_t tn = 0;
if (inv->shift > 0) if (inv->shift > 0)
{ {
/* Shift, reusing qp area if possible. In-place shift if qp == np. */ /* Shift, reusing qp area if possible. In-place shift if qp == np. */
tp = qp ? qp : gmp_xalloc_limbs (nn); tp = qp;
if (!tp)
{
tn = nn;
tp = gmp_alloc_limbs (tn);
}
r = mpn_lshift (tp, np, nn, inv->shift); r = mpn_lshift (tp, np, nn, inv->shift);
np = tp; np = tp;
} }
...@@ -977,8 +990,8 @@ mpn_div_qr_1_preinv (mp_ptr qp, mp_srcptr np, mp_size_t nn, ...@@ -977,8 +990,8 @@ mpn_div_qr_1_preinv (mp_ptr qp, mp_srcptr np, mp_size_t nn,
if (qp) if (qp)
qp[nn] = q; qp[nn] = q;
} }
if ((inv->shift > 0) && (tp != qp)) if (tn)
gmp_free (tp); gmp_free_limbs (tp, tn);
return r >> inv->shift; return r >> inv->shift;
} }
...@@ -1136,13 +1149,13 @@ mpn_div_qr (mp_ptr qp, mp_ptr np, mp_size_t nn, mp_srcptr dp, mp_size_t dn) ...@@ -1136,13 +1149,13 @@ mpn_div_qr (mp_ptr qp, mp_ptr np, mp_size_t nn, mp_srcptr dp, mp_size_t dn)
mpn_div_qr_invert (&inv, dp, dn); mpn_div_qr_invert (&inv, dp, dn);
if (dn > 2 && inv.shift > 0) if (dn > 2 && inv.shift > 0)
{ {
tp = gmp_xalloc_limbs (dn); tp = gmp_alloc_limbs (dn);
gmp_assert_nocarry (mpn_lshift (tp, dp, dn, inv.shift)); gmp_assert_nocarry (mpn_lshift (tp, dp, dn, inv.shift));
dp = tp; dp = tp;
} }
mpn_div_qr_preinv (qp, np, nn, dp, dn, &inv); mpn_div_qr_preinv (qp, np, nn, dp, dn, &inv);
if (tp) if (tp)
gmp_free (tp); gmp_free_limbs (tp, dn);
} }
...@@ -1428,14 +1441,14 @@ mpz_init2 (mpz_t r, mp_bitcnt_t bits) ...@@ -1428,14 +1441,14 @@ mpz_init2 (mpz_t r, mp_bitcnt_t bits)
r->_mp_alloc = rn; r->_mp_alloc = rn;
r->_mp_size = 0; r->_mp_size = 0;
r->_mp_d = gmp_xalloc_limbs (rn); r->_mp_d = gmp_alloc_limbs (rn);
} }
void void
mpz_clear (mpz_t r) mpz_clear (mpz_t r)
{ {
if (r->_mp_alloc) if (r->_mp_alloc)
gmp_free (r->_mp_d); gmp_free_limbs (r->_mp_d, r->_mp_alloc);
} }
static mp_ptr static mp_ptr
...@@ -1444,9 +1457,9 @@ mpz_realloc (mpz_t r, mp_size_t size) ...@@ -1444,9 +1457,9 @@ mpz_realloc (mpz_t r, mp_size_t size)
size = GMP_MAX (size, 1); size = GMP_MAX (size, 1);
if (r->_mp_alloc) if (r->_mp_alloc)
r->_mp_d = gmp_xrealloc_limbs (r->_mp_d, size); r->_mp_d = gmp_realloc_limbs (r->_mp_d, r->_mp_alloc, size);
else else
r->_mp_d = gmp_xalloc_limbs (size); r->_mp_d = gmp_alloc_limbs (size);
r->_mp_alloc = size; r->_mp_alloc = size;
if (GMP_ABS (r->_mp_size) > size) if (GMP_ABS (r->_mp_size) > size)
...@@ -1541,8 +1554,7 @@ mpz_init_set (mpz_t r, const mpz_t x) ...@@ -1541,8 +1554,7 @@ mpz_init_set (mpz_t r, const mpz_t x)
int int
mpz_fits_slong_p (const mpz_t u) mpz_fits_slong_p (const mpz_t u)
{ {
return (LONG_MAX + LONG_MIN == 0 || mpz_cmp_ui (u, LONG_MAX) <= 0) && return mpz_cmp_si (u, LONG_MAX) <= 0 && mpz_cmp_si (u, LONG_MIN) >= 0;
mpz_cmpabs_ui (u, GMP_NEG_CAST (unsigned long int, LONG_MIN)) <= 0;
} }
static int static int
...@@ -1565,6 +1577,30 @@ mpz_fits_ulong_p (const mpz_t u) ...@@ -1565,6 +1577,30 @@ mpz_fits_ulong_p (const mpz_t u)
return us >= 0 && mpn_absfits_ulong_p (u->_mp_d, us); return us >= 0 && mpn_absfits_ulong_p (u->_mp_d, us);
} }
int
mpz_fits_sint_p (const mpz_t u)
{
return mpz_cmp_si (u, INT_MAX) <= 0 && mpz_cmp_si (u, INT_MIN) >= 0;
}
int
mpz_fits_uint_p (const mpz_t u)
{
return u->_mp_size >= 0 && mpz_cmpabs_ui (u, UINT_MAX) <= 0;
}
int
mpz_fits_sshort_p (const mpz_t u)
{
return mpz_cmp_si (u, SHRT_MAX) <= 0 && mpz_cmp_si (u, SHRT_MIN) >= 0;
}
int
mpz_fits_ushort_p (const mpz_t u)
{
return u->_mp_size >= 0 && mpz_cmpabs_ui (u, USHRT_MAX) <= 0;
}
long int long int
mpz_get_si (const mpz_t u) mpz_get_si (const mpz_t u)
{ {
...@@ -3073,7 +3109,7 @@ mpz_powm (mpz_t r, const mpz_t b, const mpz_t e, const mpz_t m) ...@@ -3073,7 +3109,7 @@ mpz_powm (mpz_t r, const mpz_t b, const mpz_t e, const mpz_t m)
one, using a *normalized* m. */ one, using a *normalized* m. */
minv.shift = 0; minv.shift = 0;
tp = gmp_xalloc_limbs (mn); tp = gmp_alloc_limbs (mn);
gmp_assert_nocarry (mpn_lshift (tp, mp, mn, shift)); gmp_assert_nocarry (mpn_lshift (tp, mp, mn, shift));
mp = tp; mp = tp;
} }
...@@ -3139,7 +3175,7 @@ mpz_powm (mpz_t r, const mpz_t b, const mpz_t e, const mpz_t m) ...@@ -3139,7 +3175,7 @@ mpz_powm (mpz_t r, const mpz_t b, const mpz_t e, const mpz_t m)
tr->_mp_size = mpn_normalized_size (tr->_mp_d, mn); tr->_mp_size = mpn_normalized_size (tr->_mp_d, mn);
} }
if (tp) if (tp)
gmp_free (tp); gmp_free_limbs (tp, mn);
mpz_swap (r, tr); mpz_swap (r, tr);
mpz_clear (tr); mpz_clear (tr);
...@@ -3350,13 +3386,15 @@ gmp_jacobi_coprime (mp_limb_t a, mp_limb_t b) ...@@ -3350,13 +3386,15 @@ gmp_jacobi_coprime (mp_limb_t a, mp_limb_t b)
gmp_ctz(c, a); gmp_ctz(c, a);
a >>= 1; a >>= 1;
do for (;;)
{ {
a >>= c; a >>= c;
/* (2/b) = -1 if b = 3 or 5 mod 8 */ /* (2/b) = -1 if b = 3 or 5 mod 8 */
bit ^= c & (b ^ (b >> 1)); bit ^= c & (b ^ (b >> 1));
if (a < b) if (a < b)
{ {
if (a == 0)
return bit & 1 ? -1 : 1;
bit ^= a & b; bit ^= a & b;
a = b - a; a = b - a;
b -= a; b -= a;
...@@ -3370,9 +3408,6 @@ gmp_jacobi_coprime (mp_limb_t a, mp_limb_t b) ...@@ -3370,9 +3408,6 @@ gmp_jacobi_coprime (mp_limb_t a, mp_limb_t b)
gmp_ctz(c, a); gmp_ctz(c, a);
++c; ++c;
} }
while (b > 0);
return bit & 1 ? -1 : 1;
} }
static void static void
...@@ -4144,7 +4179,7 @@ mpz_scan0 (const mpz_t u, mp_bitcnt_t starting_bit) ...@@ -4144,7 +4179,7 @@ mpz_scan0 (const mpz_t u, mp_bitcnt_t starting_bit)
size_t size_t
mpz_sizeinbase (const mpz_t u, int base) mpz_sizeinbase (const mpz_t u, int base)
{ {
mp_size_t un; mp_size_t un, tn;
mp_srcptr up; mp_srcptr up;
mp_ptr tp; mp_ptr tp;
mp_bitcnt_t bits; mp_bitcnt_t bits;
...@@ -4177,20 +4212,21 @@ mpz_sizeinbase (const mpz_t u, int base) ...@@ -4177,20 +4212,21 @@ mpz_sizeinbase (const mpz_t u, int base)
10. */ 10. */
} }
tp = gmp_xalloc_limbs (un); tp = gmp_alloc_limbs (un);
mpn_copyi (tp, up, un); mpn_copyi (tp, up, un);
mpn_div_qr_1_invert (&bi, base); mpn_div_qr_1_invert (&bi, base);
tn = un;
ndigits = 0; ndigits = 0;
do do
{ {
ndigits++; ndigits++;
mpn_div_qr_1_preinv (tp, tp, un, &bi); mpn_div_qr_1_preinv (tp, tp, tn, &bi);
un -= (tp[un-1] == 0); tn -= (tp[tn-1] == 0);
} }
while (un > 0); while (tn > 0);
gmp_free (tp); gmp_free_limbs (tp, un);
return ndigits; return ndigits;
} }
...@@ -4200,7 +4236,7 @@ mpz_get_str (char *sp, int base, const mpz_t u) ...@@ -4200,7 +4236,7 @@ mpz_get_str (char *sp, int base, const mpz_t u)
unsigned bits; unsigned bits;
const char *digits; const char *digits;
mp_size_t un; mp_size_t un;
size_t i, sn; size_t i, sn, osn;
digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
if (base > 1) if (base > 1)
...@@ -4221,15 +4257,19 @@ mpz_get_str (char *sp, int base, const mpz_t u) ...@@ -4221,15 +4257,19 @@ mpz_get_str (char *sp, int base, const mpz_t u)
sn = 1 + mpz_sizeinbase (u, base); sn = 1 + mpz_sizeinbase (u, base);
if (!sp) if (!sp)
sp = (char *) gmp_xalloc (1 + sn); {
osn = 1 + sn;
sp = (char *) gmp_alloc (osn);
}
else
osn = 0;
un = GMP_ABS (u->_mp_size); un = GMP_ABS (u->_mp_size);
if (un == 0) if (un == 0)
{ {
sp[0] = '0'; sp[0] = '0';
sp[1] = '\0'; sn = 1;
return sp; goto ret;
} }
i = 0; i = 0;
...@@ -4248,17 +4288,20 @@ mpz_get_str (char *sp, int base, const mpz_t u) ...@@ -4248,17 +4288,20 @@ mpz_get_str (char *sp, int base, const mpz_t u)
mp_ptr tp; mp_ptr tp;
mpn_get_base_info (&info, base); mpn_g