Add Chromium-only Blender WebEngine parity work

This commit is contained in:
mes123456
2026-08-12 04:47:48 -04:00
commit 9fd26010f6
18225 changed files with 11622124 additions and 0 deletions

View File

@@ -0,0 +1,100 @@
/* mpz_2fac_ui(RESULT, N) -- Set RESULT to N!!.
Contributed to the GNU project by Marco Bodrato.
Copyright 2012, 2015, 2018 Free Software Foundation, Inc.
This file is part of the GNU MP Library.
The GNU MP Library is free software; you can redistribute it and/or modify
it under the terms of either:
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
or
* the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any
later version.
or both in parallel, as here.
The GNU MP Library 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 copies of the GNU General Public License and the
GNU Lesser General Public License along with the GNU MP Library. If not,
see https://www.gnu.org/licenses/. */
#include "gmp-impl.h"
#define FACTOR_LIST_STORE(P, PR, MAX_PR, VEC, I) \
do { \
if ((PR) > (MAX_PR)) { \
(VEC)[(I)++] = (PR); \
(PR) = (P); \
} else \
(PR) *= (P); \
} while (0)
#define FAC_2DSC_THRESHOLD ((FAC_DSC_THRESHOLD << 1) | (FAC_DSC_THRESHOLD & 1))
#define FACTORS_PER_LIMB (GMP_NUMB_BITS / (LOG2C(FAC_2DSC_THRESHOLD-1)+1))
/* Computes n!!, the 2-multi-factorial of n. (aka double-factorial or semi-factorial)
WARNING: it assumes that n fits in a limb!
*/
void
mpz_2fac_ui (mpz_ptr x, unsigned long n)
{
ASSERT (n <= GMP_NUMB_MAX);
if ((n & 1) == 0) { /* n is even, n = 2k, (2k)!! = k! 2^k */
mp_limb_t count;
if ((n <= TABLE_LIMIT_2N_MINUS_POPC_2N) & (n != 0))
count = __gmp_fac2cnt_table[n / 2 - 1];
else
{
popc_limb (count, n); /* popc(n) == popc(k) */
count = n - count; /* n - popc(n) == k + k - popc(k) */
}
mpz_oddfac_1 (x, n >> 1, 0);
mpz_mul_2exp (x, x, count);
} else { /* n is odd */
if (n <= ODD_DOUBLEFACTORIAL_TABLE_LIMIT) {
MPZ_NEWALLOC (x, 1)[0] = __gmp_odd2fac_table[n >> 1];
SIZ (x) = 1;
} else if (BELOW_THRESHOLD (n, FAC_2DSC_THRESHOLD)) { /* odd basecase, */
mp_limb_t *factors, prod, max_prod;
mp_size_t j;
TMP_SDECL;
/* FIXME: we might alloc a fixed amount 1+FAC_2DSC_THRESHOLD/FACTORS_PER_LIMB */
TMP_SMARK;
factors = TMP_SALLOC_LIMBS (1 + n / (2 * FACTORS_PER_LIMB));
factors[0] = ODD_DOUBLEFACTORIAL_TABLE_MAX;
j = 1;
prod = n;
max_prod = GMP_NUMB_MAX / FAC_2DSC_THRESHOLD;
while ((n -= 2) > ODD_DOUBLEFACTORIAL_TABLE_LIMIT)
FACTOR_LIST_STORE (n, prod, max_prod, factors, j);
factors[j++] = prod;
mpz_prodlimbs (x, factors, j);
TMP_SFREE;
} else { /* for the asymptotically fast odd case, let oddfac do the job. */
mpz_oddfac_1 (x, n, 1);
}
}
}
#undef FACTORS_PER_LIMB
#undef FACTOR_LIST_STORE
#undef FAC_2DSC_THRESHOLD

View File

@@ -0,0 +1,68 @@
## Process this file with automake to generate Makefile.in
# Copyright 1996, 1998-2003, 2012 Free Software Foundation, Inc.
#
# This file is part of the GNU MP Library.
#
# The GNU MP Library is free software; you can redistribute it and/or modify
# it under the terms of either:
#
# * the GNU Lesser General Public License as published by the Free
# Software Foundation; either version 3 of the License, or (at your
# option) any later version.
#
# or
#
# * the GNU General Public License as published by the Free Software
# Foundation; either version 2 of the License, or (at your option) any
# later version.
#
# or both in parallel, as here.
#
# The GNU MP Library 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 copies of the GNU General Public License and the
# GNU Lesser General Public License along with the GNU MP Library. If not,
# see https://www.gnu.org/licenses/.
AM_CPPFLAGS = -D__GMP_WITHIN_GMP -I$(top_srcdir)
noinst_LTLIBRARIES = libmpz.la
libmpz_la_SOURCES = aors.h aors_ui.h fits_s.h mul_i.h \
2fac_ui.c \
add.c add_ui.c abs.c aorsmul.c aorsmul_i.c and.c array_init.c \
bin_ui.c bin_uiui.c cdiv_q.c \
cdiv_q_ui.c cdiv_qr.c cdiv_qr_ui.c cdiv_r.c cdiv_r_ui.c cdiv_ui.c \
cfdiv_q_2exp.c cfdiv_r_2exp.c \
clear.c clears.c clrbit.c \
cmp.c cmp_d.c cmp_si.c cmp_ui.c cmpabs.c cmpabs_d.c cmpabs_ui.c \
com.c combit.c \
cong.c cong_2exp.c cong_ui.c \
divexact.c divegcd.c dive_ui.c divis.c divis_ui.c divis_2exp.c \
dump.c export.c fac_ui.c fdiv_q.c fdiv_q_ui.c \
fdiv_qr.c fdiv_qr_ui.c fdiv_r.c fdiv_r_ui.c fdiv_ui.c \
fib_ui.c fib2_ui.c \
fits_sint.c fits_slong.c fits_sshort.c \
fits_uint.c fits_ulong.c fits_ushort.c \
gcd.c gcd_ui.c gcdext.c get_d.c get_d_2exp.c get_si.c \
get_str.c get_ui.c getlimbn.c hamdist.c \
import.c init.c init2.c inits.c inp_raw.c inp_str.c \
invert.c ior.c iset.c iset_d.c iset_si.c iset_str.c iset_ui.c \
jacobi.c kronsz.c kronuz.c kronzs.c kronzu.c \
lcm.c lcm_ui.c limbs_read.c limbs_write.c limbs_modify.c limbs_finish.c \
lucnum_ui.c lucnum2_ui.c lucmod.c mfac_uiui.c millerrabin.c \
mod.c mul.c mul_2exp.c mul_si.c mul_ui.c n_pow_ui.c neg.c nextprime.c \
oddfac_1.c \
out_raw.c out_str.c perfpow.c perfsqr.c popcount.c pow_ui.c powm.c \
powm_sec.c powm_ui.c pprime_p.c prodlimbs.c primorial_ui.c random.c random2.c \
realloc.c realloc2.c remove.c roinit_n.c root.c rootrem.c rrandomb.c \
scan0.c scan1.c set.c set_d.c set_f.c set_q.c set_si.c set_str.c \
set_ui.c setbit.c size.c sizeinbase.c sqrt.c sqrtrem.c stronglucas.c \
sub.c sub_ui.c \
swap.c tdiv_ui.c tdiv_q.c tdiv_q_2exp.c tdiv_q_ui.c tdiv_qr.c \
tdiv_qr_ui.c tdiv_r.c tdiv_r_2exp.c tdiv_r_ui.c tstbit.c ui_pow_ui.c \
ui_sub.c urandomb.c urandomm.c xor.c

View File

@@ -0,0 +1,702 @@
# Makefile.in generated by automake 1.15 from Makefile.am.
# @configure_input@
# Copyright (C) 1994-2014 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
@SET_MAKE@
# Copyright 1996, 1998-2003, 2012 Free Software Foundation, Inc.
#
# This file is part of the GNU MP Library.
#
# The GNU MP Library is free software; you can redistribute it and/or modify
# it under the terms of either:
#
# * the GNU Lesser General Public License as published by the Free
# Software Foundation; either version 3 of the License, or (at your
# option) any later version.
#
# or
#
# * the GNU General Public License as published by the Free Software
# Foundation; either version 2 of the License, or (at your option) any
# later version.
#
# or both in parallel, as here.
#
# The GNU MP Library 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 copies of the GNU General Public License and the
# GNU Lesser General Public License along with the GNU MP Library. If not,
# see https://www.gnu.org/licenses/.
VPATH = @srcdir@
am__is_gnu_make = { \
if test -z '$(MAKELEVEL)'; then \
false; \
elif test -n '$(MAKE_HOST)'; then \
true; \
elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
true; \
else \
false; \
fi; \
}
am__make_running_with_option = \
case $${target_option-} in \
?) ;; \
*) echo "am__make_running_with_option: internal error: invalid" \
"target option '$${target_option-}' specified" >&2; \
exit 1;; \
esac; \
has_opt=no; \
sane_makeflags=$$MAKEFLAGS; \
if $(am__is_gnu_make); then \
sane_makeflags=$$MFLAGS; \
else \
case $$MAKEFLAGS in \
*\\[\ \ ]*) \
bs=\\; \
sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
| sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
esac; \
fi; \
skip_next=no; \
strip_trailopt () \
{ \
flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
}; \
for flg in $$sane_makeflags; do \
test $$skip_next = yes && { skip_next=no; continue; }; \
case $$flg in \
*=*|--*) continue;; \
-*I) strip_trailopt 'I'; skip_next=yes;; \
-*I?*) strip_trailopt 'I';; \
-*O) strip_trailopt 'O'; skip_next=yes;; \
-*O?*) strip_trailopt 'O';; \
-*l) strip_trailopt 'l'; skip_next=yes;; \
-*l?*) strip_trailopt 'l';; \
-[dEDm]) skip_next=yes;; \
-[JT]) skip_next=yes;; \
esac; \
case $$flg in \
*$$target_option*) has_opt=yes; break;; \
esac; \
done; \
test $$has_opt = yes
am__make_dryrun = (target_option=n; $(am__make_running_with_option))
am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
pkgdatadir = $(datadir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkglibexecdir = $(libexecdir)/@PACKAGE@
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
install_sh_DATA = $(install_sh) -c -m 644
install_sh_PROGRAM = $(install_sh) -c
install_sh_SCRIPT = $(install_sh) -c
INSTALL_HEADER = $(INSTALL_DATA)
transform = $(program_transform_name)
NORMAL_INSTALL = :
PRE_INSTALL = :
POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
subdir = mpz
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \
$(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
mkinstalldirs = $(install_sh) -d
CONFIG_HEADER = $(top_builddir)/config.h
CONFIG_CLEAN_FILES =
CONFIG_CLEAN_VPATH_FILES =
LTLIBRARIES = $(noinst_LTLIBRARIES)
libmpz_la_LIBADD =
am_libmpz_la_OBJECTS = 2fac_ui.lo add.lo add_ui.lo abs.lo aorsmul.lo \
aorsmul_i.lo and.lo array_init.lo bin_ui.lo bin_uiui.lo \
cdiv_q.lo cdiv_q_ui.lo cdiv_qr.lo cdiv_qr_ui.lo cdiv_r.lo \
cdiv_r_ui.lo cdiv_ui.lo cfdiv_q_2exp.lo cfdiv_r_2exp.lo \
clear.lo clears.lo clrbit.lo cmp.lo cmp_d.lo cmp_si.lo \
cmp_ui.lo cmpabs.lo cmpabs_d.lo cmpabs_ui.lo com.lo combit.lo \
cong.lo cong_2exp.lo cong_ui.lo divexact.lo divegcd.lo \
dive_ui.lo divis.lo divis_ui.lo divis_2exp.lo dump.lo \
export.lo fac_ui.lo fdiv_q.lo fdiv_q_ui.lo fdiv_qr.lo \
fdiv_qr_ui.lo fdiv_r.lo fdiv_r_ui.lo fdiv_ui.lo fib_ui.lo \
fib2_ui.lo fits_sint.lo fits_slong.lo fits_sshort.lo \
fits_uint.lo fits_ulong.lo fits_ushort.lo gcd.lo gcd_ui.lo \
gcdext.lo get_d.lo get_d_2exp.lo get_si.lo get_str.lo \
get_ui.lo getlimbn.lo hamdist.lo import.lo init.lo init2.lo \
inits.lo inp_raw.lo inp_str.lo invert.lo ior.lo iset.lo \
iset_d.lo iset_si.lo iset_str.lo iset_ui.lo jacobi.lo \
kronsz.lo kronuz.lo kronzs.lo kronzu.lo lcm.lo lcm_ui.lo \
limbs_read.lo limbs_write.lo limbs_modify.lo limbs_finish.lo \
lucnum_ui.lo lucnum2_ui.lo lucmod.lo mfac_uiui.lo \
millerrabin.lo mod.lo mul.lo mul_2exp.lo mul_si.lo mul_ui.lo \
n_pow_ui.lo neg.lo nextprime.lo oddfac_1.lo out_raw.lo \
out_str.lo perfpow.lo perfsqr.lo popcount.lo pow_ui.lo powm.lo \
powm_sec.lo powm_ui.lo pprime_p.lo prodlimbs.lo \
primorial_ui.lo random.lo random2.lo realloc.lo realloc2.lo \
remove.lo roinit_n.lo root.lo rootrem.lo rrandomb.lo scan0.lo \
scan1.lo set.lo set_d.lo set_f.lo set_q.lo set_si.lo \
set_str.lo set_ui.lo setbit.lo size.lo sizeinbase.lo sqrt.lo \
sqrtrem.lo stronglucas.lo sub.lo sub_ui.lo swap.lo tdiv_ui.lo \
tdiv_q.lo tdiv_q_2exp.lo tdiv_q_ui.lo tdiv_qr.lo tdiv_qr_ui.lo \
tdiv_r.lo tdiv_r_2exp.lo tdiv_r_ui.lo tstbit.lo ui_pow_ui.lo \
ui_sub.lo urandomb.lo urandomm.lo xor.lo
libmpz_la_OBJECTS = $(am_libmpz_la_OBJECTS)
AM_V_lt = $(am__v_lt_@AM_V@)
am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
am__v_lt_0 = --silent
am__v_lt_1 =
AM_V_P = $(am__v_P_@AM_V@)
am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
am__v_P_0 = false
am__v_P_1 = :
AM_V_GEN = $(am__v_GEN_@AM_V@)
am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
am__v_GEN_0 = @echo " GEN " $@;
am__v_GEN_1 =
AM_V_at = $(am__v_at_@AM_V@)
am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
am__v_at_0 = @
am__v_at_1 =
DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp =
am__depfiles_maybe =
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
$(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
$(AM_CFLAGS) $(CFLAGS)
AM_V_CC = $(am__v_CC_@AM_V@)
am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
am__v_CC_0 = @echo " CC " $@;
am__v_CC_1 =
CCLD = $(CC)
LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
$(AM_LDFLAGS) $(LDFLAGS) -o $@
AM_V_CCLD = $(am__v_CCLD_@AM_V@)
am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
am__v_CCLD_0 = @echo " CCLD " $@;
am__v_CCLD_1 =
SOURCES = $(libmpz_la_SOURCES)
DIST_SOURCES = $(libmpz_la_SOURCES)
am__can_run_installinfo = \
case $$AM_UPDATE_INFO_DIR in \
n|no|NO) false;; \
*) (install-info --version) >/dev/null 2>&1;; \
esac
am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
# Read a list of newline-separated strings from the standard input,
# and print each of them once, without duplicates. Input order is
# *not* preserved.
am__uniquify_input = $(AWK) '\
BEGIN { nonempty = 0; } \
{ items[$$0] = 1; nonempty = 1; } \
END { if (nonempty) { for (i in items) print i; }; } \
'
# Make sure the list of sources is unique. This is necessary because,
# e.g., the same source file might be shared among _SOURCES variables
# for different programs/libraries.
am__define_uniq_tagged_files = \
list='$(am__tagged_files)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | $(am__uniquify_input)`
ETAGS = etags
CTAGS = ctags
am__DIST_COMMON = $(srcdir)/Makefile.in
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
ABI = @ABI@
ACLOCAL = @ACLOCAL@
AMTAR = @AMTAR@
AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
AR = @AR@
AS = @AS@
ASMFLAGS = @ASMFLAGS@
AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
CALLING_CONVENTIONS_OBJS = @CALLING_CONVENTIONS_OBJS@
CC = @CC@
CCAS = @CCAS@
CC_FOR_BUILD = @CC_FOR_BUILD@
CFLAGS = @CFLAGS@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
CPP_FOR_BUILD = @CPP_FOR_BUILD@
CXX = @CXX@
CXXCPP = @CXXCPP@
CXXFLAGS = @CXXFLAGS@
CYGPATH_W = @CYGPATH_W@
DEFN_LONG_LONG_LIMB = @DEFN_LONG_LONG_LIMB@
DEFS = @DEFS@
DLLTOOL = @DLLTOOL@
DSYMUTIL = @DSYMUTIL@
DUMPBIN = @DUMPBIN@
ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
EXEEXT_FOR_BUILD = @EXEEXT_FOR_BUILD@
FGREP = @FGREP@
GMP_LDFLAGS = @GMP_LDFLAGS@
GMP_LIMB_BITS = @GMP_LIMB_BITS@
GMP_NAIL_BITS = @GMP_NAIL_BITS@
GREP = @GREP@
HAVE_CLOCK_01 = @HAVE_CLOCK_01@
HAVE_CPUTIME_01 = @HAVE_CPUTIME_01@
HAVE_GETRUSAGE_01 = @HAVE_GETRUSAGE_01@
HAVE_GETTIMEOFDAY_01 = @HAVE_GETTIMEOFDAY_01@
HAVE_HOST_CPU_FAMILY_power = @HAVE_HOST_CPU_FAMILY_power@
HAVE_HOST_CPU_FAMILY_powerpc = @HAVE_HOST_CPU_FAMILY_powerpc@
HAVE_SIGACTION_01 = @HAVE_SIGACTION_01@
HAVE_SIGALTSTACK_01 = @HAVE_SIGALTSTACK_01@
HAVE_SIGSTACK_01 = @HAVE_SIGSTACK_01@
HAVE_STACK_T_01 = @HAVE_STACK_T_01@
HAVE_SYS_RESOURCE_H_01 = @HAVE_SYS_RESOURCE_H_01@
INSTALL = @INSTALL@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
LD = @LD@
LDFLAGS = @LDFLAGS@
LEX = @LEX@
LEXLIB = @LEXLIB@
LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
LIBCURSES = @LIBCURSES@
LIBGMPXX_LDFLAGS = @LIBGMPXX_LDFLAGS@
LIBGMP_DLL = @LIBGMP_DLL@
LIBGMP_LDFLAGS = @LIBGMP_LDFLAGS@
LIBM = @LIBM@
LIBM_FOR_BUILD = @LIBM_FOR_BUILD@
LIBOBJS = @LIBOBJS@
LIBREADLINE = @LIBREADLINE@
LIBS = @LIBS@
LIBTOOL = @LIBTOOL@
LIPO = @LIPO@
LN_S = @LN_S@
LTLIBOBJS = @LTLIBOBJS@
LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
M4 = @M4@
MAINT = @MAINT@
MAKEINFO = @MAKEINFO@
MANIFEST_TOOL = @MANIFEST_TOOL@
MKDIR_P = @MKDIR_P@
NM = @NM@
NMEDIT = @NMEDIT@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
OTOOL = @OTOOL@
OTOOL64 = @OTOOL64@
PACKAGE = @PACKAGE@
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
PACKAGE_NAME = @PACKAGE_NAME@
PACKAGE_STRING = @PACKAGE_STRING@
PACKAGE_TARNAME = @PACKAGE_TARNAME@
PACKAGE_URL = @PACKAGE_URL@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
RANLIB = @RANLIB@
SED = @SED@
SET_MAKE = @SET_MAKE@
SHELL = @SHELL@
SPEED_CYCLECOUNTER_OBJ = @SPEED_CYCLECOUNTER_OBJ@
STRIP = @STRIP@
TAL_OBJECT = @TAL_OBJECT@
TUNE_LIBS = @TUNE_LIBS@
TUNE_SQR_OBJ = @TUNE_SQR_OBJ@
U_FOR_BUILD = @U_FOR_BUILD@
VERSION = @VERSION@
WITH_READLINE_01 = @WITH_READLINE_01@
YACC = @YACC@
YFLAGS = @YFLAGS@
abs_builddir = @abs_builddir@
abs_srcdir = @abs_srcdir@
abs_top_builddir = @abs_top_builddir@
abs_top_srcdir = @abs_top_srcdir@
ac_ct_AR = @ac_ct_AR@
ac_ct_CC = @ac_ct_CC@
ac_ct_CXX = @ac_ct_CXX@
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
am__leading_dot = @am__leading_dot@
am__tar = @am__tar@
am__untar = @am__untar@
bindir = @bindir@
build = @build@
build_alias = @build_alias@
build_cpu = @build_cpu@
build_os = @build_os@
build_vendor = @build_vendor@
builddir = @builddir@
datadir = @datadir@
datarootdir = @datarootdir@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
gmp_srclinks = @gmp_srclinks@
host = @host@
host_alias = @host_alias@
host_cpu = @host_cpu@
host_os = @host_os@
host_vendor = @host_vendor@
htmldir = @htmldir@
includedir = @includedir@
infodir = @infodir@
install_sh = @install_sh@
libdir = @libdir@
libexecdir = @libexecdir@
localedir = @localedir@
localstatedir = @localstatedir@
mandir = @mandir@
mkdir_p = @mkdir_p@
mpn_objects = @mpn_objects@
mpn_objs_in_libgmp = @mpn_objs_in_libgmp@
oldincludedir = @oldincludedir@
pdfdir = @pdfdir@
prefix = @prefix@
program_transform_name = @program_transform_name@
psdir = @psdir@
sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
srcdir = @srcdir@
sysconfdir = @sysconfdir@
target_alias = @target_alias@
top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
AM_CPPFLAGS = -D__GMP_WITHIN_GMP -I$(top_srcdir)
noinst_LTLIBRARIES = libmpz.la
libmpz_la_SOURCES = aors.h aors_ui.h fits_s.h mul_i.h \
2fac_ui.c \
add.c add_ui.c abs.c aorsmul.c aorsmul_i.c and.c array_init.c \
bin_ui.c bin_uiui.c cdiv_q.c \
cdiv_q_ui.c cdiv_qr.c cdiv_qr_ui.c cdiv_r.c cdiv_r_ui.c cdiv_ui.c \
cfdiv_q_2exp.c cfdiv_r_2exp.c \
clear.c clears.c clrbit.c \
cmp.c cmp_d.c cmp_si.c cmp_ui.c cmpabs.c cmpabs_d.c cmpabs_ui.c \
com.c combit.c \
cong.c cong_2exp.c cong_ui.c \
divexact.c divegcd.c dive_ui.c divis.c divis_ui.c divis_2exp.c \
dump.c export.c fac_ui.c fdiv_q.c fdiv_q_ui.c \
fdiv_qr.c fdiv_qr_ui.c fdiv_r.c fdiv_r_ui.c fdiv_ui.c \
fib_ui.c fib2_ui.c \
fits_sint.c fits_slong.c fits_sshort.c \
fits_uint.c fits_ulong.c fits_ushort.c \
gcd.c gcd_ui.c gcdext.c get_d.c get_d_2exp.c get_si.c \
get_str.c get_ui.c getlimbn.c hamdist.c \
import.c init.c init2.c inits.c inp_raw.c inp_str.c \
invert.c ior.c iset.c iset_d.c iset_si.c iset_str.c iset_ui.c \
jacobi.c kronsz.c kronuz.c kronzs.c kronzu.c \
lcm.c lcm_ui.c limbs_read.c limbs_write.c limbs_modify.c limbs_finish.c \
lucnum_ui.c lucnum2_ui.c lucmod.c mfac_uiui.c millerrabin.c \
mod.c mul.c mul_2exp.c mul_si.c mul_ui.c n_pow_ui.c neg.c nextprime.c \
oddfac_1.c \
out_raw.c out_str.c perfpow.c perfsqr.c popcount.c pow_ui.c powm.c \
powm_sec.c powm_ui.c pprime_p.c prodlimbs.c primorial_ui.c random.c random2.c \
realloc.c realloc2.c remove.c roinit_n.c root.c rootrem.c rrandomb.c \
scan0.c scan1.c set.c set_d.c set_f.c set_q.c set_si.c set_str.c \
set_ui.c setbit.c size.c sizeinbase.c sqrt.c sqrtrem.c stronglucas.c \
sub.c sub_ui.c \
swap.c tdiv_ui.c tdiv_q.c tdiv_q_2exp.c tdiv_q_ui.c tdiv_qr.c \
tdiv_qr_ui.c tdiv_r.c tdiv_r_2exp.c tdiv_r_ui.c tstbit.c ui_pow_ui.c \
ui_sub.c urandomb.c urandomm.c xor.c
all: all-am
.SUFFIXES:
.SUFFIXES: .c .lo .o .obj
$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
@for dep in $?; do \
case '$(am__configure_deps)' in \
*$$dep*) \
( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
&& { if test -f $@; then exit 0; else break; fi; }; \
exit 1;; \
esac; \
done; \
echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu --ignore-deps mpz/Makefile'; \
$(am__cd) $(top_srcdir) && \
$(AUTOMAKE) --gnu --ignore-deps mpz/Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
@case '$?' in \
*config.status*) \
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
*) \
echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
esac;
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(am__aclocal_m4_deps):
clean-noinstLTLIBRARIES:
-test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
@list='$(noinst_LTLIBRARIES)'; \
locs=`for p in $$list; do echo $$p; done | \
sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \
sort -u`; \
test -z "$$locs" || { \
echo rm -f $${locs}; \
rm -f $${locs}; \
}
libmpz.la: $(libmpz_la_OBJECTS) $(libmpz_la_DEPENDENCIES) $(EXTRA_libmpz_la_DEPENDENCIES)
$(AM_V_CCLD)$(LINK) $(libmpz_la_OBJECTS) $(libmpz_la_LIBADD) $(LIBS)
mostlyclean-compile:
-rm -f *.$(OBJEXT)
distclean-compile:
-rm -f *.tab.c
.c.o:
$(AM_V_CC)$(COMPILE) -c -o $@ $<
.c.obj:
$(AM_V_CC)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
.c.lo:
$(AM_V_CC)$(LTCOMPILE) -c -o $@ $<
mostlyclean-libtool:
-rm -f *.lo
clean-libtool:
-rm -rf .libs _libs
ID: $(am__tagged_files)
$(am__define_uniq_tagged_files); mkid -fID $$unique
tags: tags-am
TAGS: tags
tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
set x; \
here=`pwd`; \
$(am__define_uniq_tagged_files); \
shift; \
if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
test -n "$$unique" || unique=$$empty_fix; \
if test $$# -gt 0; then \
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
"$$@" $$unique; \
else \
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
$$unique; \
fi; \
fi
ctags: ctags-am
CTAGS: ctags
ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
$(am__define_uniq_tagged_files); \
test -z "$(CTAGS_ARGS)$$unique" \
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
$$unique
GTAGS:
here=`$(am__cd) $(top_builddir) && pwd` \
&& $(am__cd) $(top_srcdir) \
&& gtags -i $(GTAGS_ARGS) "$$here"
cscopelist: cscopelist-am
cscopelist-am: $(am__tagged_files)
list='$(am__tagged_files)'; \
case "$(srcdir)" in \
[\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
*) sdir=$(subdir)/$(srcdir) ;; \
esac; \
for i in $$list; do \
if test -f "$$i"; then \
echo "$(subdir)/$$i"; \
else \
echo "$$sdir/$$i"; \
fi; \
done >> $(top_builddir)/cscope.files
distclean-tags:
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
distdir: $(DISTFILES)
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
list='$(DISTFILES)'; \
dist_files=`for file in $$list; do echo $$file; done | \
sed -e "s|^$$srcdirstrip/||;t" \
-e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
case $$dist_files in \
*/*) $(MKDIR_P) `echo "$$dist_files" | \
sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
sort -u` ;; \
esac; \
for file in $$dist_files; do \
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
if test -d $$d/$$file; then \
dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
if test -d "$(distdir)/$$file"; then \
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
fi; \
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
fi; \
cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
else \
test -f "$(distdir)/$$file" \
|| cp -p $$d/$$file "$(distdir)/$$file" \
|| exit 1; \
fi; \
done
check-am: all-am
check: check-am
all-am: Makefile $(LTLIBRARIES)
installdirs:
install: install-am
install-exec: install-exec-am
install-data: install-data-am
uninstall: uninstall-am
install-am: all-am
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
installcheck: installcheck-am
install-strip:
if test -z '$(STRIP)'; then \
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
install; \
else \
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
"INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
fi
mostlyclean-generic:
clean-generic:
distclean-generic:
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
maintainer-clean-generic:
@echo "This command is intended for maintainers to use"
@echo "it deletes files that may require special tools to rebuild."
clean: clean-am
clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
mostlyclean-am
distclean: distclean-am
-rm -f Makefile
distclean-am: clean-am distclean-compile distclean-generic \
distclean-tags
dvi: dvi-am
dvi-am:
html: html-am
html-am:
info: info-am
info-am:
install-data-am:
install-dvi: install-dvi-am
install-dvi-am:
install-exec-am:
install-html: install-html-am
install-html-am:
install-info: install-info-am
install-info-am:
install-man:
install-pdf: install-pdf-am
install-pdf-am:
install-ps: install-ps-am
install-ps-am:
installcheck-am:
maintainer-clean: maintainer-clean-am
-rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic
mostlyclean: mostlyclean-am
mostlyclean-am: mostlyclean-compile mostlyclean-generic \
mostlyclean-libtool
pdf: pdf-am
pdf-am:
ps: ps-am
ps-am:
uninstall-am:
.MAKE: install-am install-strip
.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \
clean-libtool clean-noinstLTLIBRARIES cscopelist-am ctags \
ctags-am distclean distclean-compile distclean-generic \
distclean-libtool distclean-tags distdir dvi dvi-am html \
html-am info info-am install install-am install-data \
install-data-am install-dvi install-dvi-am install-exec \
install-exec-am install-html install-html-am install-info \
install-info-am install-man install-pdf install-pdf-am \
install-ps install-ps-am install-strip installcheck \
installcheck-am installdirs maintainer-clean \
maintainer-clean-generic mostlyclean mostlyclean-compile \
mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
tags tags-am uninstall uninstall-am
.PRECIOUS: Makefile
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:

View File

@@ -0,0 +1,54 @@
/* mpz_abs(dst, src) -- Assign the absolute value of SRC to DST.
Copyright 1991, 1993-1995, 2001, 2012 Free Software Foundation, Inc.
This file is part of the GNU MP Library.
The GNU MP Library is free software; you can redistribute it and/or modify
it under the terms of either:
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
or
* the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any
later version.
or both in parallel, as here.
The GNU MP Library 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 copies of the GNU General Public License and the
GNU Lesser General Public License along with the GNU MP Library. If not,
see https://www.gnu.org/licenses/. */
#define __GMP_FORCE_mpz_abs 1
#include "gmp-impl.h"
void
mpz_abs (mpz_ptr w, mpz_srcptr u)
{
mp_ptr wp;
mp_srcptr up;
mp_size_t size;
size = ABSIZ (u);
if (u != w)
{
wp = MPZ_NEWALLOC (w, size);
up = PTR (u);
MPN_COPY (wp, up, size);
}
SIZ (w) = size;
}

View File

@@ -0,0 +1,33 @@
/* mpz_add -- add integers.
Copyright 2001 Free Software Foundation, Inc.
This file is part of the GNU MP Library.
The GNU MP Library is free software; you can redistribute it and/or modify
it under the terms of either:
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
or
* the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any
later version.
or both in parallel, as here.
The GNU MP Library 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 copies of the GNU General Public License and the
GNU Lesser General Public License along with the GNU MP Library. If not,
see https://www.gnu.org/licenses/. */
#define OPERATION_add
#include "aors.h"

View File

@@ -0,0 +1,33 @@
/* mpz_add_ui -- Add an mpz_t and an unsigned one-word integer.
Copyright 2001 Free Software Foundation, Inc.
This file is part of the GNU MP Library.
The GNU MP Library is free software; you can redistribute it and/or modify
it under the terms of either:
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
or
* the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any
later version.
or both in parallel, as here.
The GNU MP Library 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 copies of the GNU General Public License and the
GNU Lesser General Public License along with the GNU MP Library. If not,
see https://www.gnu.org/licenses/. */
#define OPERATION_add_ui
#include "aors_ui.h"

View File

@@ -0,0 +1,222 @@
/* mpz_and -- Logical and.
Copyright 1991, 1993, 1994, 1996, 1997, 2000, 2001, 2003, 2005, 2012,
2015-2018 Free Software Foundation, Inc.
This file is part of the GNU MP Library.
The GNU MP Library is free software; you can redistribute it and/or modify
it under the terms of either:
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
or
* the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any
later version.
or both in parallel, as here.
The GNU MP Library 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 copies of the GNU General Public License and the
GNU Lesser General Public License along with the GNU MP Library. If not,
see https://www.gnu.org/licenses/. */
#include "gmp-impl.h"
void
mpz_and (mpz_ptr res, mpz_srcptr op1, mpz_srcptr op2)
{
mp_srcptr op1_ptr, op2_ptr;
mp_size_t op1_size, op2_size;
mp_ptr res_ptr;
mp_size_t res_size;
mp_size_t i;
op1_size = SIZ(op1);
op2_size = SIZ(op2);
if (op1_size < op2_size)
{
MPZ_SRCPTR_SWAP (op1, op2);
MP_SIZE_T_SWAP (op1_size, op2_size);
}
op1_ptr = PTR(op1);
op2_ptr = PTR(op2);
if (op2_size >= 0)
{
/* First loop finds the size of the result. */
for (i = op2_size; --i >= 0;)
if ((op1_ptr[i] & op2_ptr[i]) != 0)
{
res_size = i + 1;
/* Handle allocation, now then we know exactly how much space is
needed for the result. */
/* Don't re-read op1_ptr and op2_ptr. Since res_size <=
MIN(op1_size, op2_size), res is not changed when op1
is identical to res or op2 is identical to res. */
SIZ (res) = res_size;
mpn_and_n (MPZ_NEWALLOC (res, res_size), op1_ptr, op2_ptr, res_size);
return;
}
SIZ (res) = 0;
}
else
{
TMP_DECL;
op2_size = -op2_size;
TMP_MARK;
if (op1_size < 0)
{
mp_ptr opx, opy;
/* Both operands are negative, so will be the result.
-((-OP1) & (-OP2)) = -(~(OP1 - 1) & ~(OP2 - 1)) =
= ~(~(OP1 - 1) & ~(OP2 - 1)) + 1 =
= ((OP1 - 1) | (OP2 - 1)) + 1 */
/* It might seem as we could end up with an (invalid) result with
a leading zero-limb here when one of the operands is of the
type 1,,0,,..,,.0. But some analysis shows that we surely
would get carry into the zero-limb in this situation... */
op1_size = -op1_size;
TMP_ALLOC_LIMBS_2 (opx, op1_size, opy, op2_size);
mpn_sub_1 (opx, op1_ptr, op1_size, (mp_limb_t) 1);
op1_ptr = opx;
mpn_sub_1 (opy, op2_ptr, op2_size, (mp_limb_t) 1);
op2_ptr = opy;
res_ptr = MPZ_NEWALLOC (res, 1 + op2_size);
/* Don't re-read OP1_PTR and OP2_PTR. They point to temporary
space--never to the space PTR(res) used to point to before
reallocation. */
MPN_COPY (res_ptr + op1_size, op2_ptr + op1_size,
op2_size - op1_size);
mpn_ior_n (res_ptr, op1_ptr, op2_ptr, op1_size);
TMP_FREE;
res_size = op2_size;
res_ptr[res_size] = 0;
MPN_INCR_U (res_ptr, res_size + 1, (mp_limb_t) 1);
res_size += res_ptr[res_size];
SIZ(res) = -res_size;
}
else
{
#if ANDNEW
mp_size_t op2_lim;
mp_size_t count;
/* OP2 must be negated as with infinite precision.
Scan from the low end for a non-zero limb. The first non-zero
limb is simply negated (two's complement). Any subsequent
limbs are one's complemented. Of course, we don't need to
handle more limbs than there are limbs in the other, positive
operand as the result for those limbs is going to become zero
anyway. */
/* Scan for the least significant non-zero OP2 limb, and zero the
result meanwhile for those limb positions. (We will surely
find a non-zero limb, so we can write the loop with one
termination condition only.) */
for (i = 0; op2_ptr[i] == 0; i++)
res_ptr[i] = 0;
op2_lim = i;
if (op1_size <= op2_size)
{
/* The ones-extended OP2 is >= than the zero-extended OP1.
RES_SIZE <= OP1_SIZE. Find the exact size. */
for (i = op1_size - 1; i > op2_lim; i--)
if ((op1_ptr[i] & ~op2_ptr[i]) != 0)
break;
res_size = i + 1;
for (i = res_size - 1; i > op2_lim; i--)
res_ptr[i] = op1_ptr[i] & ~op2_ptr[i];
res_ptr[op2_lim] = op1_ptr[op2_lim] & -op2_ptr[op2_lim];
/* Yes, this *can* happen! */
MPN_NORMALIZE (res_ptr, res_size);
}
else
{
/* The ones-extended OP2 is < than the zero-extended OP1.
RES_SIZE == OP1_SIZE, since OP1 is normalized. */
res_size = op1_size;
MPN_COPY (res_ptr + op2_size, op1_ptr + op2_size, op1_size - op2_size);
for (i = op2_size - 1; i > op2_lim; i--)
res_ptr[i] = op1_ptr[i] & ~op2_ptr[i];
res_ptr[op2_lim] = op1_ptr[op2_lim] & -op2_ptr[op2_lim];
}
#else
/* OP1 is positive and zero-extended,
OP2 is negative and ones-extended.
The result will be positive.
OP1 & -OP2 = OP1 & ~(OP2 - 1). */
mp_ptr opx;
opx = TMP_ALLOC_LIMBS (op2_size);
mpn_sub_1 (opx, op2_ptr, op2_size, (mp_limb_t) 1);
op2_ptr = opx;
if (op1_size > op2_size)
{
/* The result has the same size as OP1, since OP1 is normalized
and longer than the ones-extended OP2. */
res_size = op1_size;
/* Handle allocation, now then we know exactly how much space is
needed for the result. */
res_ptr = MPZ_NEWALLOC (res, res_size);
/* Don't re-read OP1_PTR or OP2_PTR. Since res_size = op1_size,
op1 is not changed if it is identical to res.
OP2_PTR points to temporary space. */
mpn_andn_n (res_ptr, op1_ptr, op2_ptr, op2_size);
MPN_COPY (res_ptr + op2_size, op1_ptr + op2_size, res_size - op2_size);
}
else
{
/* Find out the exact result size. Ignore the high limbs of OP2,
OP1 is zero-extended and would make the result zero. */
res_size = 0;
for (i = op1_size; --i >= 0;)
if ((op1_ptr[i] & ~op2_ptr[i]) != 0)
{
res_size = i + 1;
/* Handle allocation, now then we know exactly how much
space is needed for the result. */
/* Don't re-read OP1_PTR. Since res_size <= op1_size,
op1 is not changed if it is identical to res. Don't
re-read OP2_PTR. It points to temporary space--never
to the space PTR(res) used to point to before
reallocation. */
mpn_andn_n (MPZ_NEWALLOC (res, res_size), op1_ptr, op2_ptr, res_size);
break;
}
}
#endif
SIZ(res) = res_size;
TMP_FREE;
}
}
}

View File

@@ -0,0 +1,129 @@
/* mpz_add, mpz_sub -- add or subtract integers.
Copyright 1991, 1993, 1994, 1996, 2000, 2001, 2011, 2012, 2020 Free
Software Foundation, Inc.
This file is part of the GNU MP Library.
The GNU MP Library is free software; you can redistribute it and/or modify
it under the terms of either:
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
or
* the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any
later version.
or both in parallel, as here.
The GNU MP Library 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 copies of the GNU General Public License and the
GNU Lesser General Public License along with the GNU MP Library. If not,
see https://www.gnu.org/licenses/. */
#include "gmp-impl.h"
#ifdef OPERATION_add
#define FUNCTION mpz_add
#define VARIATION
#endif
#ifdef OPERATION_sub
#define FUNCTION mpz_sub
#define VARIATION -
#endif
#ifndef FUNCTION
Error, need OPERATION_add or OPERATION_sub
#endif
void
FUNCTION (mpz_ptr w, mpz_srcptr u, mpz_srcptr v)
{
mp_srcptr up, vp;
mp_ptr wp;
mp_size_t usize, vsize, wsize;
mp_size_t abs_usize;
mp_size_t abs_vsize;
usize = SIZ(u);
vsize = VARIATION SIZ(v);
abs_usize = ABS (usize);
abs_vsize = ABS (vsize);
if (abs_usize < abs_vsize)
{
/* Swap U and V. */
MPZ_SRCPTR_SWAP (u, v);
MP_SIZE_T_SWAP (usize, vsize);
MP_SIZE_T_SWAP (abs_usize, abs_vsize);
}
/* True: ABS_USIZE >= ABS_VSIZE. */
/* If not space for w (and possible carry), increase space. */
wsize = abs_usize + 1;
wp = MPZ_REALLOC (w, wsize);
/* These must be after realloc (u or v may be the same as w). */
up = PTR(u);
vp = PTR(v);
if ((usize ^ vsize) < 0)
{
/* U and V have different sign. Need to compare them to determine
which operand to subtract from which. */
/* This test is right since ABS_USIZE >= ABS_VSIZE. */
if (abs_usize != abs_vsize)
{
mpn_sub (wp, up, abs_usize, vp, abs_vsize);
wsize = abs_usize;
MPN_NORMALIZE_NOT_ZERO (wp, wsize);
if (usize < 0)
wsize = -wsize;
}
else
{
int cmp = mpn_cmp (up, vp, abs_usize);
if (cmp < 0)
{
mpn_sub_n (wp, vp, up, abs_usize);
wsize = abs_usize;
MPN_NORMALIZE_NOT_ZERO (wp, wsize);
if (usize >= 0)
wsize = -wsize;
}
else if (cmp > 0)
{
mpn_sub_n (wp, up, vp, abs_usize);
wsize = abs_usize;
MPN_NORMALIZE_NOT_ZERO (wp, wsize);
if (usize < 0)
wsize = -wsize;
}
else
wsize = 0;
}
}
else
{
/* U and V have same sign. Add them. */
mp_limb_t cy_limb = mpn_add (wp, up, abs_usize, vp, abs_vsize);
wp[abs_usize] = cy_limb;
wsize = abs_usize + cy_limb;
if (usize < 0)
wsize = -wsize;
}
SIZ(w) = wsize;
}

View File

@@ -0,0 +1,125 @@
/* mpz_add_ui, mpz_sub_ui -- Add or subtract an mpz_t and an unsigned
one-word integer.
Copyright 1991, 1993, 1994, 1996, 1999-2002, 2004, 2012, 2013, 2015,
2020 Free Software Foundation, Inc.
This file is part of the GNU MP Library.
The GNU MP Library is free software; you can redistribute it and/or modify
it under the terms of either:
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
or
* the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any
later version.
or both in parallel, as here.
The GNU MP Library 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 copies of the GNU General Public License and the
GNU Lesser General Public License along with the GNU MP Library. If not,
see https://www.gnu.org/licenses/. */
#include "gmp-impl.h"
#ifdef OPERATION_add_ui
#define FUNCTION mpz_add_ui
#define FUNCTION2 mpz_add
#define VARIATION_CMP >=
#define VARIATION_NEG
#define VARIATION_UNNEG -
#endif
#ifdef OPERATION_sub_ui
#define FUNCTION mpz_sub_ui
#define FUNCTION2 mpz_sub
#define VARIATION_CMP <
#define VARIATION_NEG -
#define VARIATION_UNNEG
#endif
#ifndef FUNCTION
Error, need OPERATION_add_ui or OPERATION_sub_ui
#endif
void
FUNCTION (mpz_ptr w, mpz_srcptr u, unsigned long int vval)
{
mp_srcptr up;
mp_ptr wp;
mp_size_t usize, wsize;
mp_size_t abs_usize;
#if BITS_PER_ULONG > GMP_NUMB_BITS /* avoid warnings about shift amount */
if (vval > GMP_NUMB_MAX)
{
mpz_t v;
mp_limb_t vl[2];
PTR(v) = vl;
vl[0] = vval & GMP_NUMB_MASK;
vl[1] = vval >> GMP_NUMB_BITS;
SIZ(v) = 2;
FUNCTION2 (w, u, v);
return;
}
#endif
usize = SIZ (u);
if (usize == 0)
{
MPZ_NEWALLOC (w, 1)[0] = vval;
SIZ (w) = VARIATION_NEG (vval != 0);
return;
}
abs_usize = ABS (usize);
if (usize VARIATION_CMP 0)
{
mp_limb_t cy;
/* If not space for W (and possible carry), increase space. */
wp = MPZ_REALLOC (w, abs_usize + 1);
/* These must be after realloc (U may be the same as W). */
up = PTR (u);
cy = mpn_add_1 (wp, up, abs_usize, (mp_limb_t) vval);
wp[abs_usize] = cy;
wsize = VARIATION_NEG (abs_usize + cy);
}
else
{
/* If not space for W, increase space. */
wp = MPZ_REALLOC (w, abs_usize);
/* These must be after realloc (U may be the same as W). */
up = PTR (u);
/* The signs are different. Need exact comparison to determine
which operand to subtract from which. */
if (abs_usize == 1 && up[0] < vval)
{
wp[0] = vval - up[0];
wsize = VARIATION_NEG 1;
}
else
{
mpn_sub_1 (wp, up, abs_usize, (mp_limb_t) vval);
/* Size can decrease with at most one limb. */
wsize = VARIATION_UNNEG (abs_usize - (wp[abs_usize - 1] == 0));
}
}
SIZ (w) = wsize;
}

View File

@@ -0,0 +1,179 @@
/* mpz_addmul, mpz_submul -- add or subtract multiple.
Copyright 2001, 2004, 2005, 2012, 2022 Free Software Foundation, Inc.
This file is part of the GNU MP Library.
The GNU MP Library is free software; you can redistribute it and/or modify
it under the terms of either:
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
or
* the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any
later version.
or both in parallel, as here.
The GNU MP Library 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 copies of the GNU General Public License and the
GNU Lesser General Public License along with the GNU MP Library. If not,
see https://www.gnu.org/licenses/. */
#include "gmp-impl.h"
/* expecting x and y both with non-zero high limbs */
#define mpn_cmp_twosizes_lt(xp,xsize, yp,ysize) \
((xsize) < (ysize) \
|| ((xsize) == (ysize) && mpn_cmp (xp, yp, xsize) < 0))
/* sub>=0 means an addmul w += x*y, sub<0 means a submul w -= x*y.
The signs of w, x and y are fully accounted for by each flipping "sub".
The sign of w is retained for the result, unless the absolute value
submul underflows, in which case it flips. */
static void __gmpz_aorsmul (REGPARM_3_1 (mpz_ptr w, mpz_srcptr x, mpz_srcptr y, mp_size_t sub)) REGPARM_ATTR (1);
#define mpz_aorsmul(w,x,y,sub) __gmpz_aorsmul (REGPARM_3_1 (w, x, y, sub))
REGPARM_ATTR (1) static void
mpz_aorsmul (mpz_ptr w, mpz_srcptr x, mpz_srcptr y, mp_size_t sub)
{
mp_size_t xsize, ysize, tsize, wsize, wsize_signed;
mp_ptr wp, tp;
mp_limb_t c;
TMP_DECL;
/* w unaffected if x==0 or y==0 */
xsize = SIZ(x);
ysize = SIZ(y);
if (xsize == 0 || ysize == 0)
return;
/* make x the bigger of the two */
if (ABS(ysize) > ABS(xsize))
{
MPZ_SRCPTR_SWAP (x, y);
MP_SIZE_T_SWAP (xsize, ysize);
}
sub ^= ysize;
ysize = ABS(ysize);
/* use mpn_addmul_1/mpn_submul_1 if possible */
if (ysize == 1)
{
mpz_aorsmul_1 (w, x, PTR(y)[0], sub);
return;
}
sub ^= xsize;
xsize = ABS(xsize);
wsize_signed = SIZ(w);
sub ^= wsize_signed;
wsize = ABS(wsize_signed);
tsize = xsize + ysize;
wp = MPZ_REALLOC (w, MAX (wsize, tsize) + 1);
if (wsize_signed == 0)
{
mp_limb_t high;
/* Nothing to add to, just set w=x*y. No w==x or w==y overlap here,
since we know x,y!=0 but w==0. */
if (x == y)
{
mpn_sqr (wp, PTR(x),xsize);
high = wp[tsize-1];
}
else
high = mpn_mul (wp, PTR(x),xsize, PTR(y),ysize);
tsize -= (high == 0);
SIZ(w) = (sub >= 0 ? tsize : -tsize);
return;
}
TMP_MARK;
tp = TMP_ALLOC_LIMBS (tsize);
if (x == y)
{
mpn_sqr (tp, PTR(x),xsize);
tsize -= (tp[tsize-1] == 0);
}
else
{
mp_limb_t high;
high = mpn_mul (tp, PTR(x),xsize, PTR(y),ysize);
tsize -= (high == 0);
}
ASSERT (tp[tsize-1] != 0);
if (sub >= 0)
{
mp_srcptr up = wp;
mp_size_t usize = wsize;
if (usize < tsize)
{
up = tp;
usize = tsize;
tp = wp;
tsize = wsize;
wsize = usize;
}
c = mpn_add (wp, up,usize, tp,tsize);
wp[wsize] = c;
wsize += (c != 0);
}
else
{
mp_srcptr up = wp;
mp_size_t usize = wsize;
if (mpn_cmp_twosizes_lt (up,usize, tp,tsize))
{
up = tp;
usize = tsize;
tp = wp;
tsize = wsize;
wsize = usize;
wsize_signed = -wsize_signed;
}
ASSERT_NOCARRY (mpn_sub (wp, up,usize, tp,tsize));
wsize = usize;
MPN_NORMALIZE (wp, wsize);
}
SIZ(w) = (wsize_signed >= 0 ? wsize : -wsize);
TMP_FREE;
}
void
mpz_addmul (mpz_ptr w, mpz_srcptr u, mpz_srcptr v)
{
mpz_aorsmul (w, u, v, (mp_size_t) 0);
}
void
mpz_submul (mpz_ptr w, mpz_srcptr u, mpz_srcptr v)
{
mpz_aorsmul (w, u, v, (mp_size_t) -1);
}

View File

@@ -0,0 +1,254 @@
/* mpz_addmul_ui, mpz_submul_ui - add or subtract small multiple.
THE mpz_aorsmul_1 FUNCTION IN THIS FILE IS FOR INTERNAL USE ONLY AND IS
ALMOST CERTAIN TO BE SUBJECT TO INCOMPATIBLE CHANGES OR DISAPPEAR
COMPLETELY IN FUTURE GNU MP RELEASES.
Copyright 2001, 2002, 2004, 2005, 2012, 2021, 2022 Free Software
Foundation, Inc.
This file is part of the GNU MP Library.
The GNU MP Library is free software; you can redistribute it and/or modify
it under the terms of either:
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
or
* the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any
later version.
or both in parallel, as here.
The GNU MP Library 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 copies of the GNU General Public License and the
GNU Lesser General Public License along with the GNU MP Library. If not,
see https://www.gnu.org/licenses/. */
#include "gmp-impl.h"
#if HAVE_NATIVE_mpn_mul_1c
#define MPN_MUL_1C(cout, dst, src, size, n, cin) \
do { \
(cout) = mpn_mul_1c (dst, src, size, n, cin); \
} while (0)
#else
#define MPN_MUL_1C(cout, dst, src, size, n, cin) \
do { \
mp_limb_t __cy; \
__cy = mpn_mul_1 (dst, src, size, n); \
(cout) = __cy + mpn_add_1 (dst, dst, size, cin); \
} while (0)
#endif
/* sub>=0 means an addmul w += x*y, sub<0 means a submul w -= x*y.
All that's needed to account for negative w or x is to flip "sub".
The final w will retain its sign, unless an underflow occurs in a submul
of absolute values, in which case it's flipped.
If x has more limbs than w, then mpn_submul_1 followed by mpn_com is
used. The alternative would be mpn_mul_1 into temporary space followed
by mpn_sub_n. Avoiding temporary space seem good, and submul+com stands
a chance of being faster since it involves only one set of carry
propagations, not two. Note that doing an addmul_1 with a
twos-complement negative y doesn't work, because it effectively adds an
extra x * 2^GMP_LIMB_BITS. */
REGPARM_ATTR(1) void
mpz_aorsmul_1 (mpz_ptr w, mpz_srcptr x, mp_limb_t y, mp_size_t sub)
{
mp_size_t xsize, wsize, wsize_signed, new_wsize, min_size, dsize;
mp_srcptr xp;
mp_ptr wp;
mp_limb_t cy;
/* w unaffected if x==0 or y==0 */
xsize = SIZ (x);
if (xsize == 0 || y == 0)
return;
sub ^= xsize;
xsize = ABS (xsize);
wsize_signed = SIZ (w);
if (wsize_signed == 0)
{
/* nothing to add to, just set x*y, "sub" gives the sign */
wp = MPZ_NEWALLOC (w, xsize+1);
cy = mpn_mul_1 (wp, PTR(x), xsize, y);
wp[xsize] = cy;
xsize += (cy != 0);
SIZ (w) = (sub >= 0 ? xsize : -xsize);
return;
}
sub ^= wsize_signed;
wsize = ABS (wsize_signed);
new_wsize = MAX (wsize, xsize);
wp = MPZ_REALLOC (w, new_wsize+1);
xp = PTR (x);
min_size = MIN (wsize, xsize);
if (sub >= 0)
{
/* addmul of absolute values */
cy = mpn_addmul_1 (wp, xp, min_size, y);
wp += min_size;
xp += min_size;
dsize = xsize - wsize;
#if HAVE_NATIVE_mpn_mul_1c
if (dsize > 0)
cy = mpn_mul_1c (wp, xp, dsize, y, cy);
else if (dsize < 0)
{
dsize = -dsize;
cy = mpn_add_1 (wp, wp, dsize, cy);
}
#else
if (dsize != 0)
{
mp_limb_t cy2;
if (dsize > 0)
cy2 = mpn_mul_1 (wp, xp, dsize, y);
else
{
dsize = -dsize;
cy2 = 0;
}
cy = cy2 + mpn_add_1 (wp, wp, dsize, cy);
}
#endif
wp[dsize] = cy;
new_wsize += (cy != 0);
}
else
{
/* submul of absolute values */
cy = mpn_submul_1 (wp, xp, min_size, y);
if (wsize >= xsize)
{
/* if w bigger than x, then propagate borrow through it */
if (wsize != xsize)
cy = mpn_sub_1 (wp+xsize, wp+xsize, wsize-xsize, cy);
if (cy != 0)
{
/* Borrow out of w, take twos complement negative to get
absolute value, flip sign of w. */
cy -= mpn_neg (wp, wp, new_wsize);
wp[new_wsize] = cy;
new_wsize += (cy != 0);
wsize_signed = -wsize_signed;
}
}
else /* wsize < xsize */
{
/* x bigger than w, so want x*y-w. Submul has given w-x*y, so
take twos complement and use an mpn_mul_1 for the rest. */
mp_limb_t cy2;
/* -(-cy*b^n + w-x*y) = (cy-1)*b^n + ~(w-x*y) + 1 */
cy -= mpn_neg (wp, wp, wsize);
/* If cy-1 == -1 then hold that -1 for latter. mpn_submul_1 never
returns cy==MP_LIMB_T_MAX so that value always indicates a -1. */
cy2 = (cy == MP_LIMB_T_MAX);
cy += cy2;
MPN_MUL_1C (cy, wp+wsize, xp+wsize, xsize-wsize, y, cy);
wp[new_wsize] = cy;
new_wsize += (cy != 0);
/* Apply any -1 from above. The value at wp+wsize is non-zero
because y!=0 and the high limb of x will be non-zero. */
if (cy2)
MPN_DECR_U (wp+wsize, new_wsize-wsize, CNST_LIMB(1));
wsize_signed = -wsize_signed;
}
/* submul can produce high zero limbs due to cancellation, both when w
has more limbs or x has more */
MPN_NORMALIZE (wp, new_wsize);
}
SIZ (w) = (wsize_signed >= 0 ? new_wsize : -new_wsize);
ASSERT (new_wsize == 0 || PTR(w)[new_wsize-1] != 0);
}
void
mpz_addmul_ui (mpz_ptr w, mpz_srcptr x, unsigned long y)
{
#if BITS_PER_ULONG > GMP_NUMB_BITS
if (UNLIKELY (y > GMP_NUMB_MAX))
{
mpz_t t;
mp_ptr tp;
mp_size_t xn;
TMP_DECL;
TMP_MARK;
xn = SIZ (x);
if (xn == 0) return;
MPZ_TMP_INIT (t, ABS (xn) + 1);
tp = PTR (t);
tp[0] = 0;
MPN_COPY (tp + 1, PTR(x), ABS (xn));
SIZ(t) = xn >= 0 ? xn + 1 : xn - 1;
mpz_aorsmul_1 (w, t, (mp_limb_t) y >> GMP_NUMB_BITS, (mp_size_t) 0);
PTR(t) = tp + 1;
SIZ(t) = xn;
mpz_aorsmul_1 (w, t, (mp_limb_t) y & GMP_NUMB_MASK, (mp_size_t) 0);
TMP_FREE;
return;
}
#endif
mpz_aorsmul_1 (w, x, (mp_limb_t) y, (mp_size_t) 0);
}
void
mpz_submul_ui (mpz_ptr w, mpz_srcptr x, unsigned long y)
{
#if BITS_PER_ULONG > GMP_NUMB_BITS
if (y > GMP_NUMB_MAX)
{
mpz_t t;
mp_ptr tp;
mp_size_t xn;
TMP_DECL;
TMP_MARK;
xn = SIZ (x);
if (xn == 0) return;
MPZ_TMP_INIT (t, ABS (xn) + 1);
tp = PTR (t);
tp[0] = 0;
MPN_COPY (tp + 1, PTR(x), ABS (xn));
SIZ(t) = xn >= 0 ? xn + 1 : xn - 1;
mpz_aorsmul_1 (w, t, (mp_limb_t) y >> GMP_NUMB_BITS, (mp_size_t) -1);
PTR(t) = tp + 1;
SIZ(t) = xn;
mpz_aorsmul_1 (w, t, (mp_limb_t) y & GMP_NUMB_MASK, (mp_size_t) -1);
TMP_FREE;
return;
}
#endif
mpz_aorsmul_1 (w, x, (mp_limb_t) y & GMP_NUMB_MASK, (mp_size_t) -1);
}

View File

@@ -0,0 +1,49 @@
/* mpz_array_init (array, array_size, size_per_elem) --
Copyright 1991, 1993-1995, 2000-2002, 2012 Free Software Foundation, Inc.
This file is part of the GNU MP Library.
The GNU MP Library is free software; you can redistribute it and/or modify
it under the terms of either:
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
or
* the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any
later version.
or both in parallel, as here.
The GNU MP Library 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 copies of the GNU General Public License and the
GNU Lesser General Public License along with the GNU MP Library. If not,
see https://www.gnu.org/licenses/. */
#include "gmp-impl.h"
void
mpz_array_init (mpz_ptr arr, mp_size_t arr_size, mp_size_t nbits)
{
mp_ptr p;
mp_size_t i;
mp_size_t nlimbs;
nlimbs = nbits / GMP_NUMB_BITS + 1;
p = __GMP_ALLOCATE_FUNC_LIMBS (arr_size * nlimbs);
for (i = 0; i < arr_size; i++)
{
ALLOC (&arr[i]) = nlimbs + 1; /* Yes, lie a little... */
SIZ (&arr[i]) = 0;
PTR (&arr[i]) = p + i * nlimbs;
}
}

View File

@@ -0,0 +1,459 @@
/* mpz_bin_ui(RESULT, N, K) -- Set RESULT to N over K.
Copyright 1998-2002, 2012, 2013, 2015, 2017-2018, 2020 Free Software
Foundation, Inc.
This file is part of the GNU MP Library.
The GNU MP Library is free software; you can redistribute it and/or modify
it under the terms of either:
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
or
* the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any
later version.
or both in parallel, as here.
The GNU MP Library 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 copies of the GNU General Public License and the
GNU Lesser General Public License along with the GNU MP Library. If not,
see https://www.gnu.org/licenses/. */
#include "gmp-impl.h"
/* How many special cases? Minimum is 2: 0 and 1;
* also 3 {0,1,2} and 5 {0,1,2,3,4} are implemented.
*/
#define APARTAJ_KALKULOJ 2
/* Whether to use (1) or not (0) the function mpz_bin_uiui whenever
* the operands fit.
*/
#define UZU_BIN_UIUI 0
/* Whether to use a shortcut to precompute the product of four
* elements (1), or precompute only the product of a couple (0).
*
* In both cases the precomputed product is then updated with some
* linear operations to obtain the product of the next four (1)
* [or two (0)] operands.
*/
#define KVAROPE 1
static void
posmpz_init (mpz_ptr r)
{
mp_ptr rp;
ASSERT (SIZ (r) > 0);
rp = SIZ (r) + MPZ_REALLOC (r, SIZ (r) + 2);
*rp = 0;
*++rp = 0;
}
/* Equivalent to mpz_add_ui (r, r, in), but faster when
0 < SIZ (r) < ALLOC (r) and limbs above SIZ (r) contain 0. */
static void
posmpz_inc_ui (mpz_ptr r, unsigned long in)
{
#if BITS_PER_ULONG > GMP_NUMB_BITS
mpz_add_ui (r, r, in);
#else
ASSERT (SIZ (r) > 0);
MPN_INCR_U (PTR (r), SIZ (r) + 1, in);
SIZ (r) += PTR (r)[SIZ (r)];
#endif
}
/* Equivalent to mpz_sub_ui (r, r, in), but faster when
0 < SIZ (r) and we know in advance that the result is positive. */
static void
posmpz_dec_ui (mpz_ptr r, unsigned long in)
{
#if BITS_PER_ULONG > GMP_NUMB_BITS
mpz_sub_ui (r, r, in);
#else
ASSERT (mpz_cmp_ui (r, in) >= 0);
MPN_DECR_U (PTR (r), SIZ (r), in);
SIZ (r) -= (PTR (r)[SIZ (r)-1] == 0);
#endif
}
/* Equivalent to mpz_tdiv_q_2exp (r, r, 1), but faster when
0 < SIZ (r) and we know in advance that the result is positive. */
static void
posmpz_rsh1 (mpz_ptr r)
{
mp_ptr rp;
mp_size_t rn;
rn = SIZ (r);
rp = PTR (r);
ASSERT (rn > 0);
mpn_rshift (rp, rp, rn, 1);
SIZ (r) -= rp[rn - 1] == 0;
}
/* Computes r = n(n+(2*k-1))/2
It uses a sqare instead of a product, computing
r = ((n+k-1)^2 + n - (k-1)^2)/2
As a side effect, sets t = n+k-1
*/
static void
mpz_hmul_nbnpk (mpz_ptr r, mpz_srcptr n, unsigned long int k, mpz_ptr t)
{
ASSERT (k > 0 && SIZ(n) > 0);
--k;
mpz_add_ui (t, n, k);
mpz_mul (r, t, t);
mpz_add (r, r, n);
posmpz_rsh1 (r);
if (LIKELY (k <= (1UL << (BITS_PER_ULONG / 2))))
posmpz_dec_ui (r, (k + (k & 1))*(k >> 1));
else
{
mpz_t tmp;
mpz_init_set_ui (tmp, (k + (k & 1)));
mpz_mul_ui (tmp, tmp, k >> 1);
mpz_sub (r, r, tmp);
mpz_clear (tmp);
}
}
#if KVAROPE
static void
rek_raising_fac4 (mpz_ptr r, mpz_ptr p, mpz_ptr P, unsigned long int k, unsigned long int lk, mpz_ptr t)
{
if (k - lk < 5)
{
do {
posmpz_inc_ui (p, 4*k+2);
mpz_addmul_ui (P, p, 4*k);
posmpz_dec_ui (P, k);
mpz_mul (r, r, P);
} while (--k > lk);
}
else
{
mpz_t lt;
unsigned long int m;
ALLOC (lt) = 0;
SIZ (lt) = 0;
if (t == NULL)
t = lt;
m = ((k + lk) >> 1) + 1;
rek_raising_fac4 (r, p, P, k, m, t);
posmpz_inc_ui (p, 4*m+2);
mpz_addmul_ui (P, p, 4*m);
posmpz_dec_ui (P, m);
mpz_set (t, P);
rek_raising_fac4 (t, p, P, m - 1, lk, NULL);
mpz_mul (r, r, t);
mpz_clear (lt);
}
}
/* Computes (n+1)(n+2)...(n+k)/2^(k/2 +k/4) using the helper function
rek_raising_fac4, and exploiting an idea inspired by a piece of
code that Fredrik Johansson wrote and by a comment by Niels Möller.
Assume k = 4i then compute:
p = (n+1)(n+4i)/2 - i
(n+1+1)(n+4i)/2 = p + i + (n+4i)/2
(n+1+1)(n+4i-1)/2 = p + i + ((n+4i)-(n+1+1))/2 = p + i + (n-n+4i-2)/2 = p + 3i-1
P = (p + i)*(p+3i-1)/2 = (n+1)(n+2)(n+4i-1)(n+4i)/8
n' = n + 2
i' = i - 1
(n'-1)(n')(n'+4i'+1)(n'+4i'+2)/8 = P
(n'-1)(n'+4i'+2)/2 - i' - 1 = p
(n'-1+2)(n'+4i'+2)/2 - i' - 1 = p + (n'+4i'+2)
(n'-1+2)(n'+4i'+2-2)/2 - i' - 1 = p + (n'+4i'+2) - (n'-1+2) = p + 4i' + 1
(n'-1+2)(n'+4i'+2-2)/2 - i' = p + 4i' + 2
p' = p + 4i' + 2 = (n'+1)(n'+4i')/2 - i'
p' - 4i' - 2 = p
(p' - 4i' - 2 + i)*(p' - 4i' - 2+3i-1)/2 = P
(p' - 4i' - 2 + i' + 1)*(p' - 4i' - 2 + 3i' + 3 - 1)/2 = P
(p' - 3i' - 1)*(p' - i')/2 = P
(p' - 3i' - 1 + 4i' + 1)*(p' - i' + 4i' - 1)/2 = P + (4i' + 1)*(p' - i')/2 + (p' - 3i' - 1 + 4i' + 1)*(4i' - 1)/2
(p' + i')*(p' + 3i' - 1)/2 = P + (4i')*(p' + p')/2 + (p' - i' - (p' + i'))/2
(p' + i')*(p' + 3i' - 1)/2 = P + 4i'p' + (p' - i' - p' - i')/2
(p' + i')*(p' + 3i' - 1)/2 = P + 4i'p' - i'
P' = P + 4i'p' - i'
And compute the product P * P' * P" ...
*/
static void
mpz_raising_fac4 (mpz_ptr r, mpz_ptr n, unsigned long int k, mpz_ptr t, mpz_ptr p)
{
ASSERT ((k >= APARTAJ_KALKULOJ) && (APARTAJ_KALKULOJ > 0));
posmpz_init (n);
posmpz_inc_ui (n, 1);
SIZ (r) = 0;
if (k & 1)
{
mpz_set (r, n);
posmpz_inc_ui (n, 1);
}
k >>= 1;
if (APARTAJ_KALKULOJ < 2 && k == 0)
return;
mpz_hmul_nbnpk (p, n, k, t);
posmpz_init (p);
if (k & 1)
{
if (SIZ (r))
mpz_mul (r, r, p);
else
mpz_set (r, p);
posmpz_inc_ui (p, k - 1);
}
k >>= 1;
if (APARTAJ_KALKULOJ < 4 && k == 0)
return;
mpz_hmul_nbnpk (t, p, k, n);
if (SIZ (r))
mpz_mul (r, r, t);
else
mpz_set (r, t);
if (APARTAJ_KALKULOJ > 8 || k > 1)
{
posmpz_dec_ui (p, k);
rek_raising_fac4 (r, p, t, k - 1, 0, n);
}
}
#else /* KVAROPE */
static void
rek_raising_fac (mpz_ptr r, mpz_ptr n, unsigned long int k, unsigned long int lk, mpz_ptr t1, mpz_ptr t2)
{
/* Should the threshold depend on SIZ (n) ? */
if (k - lk < 10)
{
do {
posmpz_inc_ui (n, k);
mpz_mul (r, r, n);
--k;
} while (k > lk);
}
else
{
mpz_t t3;
unsigned long int m;
m = ((k + lk) >> 1) + 1;
rek_raising_fac (r, n, k, m, t1, t2);
posmpz_inc_ui (n, m);
if (t1 == NULL)
{
mpz_init_set (t3, n);
t1 = t3;
}
else
{
ALLOC (t3) = 0;
mpz_set (t1, n);
}
rek_raising_fac (t1, n, m - 1, lk, t2, NULL);
mpz_mul (r, r, t1);
mpz_clear (t3);
}
}
/* Computes (n+1)(n+2)...(n+k)/2^(k/2) using the helper function
rek_raising_fac, and exploiting an idea inspired by a piece of
code that Fredrik Johansson wrote.
Force an even k = 2i then compute:
p = (n+1)(n+2i)/2
i' = i - 1
p == (n+1)(n+2i'+2)/2
p' = p + i' == (n+2)(n+2i'+1)/2
n' = n + 1
p'== (n'+1)(n'+2i')/2 == (n+1 +1)(n+2i -1)/2
And compute the product p * p' * p" ...
*/
static void
mpz_raising_fac (mpz_ptr r, mpz_ptr n, unsigned long int k, mpz_ptr t, mpz_ptr p)
{
unsigned long int hk;
ASSERT ((k >= APARTAJ_KALKULOJ) && (APARTAJ_KALKULOJ > 1));
mpz_add_ui (n, n, 1);
hk = k >> 1;
mpz_hmul_nbnpk (p, n, hk, t);
if ((k & 1) != 0)
{
mpz_add_ui (t, t, hk + 1);
mpz_mul (r, t, p);
}
else
{
mpz_set (r, p);
}
if ((APARTAJ_KALKULOJ > 3) || (hk > 1))
{
posmpz_init (p);
rek_raising_fac (r, p, hk - 1, 0, t, n);
}
}
#endif /* KVAROPE */
/* This is a poor implementation. Look at bin_uiui.c for improvement ideas.
In fact consider calling mpz_bin_uiui() when the arguments fit, leaving
the code here only for big n.
The identity bin(n,k) = (-1)^k * bin(-n+k-1,k) can be found in Knuth vol
1 section 1.2.6 part G. */
void
mpz_bin_ui (mpz_ptr r, mpz_srcptr n, unsigned long int k)
{
mpz_t ni;
mp_size_t negate;
if (SIZ (n) < 0)
{
/* bin(n,k) = (-1)^k * bin(-n+k-1,k), and set ni = -n+k-1 - k = -n-1 */
mpz_init (ni);
mpz_add_ui (ni, n, 1L);
mpz_neg (ni, ni);
negate = (k & 1); /* (-1)^k */
}
else
{
/* bin(n,k) == 0 if k>n
(no test for this under the n<0 case, since -n+k-1 >= k there) */
if (mpz_cmp_ui (n, k) < 0)
{
SIZ (r) = 0;
return;
}
/* set ni = n-k */
mpz_init (ni);
mpz_sub_ui (ni, n, k);
negate = 0;
}
/* Now wanting bin(ni+k,k), with ni positive, and "negate" is the sign (0
for positive, 1 for negative). */
/* Rewrite bin(n,k) as bin(n,n-k) if that is smaller. In this case it's
whether ni+k-k < k meaning ni<k, and if so change to denominator ni+k-k
= ni, and new ni of ni+k-ni = k. */
if (mpz_cmp_ui (ni, k) < 0)
{
unsigned long tmp;
tmp = k;
k = mpz_get_ui (ni);
mpz_set_ui (ni, tmp);
}
if (k < APARTAJ_KALKULOJ)
{
if (k == 0)
{
SIZ (r) = 1;
MPZ_NEWALLOC (r, 1)[0] = 1;
}
#if APARTAJ_KALKULOJ > 2
else if (k > 1)
{
mpz_add_ui (ni, ni, 1 + (APARTAJ_KALKULOJ > 2 && k > 2));
mpz_mul (r, ni, ni); /* r = (n + (k>2))^2 */
if (APARTAJ_KALKULOJ == 2 || k == 2)
{
mpz_add (r, r, ni); /* n^2+n= n(n+1) */
posmpz_rsh1 (r);
}
#if APARTAJ_KALKULOJ > 3
#if APARTAJ_KALKULOJ != 5
#error Not implemented! 3 < APARTAJ_KALKULOJ != 5
#endif
else /* k > 2 */
{ /* k = 3, 4 */
mpz_sub_ui (r, r, 1); /* (n+1)^2-1 */
if (k == 3)
{
mpz_mul (r, r, ni); /* ((n+1)^2-1)(n+1) = n(n+1)(n+2) */
/* mpz_divexact_ui (r, r, 6); /\* 6=3<<1; div_by3 ? *\/ */
}
else /* k = 4 */
{
mpz_add (ni, ni, r); /* (n+1)^2+n */
mpz_mul (r, ni, ni); /* ((n+1)^2+n)^2 */
/* We should subtract one: ((n+1)^2+n)^2-1 = n(n+1)(n+2)(n+3). */
/* PTR (r) [0] ^= 1; would suffice, but it is not even needed, */
/* because the next division will shift away this bit anyway. */
/* mpz_divexact_ui (r, r, 24); /\* 24=3<<3; div_by3 ? *\/ */
}
mpn_pi1_bdiv_q_1 (PTR(r), PTR(r), SIZ(r), 3, GMP_NUMB_MASK/3*2+1, 1 | (k>>1));
SIZ(r) -= PTR(r) [SIZ(r) - 1] == 0;
}
#endif
}
#endif
else
{ /* k = 1 */
mpz_add_ui (r, ni, 1);
}
}
#if UZU_BIN_UIUI
else if (mpz_cmp_ui (ni, ULONG_MAX - k) <= 0)
{
mpz_bin_uiui (r, mpz_get_ui (ni) + k, k);
}
#endif
else
{
mp_limb_t count;
mpz_t num, den;
mpz_init (num);
mpz_init (den);
#if KVAROPE
mpz_raising_fac4 (num, ni, k, den, r);
popc_limb (count, k);
ASSERT (k - (k >> 1) - (k >> 2) - count >= 0);
mpz_tdiv_q_2exp (num, num, k - (k >> 1) - (k >> 2) - count);
#else
mpz_raising_fac (num, ni, k, den, r);
popc_limb (count, k);
ASSERT (k - (k >> 1) - count >= 0);
mpz_tdiv_q_2exp (num, num, k - (k >> 1) - count);
#endif
mpz_oddfac_1(den, k, 0);
mpz_divexact(r, num, den);
mpz_clear (num);
mpz_clear (den);
}
mpz_clear (ni);
SIZ(r) = (SIZ(r) ^ -negate) + negate;
}

View File

@@ -0,0 +1,707 @@
/* mpz_bin_uiui - compute n over k.
Contributed to the GNU project by Torbjorn Granlund and Marco Bodrato.
Copyright 2010-2012, 2015-2018, 2020 Free Software Foundation, Inc.
This file is part of the GNU MP Library.
The GNU MP Library is free software; you can redistribute it and/or modify
it under the terms of either:
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
or
* the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any
later version.
or both in parallel, as here.
The GNU MP Library 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 copies of the GNU General Public License and the
GNU Lesser General Public License along with the GNU MP Library. If not,
see https://www.gnu.org/licenses/. */
#include "gmp-impl.h"
#include "longlong.h"
#ifndef BIN_GOETGHELUCK_THRESHOLD
#define BIN_GOETGHELUCK_THRESHOLD 512
#endif
#ifndef BIN_UIUI_ENABLE_SMALLDC
#define BIN_UIUI_ENABLE_SMALLDC 1
#endif
#ifndef BIN_UIUI_RECURSIVE_SMALLDC
#define BIN_UIUI_RECURSIVE_SMALLDC (GMP_NUMB_BITS > 32)
#endif
/* Algorithm:
Accumulate chunks of factors first limb-by-limb (using one of mul0-mul8)
which are then accumulated into mpn numbers. The first inner loop
accumulates divisor factors, the 2nd inner loop accumulates exactly the same
number of dividend factors. We avoid accumulating more for the divisor,
even with its smaller factors, since we else cannot guarantee divisibility.
Since we know each division will yield an integer, we compute the quotient
using Hensel norm: If the quotient is limited by 2^t, we compute A / B mod
2^t.
Improvements:
(1) An obvious improvement to this code would be to compute mod 2^t
everywhere. Unfortunately, we cannot determine t beforehand, unless we
invoke some approximation, such as Stirling's formula. Of course, we don't
need t to be tight. However, it is not clear that this would help much,
our numbers are kept reasonably small already.
(2) Compute nmax/kmax semi-accurately, without scalar division or a loop.
Extracting the 3 msb, then doing a table lookup using cnt*8+msb as index,
would make it both reasonably accurate and fast. (We could use a table
stored into a limb, perhaps.) The table should take the removed factors of
2 into account (those done on-the-fly in mulN).
(3) The first time in the loop we compute the odd part of a
factorial in kp, we might use oddfac_1 for this task.
*/
/* This threshold determines how large divisor to accumulate before we call
bdiv. Perhaps we should never call bdiv, and accumulate all we are told,
since we are just basecase code anyway? Presumably, this depends on the
relative speed of the asymptotically fast code and this code. */
#define SOME_THRESHOLD 20
/* Multiply-into-limb functions. These remove factors of 2 on-the-fly. FIXME:
All versions of MAXFACS don't take this 2 removal into account now, meaning
that then, shifting just adds some overhead. (We remove factors from the
completed limb anyway.) */
static mp_limb_t
mul1 (mp_limb_t m)
{
return m;
}
static mp_limb_t
mul2 (mp_limb_t m)
{
/* We need to shift before multiplying, to avoid an overflow. */
mp_limb_t m01 = (m | 1) * ((m + 1) >> 1);
return m01;
}
static mp_limb_t
mul3 (mp_limb_t m)
{
mp_limb_t m01 = (m + 0) * (m + 1) >> 1;
mp_limb_t m2 = (m + 2);
return m01 * m2;
}
static mp_limb_t
mul4 (mp_limb_t m)
{
mp_limb_t m03 = (m + 0) * (m + 3) >> 1;
return m03 * (m03 + 1); /* mul2 (m03) ? */
}
static mp_limb_t
mul5 (mp_limb_t m)
{
mp_limb_t m03 = (m + 0) * (m + 3) >> 1;
mp_limb_t m034 = m03 * (m + 4);
return (m03 + 1) * m034;
}
static mp_limb_t
mul6 (mp_limb_t m)
{
mp_limb_t m05 = (m + 0) * (m + 5);
mp_limb_t m1234 = (m05 + 5) * (m05 + 5) >> 3;
return m1234 * (m05 >> 1);
}
static mp_limb_t
mul7 (mp_limb_t m)
{
mp_limb_t m05 = (m + 0) * (m + 5);
mp_limb_t m1234 = (m05 + 5) * (m05 + 5) >> 3;
mp_limb_t m056 = m05 * (m + 6) >> 1;
return m1234 * m056;
}
static mp_limb_t
mul8 (mp_limb_t m)
{
mp_limb_t m07 = (m + 0) * (m + 7);
mp_limb_t m0257 = m07 * (m07 + 10) >> 3;
mp_limb_t m1346 = m07 + 9 + m0257;
return m0257 * m1346;
}
/*
static mp_limb_t
mul9 (mp_limb_t m)
{
return (m + 8) * mul8 (m) ;
}
static mp_limb_t
mul10 (mp_limb_t m)
{
mp_limb_t m09 = (m + 0) * (m + 9);
mp_limb_t m18 = (m09 >> 1) + 4;
mp_limb_t m0369 = m09 * (m09 + 18) >> 3;
mp_limb_t m2457 = m09 * 2 + 35 + m0369;
return ((m0369 * m2457) >> 1) * m18;
}
*/
typedef mp_limb_t (* mulfunc_t) (mp_limb_t);
static const mulfunc_t mulfunc[] = {mul1,mul2,mul3,mul4,mul5,mul6,mul7,mul8 /* ,mul9,mul10 */};
#define M (numberof(mulfunc))
/* Number of factors-of-2 removed by the corresponding mulN function. */
static const unsigned char tcnttab[] = {0, 1, 1, 2, 2, 4, 4, 6 /*,6,8*/};
#if 1
/* This variant is inaccurate but share the code with other functions. */
#define MAXFACS(max,l) \
do { \
(max) = log_n_max (l); \
} while (0)
#else
/* This variant is exact(?) but uses a loop. It takes the 2 removal
of mulN into account. */
static const unsigned long ftab[] =
#if GMP_NUMB_BITS == 64
/* 1 to 8 factors per iteration */
{CNST_LIMB(0xffffffffffffffff),CNST_LIMB(0x16a09e667),0x32cbfc,0x16a08,0x24c0,0xa11,0x345,0x1ab /*,0xe9,0x8e */};
#endif
#if GMP_NUMB_BITS == 32
/* 1 to 7 factors per iteration */
{0xffffffff,0x16a09,0x7ff,0x168,0x6f,0x3d,0x20 /* ,0x17 */};
#endif
#define MAXFACS(max,l) \
do { \
int __i; \
for (__i = numberof (ftab) - 1; l > ftab[__i]; __i--) \
; \
(max) = __i + 1; \
} while (0)
#endif
/* Entry i contains (i!/2^t)^(-1) where t is chosen such that the parenthesis
is an odd integer. */
static const mp_limb_t facinv[] = { ONE_LIMB_ODD_FACTORIAL_INVERSES_TABLE };
static void
mpz_bdiv_bin_uiui (mpz_ptr r, unsigned long int n, unsigned long int k)
{
unsigned nmax, kmax, nmaxnow, numfac;
mp_ptr np, kp;
mp_size_t nn, kn, alloc;
mp_limb_t i, j, t, iii, jjj, cy, dinv;
int cnt;
mp_size_t maxn;
TMP_DECL;
ASSERT (k > ODD_FACTORIAL_TABLE_LIMIT);
TMP_MARK;
maxn = 1 + n / GMP_NUMB_BITS; /* absolutely largest result size (limbs) */
/* FIXME: This allocation might be insufficient, but is usually way too
large. */
alloc = SOME_THRESHOLD - 1 + MAX (3 * maxn / 2, SOME_THRESHOLD);
alloc = MIN (alloc, (mp_size_t) k) + 1;
TMP_ALLOC_LIMBS_2 (np, alloc, kp, SOME_THRESHOLD + 1);
MAXFACS (nmax, n);
ASSERT (nmax <= M);
MAXFACS (kmax, k);
ASSERT (kmax <= M);
ASSERT (k >= M);
i = n - k + 1;
np[0] = 1; nn = 1;
numfac = 1;
j = ODD_FACTORIAL_TABLE_LIMIT + 1;
jjj = ODD_FACTORIAL_TABLE_MAX;
ASSERT (__gmp_oddfac_table[ODD_FACTORIAL_TABLE_LIMIT] == ODD_FACTORIAL_TABLE_MAX);
while (1)
{
kp[0] = jjj; /* store new factors */
kn = 1;
t = k - j + 1;
kmax = MIN (kmax, t);
while (kmax != 0 && kn < SOME_THRESHOLD)
{
jjj = mulfunc[kmax - 1] (j);
j += kmax; /* number of factors used */
count_trailing_zeros (cnt, jjj); /* count low zeros */
jjj >>= cnt; /* remove remaining low zeros */
cy = mpn_mul_1 (kp, kp, kn, jjj); /* accumulate new factors */
kp[kn] = cy;
kn += cy != 0;
t = k - j + 1;
kmax = MIN (kmax, t);
}
numfac = j - numfac;
while (numfac != 0)
{
nmaxnow = MIN (nmax, numfac);
iii = mulfunc[nmaxnow - 1] (i);
i += nmaxnow; /* number of factors used */
count_trailing_zeros (cnt, iii); /* count low zeros */
iii >>= cnt; /* remove remaining low zeros */
cy = mpn_mul_1 (np, np, nn, iii); /* accumulate new factors */
np[nn] = cy;
nn += cy != 0;
numfac -= nmaxnow;
}
ASSERT (nn < alloc);
binvert_limb (dinv, kp[0]);
nn += (np[nn - 1] >= kp[kn - 1]);
nn -= kn;
mpn_sbpi1_bdiv_q (np, np, nn, kp, MIN(kn,nn), -dinv);
mpn_neg (np, np, nn);
if (kmax == 0)
break;
numfac = j;
jjj = mulfunc[kmax - 1] (j);
j += kmax; /* number of factors used */
count_trailing_zeros (cnt, jjj); /* count low zeros */
jjj >>= cnt; /* remove remaining low zeros */
}
/* Put back the right number of factors of 2. */
popc_limb (cnt, n - k);
popc_limb (j, k);
cnt += j;
popc_limb (j, n);
cnt -= j;
if (cnt != 0)
{
ASSERT (cnt < GMP_NUMB_BITS); /* can happen, but not for intended use */
cy = mpn_lshift (np, np, nn, cnt);
np[nn] = cy;
nn += cy != 0;
}
nn -= np[nn - 1] == 0; /* normalisation */
kp = MPZ_NEWALLOC (r, nn);
SIZ(r) = nn;
MPN_COPY (kp, np, nn);
TMP_FREE;
}
static void
mpz_smallk_bin_uiui (mpz_ptr r, unsigned long int n, unsigned long int k)
{
unsigned nmax, numfac;
mp_ptr rp;
mp_size_t rn, alloc;
mp_limb_t i, iii, cy;
unsigned i2cnt, cnt;
MAXFACS (nmax, n);
nmax = MIN (nmax, M);
i = n - k + 1;
i2cnt = __gmp_fac2cnt_table[k / 2 - 1]; /* low zeros count */
if (nmax >= k)
{
MPZ_NEWALLOC (r, 1) [0] = mulfunc[k - 1] (i) * facinv[k - 2] >>
(i2cnt - tcnttab[k - 1]);
SIZ(r) = 1;
return;
}
count_leading_zeros (cnt, (mp_limb_t) n);
cnt = GMP_LIMB_BITS - cnt;
alloc = cnt * k / GMP_NUMB_BITS + 3; /* FIXME: ensure rounding is enough. */
rp = MPZ_NEWALLOC (r, alloc);
rp[0] = mulfunc[nmax - 1] (i);
rn = 1;
i += nmax; /* number of factors used */
i2cnt -= tcnttab[nmax - 1]; /* low zeros count */
numfac = k - nmax;
do
{
nmax = MIN (nmax, numfac);
iii = mulfunc[nmax - 1] (i);
i += nmax; /* number of factors used */
i2cnt -= tcnttab[nmax - 1]; /* update low zeros count */
cy = mpn_mul_1 (rp, rp, rn, iii); /* accumulate new factors */
rp[rn] = cy;
rn += cy != 0;
numfac -= nmax;
} while (numfac != 0);
ASSERT (rn < alloc);
mpn_pi1_bdiv_q_1 (rp, rp, rn, __gmp_oddfac_table[k], facinv[k - 2], i2cnt);
/* A two-fold, branch-free normalisation is possible :*/
/* rn -= rp[rn - 1] == 0; */
/* rn -= rp[rn - 1] == 0; */
MPN_NORMALIZE_NOT_ZERO (rp, rn);
SIZ(r) = rn;
}
/* Algorithm:
Plain and simply multiply things together.
We tabulate factorials (k!/2^t)^(-1) mod B (where t is chosen such
that k!/2^t is odd).
*/
static mp_limb_t
bc_bin_uiui (unsigned int n, unsigned int k)
{
return ((__gmp_oddfac_table[n] * facinv[k - 2] * facinv[n - k - 2])
<< (__gmp_fac2cnt_table[n / 2 - 1] - __gmp_fac2cnt_table[k / 2 - 1] - __gmp_fac2cnt_table[(n-k) / 2 - 1]))
& GMP_NUMB_MASK;
}
/* Algorithm:
Recursively exploit the relation
bin(n,k) = bin(n,k>>1)*bin(n-k>>1,k-k>>1)/bin(k,k>>1) .
Values for binomial(k,k>>1) that fit in a limb are precomputed
(with inverses).
*/
/* bin2kk[i - ODD_CENTRAL_BINOMIAL_OFFSET] =
binomial(i*2,i)/2^t (where t is chosen so that it is odd). */
static const mp_limb_t bin2kk[] = { ONE_LIMB_ODD_CENTRAL_BINOMIAL_TABLE };
/* bin2kkinv[i] = bin2kk[i]^-1 mod B */
static const mp_limb_t bin2kkinv[] = { ONE_LIMB_ODD_CENTRAL_BINOMIAL_INVERSE_TABLE };
/* bin2kk[i] = binomial((i+MIN_S)*2,i+MIN_S)/2^t. This table contains the t values. */
static const unsigned char fac2bin[] = { CENTRAL_BINOMIAL_2FAC_TABLE };
static void
mpz_smallkdc_bin_uiui (mpz_ptr r, unsigned long int n, unsigned long int k)
{
mp_ptr rp;
mp_size_t rn;
unsigned long int hk;
hk = k >> 1;
if ((! BIN_UIUI_RECURSIVE_SMALLDC) || hk <= ODD_FACTORIAL_TABLE_LIMIT)
mpz_smallk_bin_uiui (r, n, hk);
else
mpz_smallkdc_bin_uiui (r, n, hk);
k -= hk;
n -= hk;
if (n <= ODD_FACTORIAL_EXTTABLE_LIMIT) {
mp_limb_t cy;
rn = SIZ (r);
rp = MPZ_REALLOC (r, rn + 1);
cy = mpn_mul_1 (rp, rp, rn, bc_bin_uiui (n, k));
rp [rn] = cy;
rn += cy != 0;
} else {
mp_limb_t buffer[ODD_CENTRAL_BINOMIAL_TABLE_LIMIT + 3];
mpz_t t;
ALLOC (t) = ODD_CENTRAL_BINOMIAL_TABLE_LIMIT + 3;
PTR (t) = buffer;
if ((! BIN_UIUI_RECURSIVE_SMALLDC) || k <= ODD_FACTORIAL_TABLE_LIMIT)
mpz_smallk_bin_uiui (t, n, k);
else
mpz_smallkdc_bin_uiui (t, n, k);
mpz_mul (r, r, t);
rp = PTR (r);
rn = SIZ (r);
}
mpn_pi1_bdiv_q_1 (rp, rp, rn, bin2kk[k - ODD_CENTRAL_BINOMIAL_OFFSET],
bin2kkinv[k - ODD_CENTRAL_BINOMIAL_OFFSET],
fac2bin[k - ODD_CENTRAL_BINOMIAL_OFFSET] - (k != hk));
/* A two-fold, branch-free normalisation is possible :*/
/* rn -= rp[rn - 1] == 0; */
/* rn -= rp[rn - 1] == 0; */
MPN_NORMALIZE_NOT_ZERO (rp, rn);
SIZ(r) = rn;
}
/* mpz_goetgheluck_bin_uiui(RESULT, N, K) -- Set RESULT to binomial(N,K).
*
* Contributed to the GNU project by Marco Bodrato.
*
* Implementation of the algorithm by P. Goetgheluck, "Computing
* Binomial Coefficients", The American Mathematical Monthly, Vol. 94,
* No. 4 (April 1987), pp. 360-365.
*
* Acknowledgment: Peter Luschny did spot the slowness of the previous
* code and suggested the reference.
*/
/* TODO: Remove duplicated constants / macros / static functions...
*/
/*************************************************************/
/* Section macros: common macros, for swing/fac/bin (&sieve) */
/*************************************************************/
#define FACTOR_LIST_APPEND(PR, MAX_PR, VEC, I) \
if ((PR) > (MAX_PR)) { \
(VEC)[(I)++] = (PR); \
(PR) = 1; \
}
#define FACTOR_LIST_STORE(P, PR, MAX_PR, VEC, I) \
do { \
if ((PR) > (MAX_PR)) { \
(VEC)[(I)++] = (PR); \
(PR) = (P); \
} else \
(PR) *= (P); \
} while (0)
#define LOOP_ON_SIEVE_CONTINUE(prime,end) \
__max_i = (end); \
\
do { \
++__i; \
if ((*__sieve & __mask) == 0) \
{ \
mp_limb_t prime; \
prime = id_to_n(__i)
#define LOOP_ON_SIEVE_BEGIN(prime,start,end,off,sieve) \
do { \
mp_limb_t __mask, *__sieve, __max_i, __i; \
\
__i = (start)-(off); \
__sieve = (sieve) + __i / GMP_LIMB_BITS; \
__mask = CNST_LIMB(1) << (__i % GMP_LIMB_BITS); \
__i += (off); \
\
LOOP_ON_SIEVE_CONTINUE(prime,end)
#define LOOP_ON_SIEVE_STOP \
} \
__mask = __mask << 1 | __mask >> (GMP_LIMB_BITS-1); \
__sieve += __mask & 1; \
} while (__i <= __max_i)
#define LOOP_ON_SIEVE_END \
LOOP_ON_SIEVE_STOP; \
} while (0)
/*********************************************************/
/* Section sieve: sieving functions and tools for primes */
/*********************************************************/
#if WANT_ASSERT
static mp_limb_t
bit_to_n (mp_limb_t bit) { return (bit*3+4)|1; }
#endif
/* id_to_n (x) = bit_to_n (x-1) = (id*3+1)|1*/
static mp_limb_t
id_to_n (mp_limb_t id) { return id*3+1+(id&1); }
/* n_to_bit (n) = ((n-1)&(-CNST_LIMB(2)))/3U-1 */
static mp_limb_t
n_to_bit (mp_limb_t n) { return ((n-5)|1)/3U; }
static mp_size_t
primesieve_size (mp_limb_t n) { return n_to_bit(n) / GMP_LIMB_BITS + 1; }
/*********************************************************/
/* Section binomial: fast binomial implementation */
/*********************************************************/
#define COUNT_A_PRIME(P, N, K, PR, MAX_PR, VEC, I) \
do { \
mp_limb_t __a, __b, __prime, __ma,__mb; \
__prime = (P); \
__a = (N); __b = (K); __mb = 0; \
FACTOR_LIST_APPEND(PR, MAX_PR, VEC, I); \
do { \
__mb += __b % __prime; __b /= __prime; \
__ma = __a % __prime; __a /= __prime; \
if (__ma < __mb) { \
__mb = 1; (PR) *= __prime; \
} else __mb = 0; \
} while (__a >= __prime); \
} while (0)
#define SH_COUNT_A_PRIME(P, N, K, PR, MAX_PR, VEC, I) \
do { \
mp_limb_t __prime; \
__prime = (P); \
if (((N) % __prime) < ((K) % __prime)) { \
FACTOR_LIST_STORE (__prime, PR, MAX_PR, VEC, I); \
} \
} while (0)
/* Returns an approximation of the sqare root of x.
* It gives:
* limb_apprsqrt (x) ^ 2 <= x < (limb_apprsqrt (x)+1) ^ 2
* or
* x <= limb_apprsqrt (x) ^ 2 <= x * 9/8
*/
static mp_limb_t
limb_apprsqrt (mp_limb_t x)
{
int s;
ASSERT (x > 2);
count_leading_zeros (s, x);
s = (GMP_LIMB_BITS - s) >> 1;
return ((CNST_LIMB(1) << (s - 1)) + (x >> 1 >> s));
}
static void
mpz_goetgheluck_bin_uiui (mpz_ptr r, unsigned long int n, unsigned long int k)
{
mp_limb_t *sieve, *factors, count;
mp_limb_t prod, max_prod;
mp_size_t j;
TMP_DECL;
ASSERT (BIN_GOETGHELUCK_THRESHOLD >= 13);
ASSERT (n >= 25);
TMP_MARK;
sieve = TMP_ALLOC_LIMBS (primesieve_size (n));
count = gmp_primesieve (sieve, n) + 1;
factors = TMP_ALLOC_LIMBS (count / log_n_max (n) + 1);
max_prod = GMP_NUMB_MAX / n;
/* Handle primes = 2, 3 separately. */
popc_limb (count, n - k);
popc_limb (j, k);
count += j;
popc_limb (j, n);
count -= j;
prod = CNST_LIMB(1) << count;
j = 0;
COUNT_A_PRIME (3, n, k, prod, max_prod, factors, j);
/* Accumulate prime factors from 5 to n/2 */
{
mp_limb_t s;
s = limb_apprsqrt(n);
s = n_to_bit (s);
ASSERT (bit_to_n (s+1) * bit_to_n (s+1) > n);
ASSERT (s <= n_to_bit (n >> 1));
LOOP_ON_SIEVE_BEGIN (prime, n_to_bit (5), s, 0,sieve);
COUNT_A_PRIME (prime, n, k, prod, max_prod, factors, j);
LOOP_ON_SIEVE_STOP;
ASSERT (max_prod <= GMP_NUMB_MAX / 2);
max_prod <<= 1;
LOOP_ON_SIEVE_CONTINUE (prime, n_to_bit (n >> 1));
SH_COUNT_A_PRIME (prime, n, k, prod, max_prod, factors, j);
LOOP_ON_SIEVE_END;
max_prod >>= 1;
}
/* Store primes from (n-k)+1 to n */
ASSERT (n_to_bit (n - k) < n_to_bit (n));
LOOP_ON_SIEVE_BEGIN (prime, n_to_bit (n - k) + 1, n_to_bit (n), 0,sieve);
FACTOR_LIST_STORE (prime, prod, max_prod, factors, j);
LOOP_ON_SIEVE_END;
if (LIKELY (j != 0))
{
factors[j++] = prod;
mpz_prodlimbs (r, factors, j);
}
else
{
MPZ_NEWALLOC (r, 1)[0] = prod;
SIZ (r) = 1;
}
TMP_FREE;
}
#undef COUNT_A_PRIME
#undef SH_COUNT_A_PRIME
#undef LOOP_ON_SIEVE_END
#undef LOOP_ON_SIEVE_STOP
#undef LOOP_ON_SIEVE_BEGIN
#undef LOOP_ON_SIEVE_CONTINUE
/*********************************************************/
/* End of implementation of Goetgheluck's algorithm */
/*********************************************************/
void
mpz_bin_uiui (mpz_ptr r, unsigned long int n, unsigned long int k)
{
if (UNLIKELY (n < k)) {
SIZ (r) = 0;
#if BITS_PER_ULONG > GMP_NUMB_BITS
} else if (UNLIKELY (n > GMP_NUMB_MAX)) {
mpz_t tmp;
mpz_init_set_ui (tmp, n);
mpz_bin_ui (r, tmp, k);
mpz_clear (tmp);
#endif
} else {
ASSERT (n <= GMP_NUMB_MAX);
/* Rewrite bin(n,k) as bin(n,n-k) if that is smaller. */
k = MIN (k, n - k);
if (k < 2) {
MPZ_NEWALLOC (r, 1)[0] = k ? n : 1; /* 1 + ((-k) & (n-1)); */
SIZ(r) = 1;
} else if (n <= ODD_FACTORIAL_EXTTABLE_LIMIT) { /* k >= 2, n >= 4 */
MPZ_NEWALLOC (r, 1)[0] = bc_bin_uiui (n, k);
SIZ(r) = 1;
} else if (k <= ODD_FACTORIAL_TABLE_LIMIT)
mpz_smallk_bin_uiui (r, n, k);
else if (BIN_UIUI_ENABLE_SMALLDC &&
k <= (BIN_UIUI_RECURSIVE_SMALLDC ? ODD_CENTRAL_BINOMIAL_TABLE_LIMIT : ODD_FACTORIAL_TABLE_LIMIT)* 2)
mpz_smallkdc_bin_uiui (r, n, k);
else if (ABOVE_THRESHOLD (k, BIN_GOETGHELUCK_THRESHOLD) &&
k > (n >> 4)) /* k > ODD_FACTORIAL_TABLE_LIMIT */
mpz_goetgheluck_bin_uiui (r, n, k);
else
mpz_bdiv_bin_uiui (r, n, k);
}
}

View File

@@ -0,0 +1,52 @@
/* mpz_cdiv_q -- Division rounding the quotient towards +infinity. The
remainder gets the opposite sign as the denominator.
Copyright 1994-1996, 2000, 2001, 2005, 2012 Free Software Foundation, Inc.
This file is part of the GNU MP Library.
The GNU MP Library is free software; you can redistribute it and/or modify
it under the terms of either:
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
or
* the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any
later version.
or both in parallel, as here.
The GNU MP Library 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 copies of the GNU General Public License and the
GNU Lesser General Public License along with the GNU MP Library. If not,
see https://www.gnu.org/licenses/. */
#include "gmp-impl.h"
void
mpz_cdiv_q (mpz_ptr quot, mpz_srcptr dividend, mpz_srcptr divisor)
{
mp_size_t dividend_size = SIZ (dividend);
mp_size_t divisor_size = SIZ (divisor);
mpz_t rem;
TMP_DECL;
TMP_MARK;
MPZ_TMP_INIT (rem, ABS (divisor_size));
mpz_tdiv_qr (quot, rem, dividend, divisor);
if ((divisor_size ^ dividend_size) >= 0 && SIZ (rem) != 0)
mpz_add_ui (quot, quot, 1L);
TMP_FREE;
}

View File

@@ -0,0 +1,102 @@
/* mpz_cdiv_q_ui -- Division rounding the quotient towards +infinity. The
remainder gets the opposite sign as the denominator. In order to make it
always fit into the return type, the negative of the true remainder is
returned.
Copyright 1994, 1996, 1999, 2001, 2002, 2004, 2012 Free Software Foundation,
Inc.
This file is part of the GNU MP Library.
The GNU MP Library is free software; you can redistribute it and/or modify
it under the terms of either:
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
or
* the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any
later version.
or both in parallel, as here.
The GNU MP Library 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 copies of the GNU General Public License and the
GNU Lesser General Public License along with the GNU MP Library. If not,
see https://www.gnu.org/licenses/. */
#include "gmp-impl.h"
unsigned long int
mpz_cdiv_q_ui (mpz_ptr quot, mpz_srcptr dividend, unsigned long int divisor)
{
mp_size_t ns, nn, qn;
mp_ptr np, qp;
mp_limb_t rl;
if (UNLIKELY (divisor == 0))
DIVIDE_BY_ZERO;
ns = SIZ(dividend);
if (ns == 0)
{
SIZ(quot) = 0;
return 0;
}
nn = ABS(ns);
qp = MPZ_REALLOC (quot, nn);
np = PTR(dividend);
#if BITS_PER_ULONG > GMP_NUMB_BITS /* avoid warnings about shift amount */
if (divisor > GMP_NUMB_MAX)
{
mp_limb_t dp[2], rp[2];
if (nn == 1) /* tdiv_qr requirements; tested above for 0 */
{
qp[0] = 0;
rl = np[0];
qn = 1; /* a white lie, fixed below */
}
else
{
dp[0] = divisor & GMP_NUMB_MASK;
dp[1] = divisor >> GMP_NUMB_BITS;
mpn_tdiv_qr (qp, rp, (mp_size_t) 0, np, nn, dp, (mp_size_t) 2);
rl = rp[0] + (rp[1] << GMP_NUMB_BITS);
qn = nn - 2 + 1;
}
if (rl != 0 && ns >= 0)
{
mpn_incr_u (qp, (mp_limb_t) 1);
rl = divisor - rl;
}
qn -= qp[qn - 1] == 0; qn -= qn != 0 && qp[qn - 1] == 0;
}
else
#endif
{
rl = mpn_divrem_1 (qp, (mp_size_t) 0, np, nn, (mp_limb_t) divisor);
if (rl != 0 && ns >= 0)
{
mpn_incr_u (qp, (mp_limb_t) 1);
rl = divisor - rl;
}
qn = nn - (qp[nn - 1] == 0);
}
SIZ(quot) = ns >= 0 ? qn : -qn;
return rl;
}

View File

@@ -0,0 +1,64 @@
/* mpz_cdiv_qr -- Division rounding the quotient towards +infinity. The
remainder gets the opposite sign as the denominator.
Copyright 1994-1996, 2000, 2001, 2005, 2012 Free Software Foundation, Inc.
This file is part of the GNU MP Library.
The GNU MP Library is free software; you can redistribute it and/or modify
it under the terms of either:
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
or
* the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any
later version.
or both in parallel, as here.
The GNU MP Library 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 copies of the GNU General Public License and the
GNU Lesser General Public License along with the GNU MP Library. If not,
see https://www.gnu.org/licenses/. */
#include "gmp-impl.h"
void
mpz_cdiv_qr (mpz_ptr quot, mpz_ptr rem, mpz_srcptr dividend, mpz_srcptr divisor)
{
mp_size_t divisor_size = SIZ (divisor);
mp_size_t xsize;
mpz_t temp_divisor; /* N.B.: lives until function returns! */
TMP_DECL;
TMP_MARK;
/* We need the original value of the divisor after the quotient and
remainder have been preliminary calculated. We have to copy it to
temporary space if it's the same variable as either QUOT or REM. */
if (quot == divisor || rem == divisor)
{
MPZ_TMP_INIT (temp_divisor, ABS (divisor_size));
mpz_set (temp_divisor, divisor);
divisor = temp_divisor;
}
xsize = SIZ (dividend) ^ divisor_size;;
mpz_tdiv_qr (quot, rem, dividend, divisor);
if (xsize >= 0 && SIZ (rem) != 0)
{
mpz_add_ui (quot, quot, 1L);
mpz_sub (rem, rem, divisor);
}
TMP_FREE;
}

View File

@@ -0,0 +1,118 @@
/* mpz_cdiv_qr_ui -- Division rounding the quotient towards +infinity. The
remainder gets the opposite sign as the denominator. In order to make it
always fit into the return type, the negative of the true remainder is
returned.
Copyright 1994-1996, 1999, 2001, 2002, 2004, 2012, 2015 Free Software
Foundation, Inc.
This file is part of the GNU MP Library.
The GNU MP Library is free software; you can redistribute it and/or modify
it under the terms of either:
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
or
* the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any
later version.
or both in parallel, as here.
The GNU MP Library 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 copies of the GNU General Public License and the
GNU Lesser General Public License along with the GNU MP Library. If not,
see https://www.gnu.org/licenses/. */
#include "gmp-impl.h"
unsigned long int
mpz_cdiv_qr_ui (mpz_ptr quot, mpz_ptr rem, mpz_srcptr dividend, unsigned long int divisor)
{
mp_size_t ns, nn, qn;
mp_ptr np, qp;
mp_limb_t rl;
if (UNLIKELY (divisor == 0))
DIVIDE_BY_ZERO;
ns = SIZ(dividend);
if (ns == 0)
{
SIZ(quot) = 0;
SIZ(rem) = 0;
return 0;
}
nn = ABS(ns);
qp = MPZ_REALLOC (quot, nn);
np = PTR(dividend);
#if BITS_PER_ULONG > GMP_NUMB_BITS /* avoid warnings about shift amount */
if (divisor > GMP_NUMB_MAX)
{
mp_limb_t dp[2];
mp_ptr rp;
mp_size_t rn;
rp = MPZ_REALLOC (rem, 2);
if (nn == 1) /* tdiv_qr requirements; tested above for 0 */
{
qp[0] = 0;
qn = 1; /* a white lie, fixed below */
rl = np[0];
rp[0] = rl;
}
else
{
dp[0] = divisor & GMP_NUMB_MASK;
dp[1] = divisor >> GMP_NUMB_BITS;
mpn_tdiv_qr (qp, rp, (mp_size_t) 0, np, nn, dp, (mp_size_t) 2);
rl = rp[0] + (rp[1] << GMP_NUMB_BITS);
qn = nn - 2 + 1;
}
if (rl != 0 && ns >= 0)
{
mpn_incr_u (qp, (mp_limb_t) 1);
rl = divisor - rl;
rp[0] = rl & GMP_NUMB_MASK;
rp[1] = rl >> GMP_NUMB_BITS;
}
qn -= qp[qn - 1] == 0; qn -= qn != 0 && qp[qn - 1] == 0;
rn = 1 + (rl > GMP_NUMB_MAX); rn -= (rp[rn - 1] == 0);
SIZ(rem) = -rn;
}
else
#endif
{
rl = mpn_divrem_1 (qp, (mp_size_t) 0, np, nn, (mp_limb_t) divisor);
if (rl == 0)
SIZ(rem) = 0;
else
{
if (ns >= 0)
{
mpn_incr_u (qp, (mp_limb_t) 1);
rl = divisor - rl;
}
MPZ_NEWALLOC (rem, 1)[0] = rl;
SIZ(rem) = -(rl != 0);
}
qn = nn - (qp[nn - 1] == 0);
}
SIZ(quot) = ns >= 0 ? qn : -qn;
return rl;
}

View File

@@ -0,0 +1,60 @@
/* mpz_cdiv_r -- Division rounding the quotient towards +infinity. The
remainder gets the opposite sign as the denominator.
Copyright 1994-1996, 2001, 2005, 2012 Free Software Foundation, Inc.
This file is part of the GNU MP Library.
The GNU MP Library is free software; you can redistribute it and/or modify
it under the terms of either:
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
or
* the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any
later version.
or both in parallel, as here.
The GNU MP Library 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 copies of the GNU General Public License and the
GNU Lesser General Public License along with the GNU MP Library. If not,
see https://www.gnu.org/licenses/. */
#include "gmp-impl.h"
void
mpz_cdiv_r (mpz_ptr rem, mpz_srcptr dividend, mpz_srcptr divisor)
{
mp_size_t divisor_size = SIZ (divisor);
mpz_t temp_divisor; /* N.B.: lives until function returns! */
TMP_DECL;
TMP_MARK;
/* We need the original value of the divisor after the remainder has been
preliminary calculated. We have to copy it to temporary space if it's
the same variable as REM. */
if (rem == divisor)
{
MPZ_TMP_INIT (temp_divisor, ABS (divisor_size));
mpz_set (temp_divisor, divisor);
divisor = temp_divisor;
}
mpz_tdiv_r (rem, dividend, divisor);
if ((divisor_size ^ SIZ (dividend)) >= 0 && SIZ (rem) != 0)
mpz_sub (rem, rem, divisor);
TMP_FREE;
}

View File

@@ -0,0 +1,109 @@
/* mpz_cdiv_r_ui -- Division rounding the quotient towards +infinity. The
remainder gets the opposite sign as the denominator. In order to make it
always fit into the return type, the negative of the true remainder is
returned.
Copyright 1994-1996, 2001, 2002, 2004, 2005, 2012, 2015 Free Software
Foundation, Inc.
This file is part of the GNU MP Library.
The GNU MP Library is free software; you can redistribute it and/or modify
it under the terms of either:
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
or
* the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any
later version.
or both in parallel, as here.
The GNU MP Library 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 copies of the GNU General Public License and the
GNU Lesser General Public License along with the GNU MP Library. If not,
see https://www.gnu.org/licenses/. */
#include "gmp-impl.h"
unsigned long int
mpz_cdiv_r_ui (mpz_ptr rem, mpz_srcptr dividend, unsigned long int divisor)
{
mp_size_t ns, nn;
mp_ptr np;
mp_limb_t rl;
if (UNLIKELY (divisor == 0))
DIVIDE_BY_ZERO;
ns = SIZ(dividend);
if (ns == 0)
{
SIZ(rem) = 0;
return 0;
}
nn = ABS(ns);
np = PTR(dividend);
#if BITS_PER_ULONG > GMP_NUMB_BITS /* avoid warnings about shift amount */
if (divisor > GMP_NUMB_MAX)
{
mp_limb_t dp[2];
mp_ptr rp, qp;
mp_size_t rn;
TMP_DECL;
rp = MPZ_REALLOC (rem, 2);
if (nn == 1) /* tdiv_qr requirements; tested above for 0 */
{
rl = np[0];
rp[0] = rl;
}
else
{
TMP_MARK;
dp[0] = divisor & GMP_NUMB_MASK;
dp[1] = divisor >> GMP_NUMB_BITS;
qp = TMP_ALLOC_LIMBS (nn - 2 + 1);
mpn_tdiv_qr (qp, rp, (mp_size_t) 0, np, nn, dp, (mp_size_t) 2);
TMP_FREE;
rl = rp[0] + (rp[1] << GMP_NUMB_BITS);
}
if (rl != 0 && ns >= 0)
{
rl = divisor - rl;
rp[0] = rl & GMP_NUMB_MASK;
rp[1] = rl >> GMP_NUMB_BITS;
}
rn = 1 + (rl > GMP_NUMB_MAX); rn -= (rp[rn - 1] == 0);
SIZ(rem) = -rn;
}
else
#endif
{
rl = mpn_mod_1 (np, nn, (mp_limb_t) divisor);
if (rl == 0)
SIZ(rem) = 0;
else
{
if (ns >= 0)
rl = divisor - rl;
MPZ_NEWALLOC (rem, 1)[0] = rl;
SIZ(rem) = -1;
}
}
return rl;
}

View File

@@ -0,0 +1,102 @@
/* mpz_cdiv_ui -- Division rounding the quotient towards +infinity. The
remainder gets the opposite sign as the denominator. In order to make it
always fit into the return type, the negative of the true remainder is
returned.
Copyright 1994-1996, 2001, 2002, 2004, 2005, 2012 Free Software Foundation,
Inc.
This file is part of the GNU MP Library.
The GNU MP Library is free software; you can redistribute it and/or modify
it under the terms of either:
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
or
* the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any
later version.
or both in parallel, as here.
The GNU MP Library 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 copies of the GNU General Public License and the
GNU Lesser General Public License along with the GNU MP Library. If not,
see https://www.gnu.org/licenses/. */
#include "gmp-impl.h"
unsigned long int
mpz_cdiv_ui (mpz_srcptr dividend, unsigned long int divisor)
{
mp_size_t ns, nn;
mp_ptr np;
mp_limb_t rl;
if (UNLIKELY (divisor == 0))
DIVIDE_BY_ZERO;
ns = SIZ(dividend);
if (ns == 0)
{
return 0;
}
nn = ABS(ns);
np = PTR(dividend);
#if BITS_PER_ULONG > GMP_NUMB_BITS /* avoid warnings about shift amount */
if (divisor > GMP_NUMB_MAX)
{
mp_limb_t dp[2], rp[2];
mp_ptr qp;
mp_size_t rn;
TMP_DECL;
if (nn == 1) /* tdiv_qr requirements; tested above for 0 */
{
rl = np[0];
rp[0] = rl;
}
else
{
TMP_MARK;
dp[0] = divisor & GMP_NUMB_MASK;
dp[1] = divisor >> GMP_NUMB_BITS;
qp = TMP_ALLOC_LIMBS (nn - 2 + 1);
mpn_tdiv_qr (qp, rp, (mp_size_t) 0, np, nn, dp, (mp_size_t) 2);
TMP_FREE;
rl = rp[0] + (rp[1] << GMP_NUMB_BITS);
}
if (rl != 0 && ns >= 0)
{
rl = divisor - rl;
rp[0] = rl & GMP_NUMB_MASK;
rp[1] = rl >> GMP_NUMB_BITS;
}
rn = 1 + (rl > GMP_NUMB_MAX); rn -= (rp[rn - 1] == 0);
}
else
#endif
{
rl = mpn_mod_1 (np, nn, (mp_limb_t) divisor);
if (rl == 0)
;
else
{
if (ns >= 0)
rl = divisor - rl;
}
}
return rl;
}

View File

@@ -0,0 +1,111 @@
/* mpz_cdiv_q_2exp, mpz_fdiv_q_2exp -- quotient from mpz divided by 2^n.
Copyright 1991, 1993, 1994, 1996, 1998, 1999, 2001, 2002, 2004, 2012,
2015 Free Software Foundation, Inc.
This file is part of the GNU MP Library.
The GNU MP Library is free software; you can redistribute it and/or modify
it under the terms of either:
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
or
* the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any
later version.
or both in parallel, as here.
The GNU MP Library 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 copies of the GNU General Public License and the
GNU Lesser General Public License along with the GNU MP Library. If not,
see https://www.gnu.org/licenses/. */
#include "gmp-impl.h"
/* dir==1 for ceil, dir==-1 for floor */
static void __gmpz_cfdiv_q_2exp (REGPARM_3_1 (mpz_ptr, mpz_srcptr, mp_bitcnt_t, int)) REGPARM_ATTR (1);
#define cfdiv_q_2exp(w,u,cnt,dir) __gmpz_cfdiv_q_2exp (REGPARM_3_1 (w,u,cnt,dir))
REGPARM_ATTR (1) static void
cfdiv_q_2exp (mpz_ptr w, mpz_srcptr u, mp_bitcnt_t cnt, int dir)
{
mp_size_t wsize, usize, abs_usize, limb_cnt, i;
mp_srcptr up;
mp_ptr wp;
mp_limb_t round, rmask;
usize = SIZ (u);
abs_usize = ABS (usize);
limb_cnt = cnt / GMP_NUMB_BITS;
wsize = abs_usize - limb_cnt;
if (wsize <= 0)
{
/* u < 2**cnt, so result 1, 0 or -1 according to rounding */
MPZ_NEWALLOC (w, 1)[0] = 1;
SIZ(w) = (usize == 0 || (usize ^ dir) < 0 ? 0 : dir);
return;
}
/* +1 limb to allow for mpn_add_1 below */
wp = MPZ_REALLOC (w, wsize+1);
/* Check for rounding if direction matches u sign.
Set round if we're skipping non-zero limbs. */
up = PTR(u);
round = 0;
rmask = ((usize ^ dir) >= 0 ? MP_LIMB_T_MAX : 0);
if (rmask != 0)
for (i = 0; i < limb_cnt && round == 0; i++)
round = up[i];
cnt %= GMP_NUMB_BITS;
if (cnt != 0)
{
round |= rmask & mpn_rshift (wp, up + limb_cnt, wsize, cnt);
wsize -= (wp[wsize - 1] == 0);
}
else
MPN_COPY_INCR (wp, up + limb_cnt, wsize);
if (round != 0)
{
if (wsize != 0)
{
mp_limb_t cy;
cy = mpn_add_1 (wp, wp, wsize, CNST_LIMB(1));
wp[wsize] = cy;
wsize += cy;
}
else
{
/* We shifted something to zero. */
wp[0] = 1;
wsize = 1;
}
}
SIZ(w) = (usize >= 0 ? wsize : -wsize);
}
void
mpz_cdiv_q_2exp (mpz_ptr w, mpz_srcptr u, mp_bitcnt_t cnt)
{
cfdiv_q_2exp (w, u, cnt, 1);
}
void
mpz_fdiv_q_2exp (mpz_ptr w, mpz_srcptr u, mp_bitcnt_t cnt)
{
cfdiv_q_2exp (w, u, cnt, -1);
}

View File

@@ -0,0 +1,159 @@
/* mpz_cdiv_r_2exp, mpz_fdiv_r_2exp -- remainder from mpz divided by 2^n.
Copyright 2001, 2002, 2004, 2012 Free Software Foundation, Inc.
This file is part of the GNU MP Library.
The GNU MP Library is free software; you can redistribute it and/or modify
it under the terms of either:
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
or
* the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any
later version.
or both in parallel, as here.
The GNU MP Library 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 copies of the GNU General Public License and the
GNU Lesser General Public License along with the GNU MP Library. If not,
see https://www.gnu.org/licenses/. */
#include "gmp-impl.h"
/* Bit mask of "n" least significant bits of a limb. */
#define LOW_MASK(n) ((CNST_LIMB(1) << (n)) - 1)
/* dir==1 for ceil, dir==-1 for floor */
static void __gmpz_cfdiv_r_2exp (REGPARM_3_1 (mpz_ptr, mpz_srcptr, mp_bitcnt_t, int)) REGPARM_ATTR (1);
#define cfdiv_r_2exp(w,u,cnt,dir) __gmpz_cfdiv_r_2exp (REGPARM_3_1 (w, u, cnt, dir))
REGPARM_ATTR (1) static void
cfdiv_r_2exp (mpz_ptr w, mpz_srcptr u, mp_bitcnt_t cnt, int dir)
{
mp_size_t usize, abs_usize, limb_cnt, i;
mp_srcptr up;
mp_ptr wp;
mp_limb_t high;
usize = SIZ(u);
if (usize == 0)
{
SIZ(w) = 0;
return;
}
limb_cnt = cnt / GMP_NUMB_BITS;
cnt %= GMP_NUMB_BITS;
abs_usize = ABS (usize);
/* MPZ_REALLOC(w) below is only when w!=u, so we can fetch PTR(u) here
nice and early */
up = PTR(u);
if ((usize ^ dir) < 0)
{
/* Round towards zero, means just truncate */
if (w == u)
{
/* if already smaller than limb_cnt then do nothing */
if (abs_usize <= limb_cnt)
return;
wp = (mp_ptr) up;
}
else
{
i = MIN (abs_usize, limb_cnt+1);
wp = MPZ_NEWALLOC (w, i);
MPN_COPY (wp, up, i);
/* if smaller than limb_cnt then only the copy is needed */
if (abs_usize <= limb_cnt)
{
SIZ(w) = usize;
return;
}
}
}
else
{
/* Round away from zero, means twos complement if non-zero */
/* if u!=0 and smaller than divisor, then must negate */
if (abs_usize <= limb_cnt)
goto negate;
/* if non-zero low limb, then must negate */
for (i = 0; i < limb_cnt; i++)
if (up[i] != 0)
goto negate;
/* if non-zero partial limb, then must negate */
if ((up[limb_cnt] & LOW_MASK (cnt)) != 0)
goto negate;
/* otherwise low bits of u are zero, so that's the result */
SIZ(w) = 0;
return;
negate:
/* twos complement negation to get 2**cnt-u */
wp = MPZ_REALLOC (w, limb_cnt+1);
up = PTR(u);
/* Ones complement */
i = MIN (abs_usize, limb_cnt+1);
ASSERT_CARRY (mpn_neg (wp, up, i));
for ( ; i <= limb_cnt; i++)
wp[i] = GMP_NUMB_MAX;
usize = -usize;
}
/* Mask the high limb */
high = wp[limb_cnt];
high &= LOW_MASK (cnt);
wp[limb_cnt] = high;
/* Strip any consequent high zeros */
while (high == 0)
{
limb_cnt--;
if (limb_cnt < 0)
{
SIZ(w) = 0;
return;
}
high = wp[limb_cnt];
}
limb_cnt++;
SIZ(w) = (usize >= 0 ? limb_cnt : -limb_cnt);
}
void
mpz_cdiv_r_2exp (mpz_ptr w, mpz_srcptr u, mp_bitcnt_t cnt)
{
cfdiv_r_2exp (w, u, cnt, 1);
}
void
mpz_fdiv_r_2exp (mpz_ptr w, mpz_srcptr u, mp_bitcnt_t cnt)
{
cfdiv_r_2exp (w, u, cnt, -1);
}

View File

@@ -0,0 +1,40 @@
/* mpz_clear -- de-allocate the space occupied by the dynamic digit space of
an integer.
Copyright 1991, 1993-1995, 2000, 2001, 2012, 2014, 2015 Free Software
Foundation, Inc.
This file is part of the GNU MP Library.
The GNU MP Library is free software; you can redistribute it and/or modify
it under the terms of either:
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
or
* the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any
later version.
or both in parallel, as here.
The GNU MP Library 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 copies of the GNU General Public License and the
GNU Lesser General Public License along with the GNU MP Library. If not,
see https://www.gnu.org/licenses/. */
#include "gmp-impl.h"
void
mpz_clear (mpz_ptr x)
{
if (ALLOC (x))
__GMP_FREE_FUNC_LIMBS (PTR (x), ALLOC(x));
}

View File

@@ -0,0 +1,50 @@
/* mpz_clears() -- Clear multiple mpz_t variables.
Copyright 2009, 2014, 2015 Free Software Foundation, Inc.
This file is part of the GNU MP Library.
The GNU MP Library is free software; you can redistribute it and/or modify
it under the terms of either:
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
or
* the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any
later version.
or both in parallel, as here.
The GNU MP Library 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 copies of the GNU General Public License and the
GNU Lesser General Public License along with the GNU MP Library. If not,
see https://www.gnu.org/licenses/. */
#include <stdarg.h>
#include "gmp-impl.h"
void
mpz_clears (mpz_ptr x, ...)
{
va_list ap;
va_start (ap, x);
do
{
if (ALLOC (x))
__GMP_FREE_FUNC_LIMBS (PTR (x), ALLOC (x));
x = va_arg (ap, mpz_ptr);
}
while (x != NULL);
va_end (ap);
}

View File

@@ -0,0 +1,115 @@
/* mpz_clrbit -- clear a specified bit.
Copyright 1991, 1993-1995, 2001, 2002, 2012 Free Software Foundation, Inc.
This file is part of the GNU MP Library.
The GNU MP Library is free software; you can redistribute it and/or modify
it under the terms of either:
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
or
* the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any
later version.
or both in parallel, as here.
The GNU MP Library 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 copies of the GNU General Public License and the
GNU Lesser General Public License along with the GNU MP Library. If not,
see https://www.gnu.org/licenses/. */
#include "gmp-impl.h"
void
mpz_clrbit (mpz_ptr d, mp_bitcnt_t bit_idx)
{
mp_size_t dsize = SIZ (d);
mp_ptr dp = PTR (d);
mp_size_t limb_idx;
mp_limb_t mask;
limb_idx = bit_idx / GMP_NUMB_BITS;
mask = CNST_LIMB(1) << (bit_idx % GMP_NUMB_BITS);
if (dsize >= 0)
{
if (limb_idx < dsize)
{
mp_limb_t dlimb;
dlimb = dp[limb_idx] & ~mask;
dp[limb_idx] = dlimb;
if (UNLIKELY ((dlimb == 0) + limb_idx == dsize)) /* dsize == limb_idx + 1 */
{
/* high limb became zero, must normalize */
MPN_NORMALIZE (dp, limb_idx);
SIZ (d) = limb_idx;
}
}
else
;
}
else
{
/* Simulate two's complement arithmetic, i.e. simulate
1. Set OP = ~(OP - 1) [with infinitely many leading ones].
2. clear the bit.
3. Set OP = ~OP + 1. */
dsize = -dsize;
if (limb_idx < dsize)
{
mp_size_t zero_bound;
/* No index upper bound on this loop, we're sure there's a non-zero limb
sooner or later. */
zero_bound = 0;
while (dp[zero_bound] == 0)
zero_bound++;
if (limb_idx > zero_bound)
{
dp[limb_idx] |= mask;
}
else if (limb_idx == zero_bound)
{
mp_limb_t dlimb;
dlimb = (((dp[limb_idx] - 1) | mask) + 1) & GMP_NUMB_MASK;
dp[limb_idx] = dlimb;
if (dlimb == 0)
{
/* Increment at limb_idx + 1. Extend the number with a zero limb
for simplicity. */
dp = MPZ_REALLOC (d, dsize + 1);
dp[dsize] = 0;
MPN_INCR_U (dp + limb_idx + 1, dsize - limb_idx, 1);
dsize += dp[dsize];
SIZ (d) = -dsize;
}
}
else
;
}
else
{
/* Ugh. The bit should be cleared outside of the end of the
number. We have to increase the size of the number. */
dp = MPZ_REALLOC (d, limb_idx + 1);
SIZ (d) = -(limb_idx + 1);
MPN_ZERO (dp + dsize, limb_idx - dsize);
dp[limb_idx] = mask;
}
}
}

View File

@@ -0,0 +1,53 @@
/* mpz_cmp(u,v) -- Compare U, V. Return positive, zero, or negative
based on if U > V, U == V, or U < V.
Copyright 1991, 1993, 1994, 1996, 2001, 2002, 2011, 2020 Free Software
Foundation, Inc.
This file is part of the GNU MP Library.
The GNU MP Library is free software; you can redistribute it and/or modify
it under the terms of either:
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
or
* the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any
later version.
or both in parallel, as here.
The GNU MP Library 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 copies of the GNU General Public License and the
GNU Lesser General Public License along with the GNU MP Library. If not,
see https://www.gnu.org/licenses/. */
#include "gmp-impl.h"
int
mpz_cmp (mpz_srcptr u, mpz_srcptr v) __GMP_NOTHROW
{
mp_size_t usize, vsize, asize;
mp_srcptr up, vp;
int cmp;
usize = SIZ(u);
vsize = SIZ(v);
/* Cannot use usize - vsize, may overflow an "int" */
if (usize != vsize)
return (usize > vsize) ? 1 : -1;
asize = ABS (usize);
up = PTR(u);
vp = PTR(v);
MPN_CMP (cmp, up, vp, asize);
return (usize >= 0 ? cmp : -cmp);
}

View File

@@ -0,0 +1,144 @@
/* mpz_cmp_d -- compare absolute values of mpz and double.
Copyright 2001-2003 Free Software Foundation, Inc.
This file is part of the GNU MP Library.
The GNU MP Library is free software; you can redistribute it and/or modify
it under the terms of either:
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
or
* the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any
later version.
or both in parallel, as here.
The GNU MP Library 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 copies of the GNU General Public License and the
GNU Lesser General Public License along with the GNU MP Library. If not,
see https://www.gnu.org/licenses/. */
#include "config.h"
#if HAVE_FLOAT_H
#include <float.h> /* for DBL_MAX */
#endif
#include "gmp-impl.h"
#define RETURN_CMP(zl, dl) \
do { \
zlimb = (zl); \
dlimb = (dl); \
if (zlimb != dlimb) \
return (zlimb >= dlimb ? ret : -ret); \
} while (0)
#define RETURN_NONZERO(ptr, size, val) \
do { \
mp_size_t __i; \
for (__i = (size)-1; __i >= 0; __i--) \
if ((ptr)[__i] != 0) \
return val; \
return 0; \
} while (0)
int
mpz_cmp_d (mpz_srcptr z, double d)
{
mp_limb_t darray[LIMBS_PER_DOUBLE], zlimb, dlimb;
mp_srcptr zp;
mp_size_t zsize;
int dexp, ret;
/* d=NaN is an invalid operation, there's no sensible return value.
d=Inf or -Inf is always bigger than z. */
DOUBLE_NAN_INF_ACTION (d, __gmp_invalid_operation (), goto z_zero);
/* 1. Either operand zero. */
zsize = SIZ(z);
if (d == 0.0)
return zsize;
if (zsize == 0)
{
z_zero:
return (d < 0.0 ? 1 : -1);
}
/* 2. Opposite signs. */
if (zsize >= 0)
{
if (d < 0.0)
return 1; /* >=0 cmp <0 */
ret = 1;
}
else
{
if (d >= 0.0)
return -1; /* <0 cmp >=0 */
ret = -1;
d = -d;
zsize = -zsize;
}
/* 3. Small d, knowing abs(z) >= 1. */
if (d < 1.0)
return ret;
dexp = __gmp_extract_double (darray, d);
ASSERT (dexp >= 1);
/* 4. Check for different high limb positions. */
if (zsize != dexp)
return (zsize >= dexp ? ret : -ret);
/* 5. Limb data. */
zp = PTR(z);
#if LIMBS_PER_DOUBLE == 2
RETURN_CMP (zp[zsize-1], darray[1]);
if (zsize == 1)
return (darray[0] != 0 ? -ret : 0);
RETURN_CMP (zp[zsize-2], darray[0]);
RETURN_NONZERO (zp, zsize-2, ret);
#endif
#if LIMBS_PER_DOUBLE == 3
RETURN_CMP (zp[zsize-1], darray[2]);
if (zsize == 1)
return ((darray[0] | darray[1]) != 0 ? -ret : 0);
RETURN_CMP (zp[zsize-2], darray[1]);
if (zsize == 2)
return (darray[0] != 0 ? -ret : 0);
RETURN_CMP (zp[zsize-3], darray[0]);
RETURN_NONZERO (zp, zsize-3, ret);
#endif
#if LIMBS_PER_DOUBLE >= 4
{
int i;
for (i = 1; i <= LIMBS_PER_DOUBLE; i++)
{
RETURN_CMP (zp[zsize-i], darray[LIMBS_PER_DOUBLE-i]);
if (i >= zsize)
RETURN_NONZERO (darray, LIMBS_PER_DOUBLE-i, -ret);
}
RETURN_NONZERO (zp, zsize-LIMBS_PER_DOUBLE, ret);
}
#endif
}

View File

@@ -0,0 +1,69 @@
/* mpz_cmp_si(u,v) -- Compare an integer U with a single-word int V.
Return positive, zero, or negative based on if U > V, U == V, or U < V.
Copyright 1991, 1993-1996, 2000-2002, 2012, 2013 Free Software Foundation, Inc.
This file is part of the GNU MP Library.
The GNU MP Library is free software; you can redistribute it and/or modify
it under the terms of either:
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
or
* the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any
later version.
or both in parallel, as here.
The GNU MP Library 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 copies of the GNU General Public License and the
GNU Lesser General Public License along with the GNU MP Library. If not,
see https://www.gnu.org/licenses/. */
#include "gmp-impl.h"
int
_mpz_cmp_si (mpz_srcptr u, signed long int v_digit) __GMP_NOTHROW
{
#if GMP_NAIL_BITS != 0
/* FIXME. This isn't very pretty. */
mpz_t tmp;
mp_limb_t tt[2];
PTR(tmp) = tt;
ALLOC(tmp) = 2;
mpz_set_si (tmp, v_digit);
return mpz_cmp (u, tmp);
#else
mp_size_t vsize, usize;
usize = SIZ (u);
vsize = (v_digit > 0) - (v_digit < 0);
if ((usize == 0) | (usize != vsize))
return usize - vsize;
else {
mp_limb_t u_digit, absv_digit;
u_digit = PTR (u)[0];
absv_digit = ABS_CAST (unsigned long, v_digit);
if (u_digit == absv_digit)
return 0;
if (u_digit > absv_digit)
return usize;
else
return -usize;
}
#endif
}

View File

@@ -0,0 +1,77 @@
/* mpz_cmp_ui.c -- Compare an mpz_t a with an mp_limb_t b. Return positive,
zero, or negative based on if a > b, a == b, or a < b.
Copyright 1991, 1993-1996, 2001, 2002 Free Software Foundation, Inc.
This file is part of the GNU MP Library.
The GNU MP Library is free software; you can redistribute it and/or modify
it under the terms of either:
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
or
* the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any
later version.
or both in parallel, as here.
The GNU MP Library 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 copies of the GNU General Public License and the
GNU Lesser General Public License along with the GNU MP Library. If not,
see https://www.gnu.org/licenses/. */
#include "gmp-impl.h"
int
_mpz_cmp_ui (mpz_srcptr u, unsigned long int v_digit) __GMP_NOTHROW
{
mp_ptr up;
mp_size_t un;
mp_limb_t ul;
up = PTR(u);
un = SIZ(u);
if (un == 0)
return -(v_digit != 0);
if (un == 1)
{
ul = up[0];
if (ul > v_digit)
return 1;
if (ul < v_digit)
return -1;
return 0;
}
#if GMP_NAIL_BITS != 0
if (v_digit > GMP_NUMB_MAX)
{
if (un == 2)
{
ul = up[0] + (up[1] << GMP_NUMB_BITS);
if ((up[1] >> GMP_NAIL_BITS) != 0)
return 1;
if (ul > v_digit)
return 1;
if (ul < v_digit)
return -1;
return 0;
}
}
#endif
return un > 0 ? 1 : -1;
}

View File

@@ -0,0 +1,53 @@
/* mpz_cmpabs(u,v) -- Compare U, V. Return positive, zero, or negative
based on if U > V, U == V, or U < V.
Copyright 1991, 1993, 1994, 1996, 1997, 2000-2002, 2020 Free Software
Foundation, Inc.
This file is part of the GNU MP Library.
The GNU MP Library is free software; you can redistribute it and/or modify
it under the terms of either:
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
or
* the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any
later version.
or both in parallel, as here.
The GNU MP Library 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 copies of the GNU General Public License and the
GNU Lesser General Public License along with the GNU MP Library. If not,
see https://www.gnu.org/licenses/. */
#include "gmp-impl.h"
int
mpz_cmpabs (mpz_srcptr u, mpz_srcptr v) __GMP_NOTHROW
{
mp_size_t usize, vsize;
mp_srcptr up, vp;
int cmp;
usize = ABSIZ (u);
vsize = ABSIZ (v);
/* Cannot use usize - vsize, may overflow an "int" */
if (usize != vsize)
return (usize > vsize) ? 1 : -1;
up = PTR(u);
vp = PTR(v);
MPN_CMP (cmp, up, vp, usize);
return cmp;
}

View File

@@ -0,0 +1,129 @@
/* mpz_cmpabs_d -- compare absolute values of mpz and double.
Copyright 2001-2003, 2012 Free Software Foundation, Inc.
This file is part of the GNU MP Library.
The GNU MP Library is free software; you can redistribute it and/or modify
it under the terms of either:
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
or
* the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any
later version.
or both in parallel, as here.
The GNU MP Library 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 copies of the GNU General Public License and the
GNU Lesser General Public License along with the GNU MP Library. If not,
see https://www.gnu.org/licenses/. */
#include "config.h"
#if HAVE_FLOAT_H
#include <float.h> /* for DBL_MAX */
#endif
#include "gmp-impl.h"
#define RETURN_CMP(zl, dl) \
do { \
zlimb = (zl); \
dlimb = (dl); \
if (zlimb != dlimb) \
return (zlimb >= dlimb ? 1 : -1); \
} while (0)
#define RETURN_NONZERO(ptr, size, val) \
do { \
mp_size_t __i; \
for (__i = (size)-1; __i >= 0; __i--) \
if ((ptr)[__i] != 0) \
return val; \
return 0; \
} while (0)
int
mpz_cmpabs_d (mpz_srcptr z, double d)
{
mp_limb_t darray[LIMBS_PER_DOUBLE], zlimb, dlimb;
mp_srcptr zp;
mp_size_t zsize;
int dexp;
/* d=NaN is an invalid operation, there's no sensible return value.
d=Inf or -Inf is always bigger than z. */
DOUBLE_NAN_INF_ACTION (d, __gmp_invalid_operation (), return -1);
/* 1. Check for either operand zero. */
zsize = SIZ(z);
if (d == 0.0)
return (zsize != 0);
if (zsize == 0)
return -1; /* d != 0 */
/* 2. Ignore signs. */
zsize = ABS(zsize);
d = ABS(d);
/* 3. Small d, knowing abs(z) >= 1. */
if (d < 1.0)
return 1;
dexp = __gmp_extract_double (darray, d);
ASSERT (dexp >= 1);
/* 4. Check for different high limb positions. */
if (zsize != dexp)
return (zsize >= dexp ? 1 : -1);
/* 5. Limb data. */
zp = PTR(z);
#if LIMBS_PER_DOUBLE == 2
RETURN_CMP (zp[zsize-1], darray[1]);
if (zsize == 1)
return (darray[0] != 0 ? -1 : 0);
RETURN_CMP (zp[zsize-2], darray[0]);
RETURN_NONZERO (zp, zsize-2, 1);
#endif
#if LIMBS_PER_DOUBLE == 3
RETURN_CMP (zp[zsize-1], darray[2]);
if (zsize == 1)
return ((darray[0] | darray[1]) != 0 ? -1 : 0);
RETURN_CMP (zp[zsize-2], darray[1]);
if (zsize == 2)
return (darray[0] != 0 ? -1 : 0);
RETURN_CMP (zp[zsize-3], darray[0]);
RETURN_NONZERO (zp, zsize-3, 1);
#endif
#if LIMBS_PER_DOUBLE >= 4
{
int i;
for (i = 1; i <= LIMBS_PER_DOUBLE; i++)
{
RETURN_CMP (zp[zsize-i], darray[LIMBS_PER_DOUBLE-i]);
if (i >= zsize)
RETURN_NONZERO (darray, LIMBS_PER_DOUBLE-i, -1);
}
RETURN_NONZERO (zp, zsize-LIMBS_PER_DOUBLE, 1);
}
#endif
}

View File

@@ -0,0 +1,76 @@
/* mpz_cmpabs_ui.c -- Compare an mpz_t a with an mp_limb_t b. Return positive,
zero, or negative based on if a > b, a == b, or a < b.
Copyright 1991, 1993-1995, 1997, 2000-2002 Free Software Foundation, Inc.
This file is part of the GNU MP Library.
The GNU MP Library is free software; you can redistribute it and/or modify
it under the terms of either:
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
or
* the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any
later version.
or both in parallel, as here.
The GNU MP Library 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 copies of the GNU General Public License and the
GNU Lesser General Public License along with the GNU MP Library. If not,
see https://www.gnu.org/licenses/. */
#include "gmp-impl.h"
int
mpz_cmpabs_ui (mpz_srcptr u, unsigned long int v_digit) __GMP_NOTHROW
{
mp_ptr up;
mp_size_t un;
mp_limb_t ul;
up = PTR(u);
un = SIZ(u);
if (un == 0)
return -(v_digit != 0);
un = ABS (un);
if (un == 1)
{
ul = up[0];
if (ul > v_digit)
return 1;
if (ul < v_digit)
return -1;
return 0;
}
#if GMP_NAIL_BITS != 0
if (v_digit > GMP_NUMB_MAX)
{
if (un == 2)
{
ul = up[0] + (up[1] << GMP_NUMB_BITS);
if (ul > v_digit)
return 1;
if (ul < v_digit)
return -1;
return 0;
}
}
#endif
return 1;
}

View File

@@ -0,0 +1,87 @@
/* mpz_com(mpz_ptr dst, mpz_ptr src) -- Assign the bit-complemented value of
SRC to DST.
Copyright 1991, 1993, 1994, 1996, 2001, 2003, 2012, 2015 Free Software
Foundation, Inc.
This file is part of the GNU MP Library.
The GNU MP Library is free software; you can redistribute it and/or modify
it under the terms of either:
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
or
* the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any
later version.
or both in parallel, as here.
The GNU MP Library 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 copies of the GNU General Public License and the
GNU Lesser General Public License along with the GNU MP Library. If not,
see https://www.gnu.org/licenses/. */
#include "gmp-impl.h"
void
mpz_com (mpz_ptr dst, mpz_srcptr src)
{
mp_size_t size = SIZ (src);
mp_srcptr src_ptr;
mp_ptr dst_ptr;
if (size >= 0)
{
/* As with infinite precision: one's complement, two's complement.
But this can be simplified using the identity -x = ~x + 1.
So we're going to compute (~~x) + 1 = x + 1! */
if (UNLIKELY (size == 0))
{
/* special case, as mpn_add_1 wants size!=0 */
MPZ_NEWALLOC (dst, 1)[0] = 1;
SIZ (dst) = -1;
}
else
{
mp_limb_t cy;
dst_ptr = MPZ_REALLOC (dst, size + 1);
src_ptr = PTR (src);
cy = mpn_add_1 (dst_ptr, src_ptr, size, (mp_limb_t) 1);
dst_ptr[size] = cy;
size += cy;
/* Store a negative size, to indicate ones-extension. */
SIZ (dst) = -size;
}
}
else
{
/* As with infinite precision: two's complement, then one's complement.
But that can be simplified using the identity -x = ~(x - 1).
So we're going to compute ~~(x - 1) = x - 1! */
size = -size;
dst_ptr = MPZ_REALLOC (dst, size);
src_ptr = PTR (src);
mpn_sub_1 (dst_ptr, src_ptr, size, (mp_limb_t) 1);
size -= dst_ptr[size - 1] == 0;
/* Store a positive size, to indicate zero-extension. */
SIZ (dst) = size;
}
}

View File

@@ -0,0 +1,103 @@
/* mpz_combit -- complement a specified bit.
Copyright 2002, 2003, 2012, 2015 Free Software Foundation, Inc.
This file is part of the GNU MP Library.
The GNU MP Library is free software; you can redistribute it and/or modify
it under the terms of either:
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
or
* the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any
later version.
or both in parallel, as here.
The GNU MP Library 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 copies of the GNU General Public License and the
GNU Lesser General Public License along with the GNU MP Library. If not,
see https://www.gnu.org/licenses/. */
#include "gmp-impl.h"
void
mpz_combit (mpz_ptr d, mp_bitcnt_t bit_index)
{
mp_size_t dsize = SIZ(d);
mp_ptr dp = PTR(d);
mp_size_t limb_index = bit_index / GMP_NUMB_BITS;
mp_limb_t bit = (CNST_LIMB (1) << (bit_index % GMP_NUMB_BITS));
/* Check for the most common case: Positive input, no realloc or
normalization needed. */
if (limb_index + 1 < dsize)
dp[limb_index] ^= bit;
/* Check for the hairy case. d < 0, and we have all zero bits to the
right of the bit to toggle. */
else if (limb_index < -dsize
&& (limb_index == 0 || mpn_zero_p (dp, limb_index))
&& (dp[limb_index] & (bit - 1)) == 0)
{
ASSERT (dsize < 0);
dsize = -dsize;
if (dp[limb_index] & bit)
{
/* We toggle the least significant one bit. Corresponds to
an add, with potential carry propagation, on the absolute
value. */
dp = MPZ_REALLOC (d, 1 + dsize);
dp[dsize] = 0;
MPN_INCR_U (dp + limb_index, 1 + dsize - limb_index, bit);
SIZ(d) = - dsize - dp[dsize];
}
else
{
/* We toggle a zero bit, subtract from the absolute value. */
MPN_DECR_U (dp + limb_index, dsize - limb_index, bit);
/* The absolute value shrinked by at most one bit. */
dsize -= dp[dsize - 1] == 0;
ASSERT (dsize > 0 && dp[dsize - 1] != 0);
SIZ (d) = -dsize;
}
}
else
{
/* Simple case: Toggle the bit in the absolute value. */
dsize = ABS(dsize);
if (limb_index < dsize)
{
mp_limb_t dlimb;
dlimb = dp[limb_index] ^ bit;
dp[limb_index] = dlimb;
/* Can happen only when limb_index = dsize - 1. Avoid SIZ(d)
bookkeeping in the common case. */
if (UNLIKELY ((dlimb == 0) + limb_index == dsize)) /* dsize == limb_index + 1 */
{
/* high limb became zero, must normalize */
MPN_NORMALIZE (dp, limb_index);
SIZ (d) = SIZ (d) >= 0 ? limb_index : -limb_index;
}
}
else
{
dp = MPZ_REALLOC (d, limb_index + 1);
MPN_ZERO(dp + dsize, limb_index - dsize);
dp[limb_index++] = bit;
SIZ(d) = SIZ(d) >= 0 ? limb_index : -limb_index;
}
}
}

View File

@@ -0,0 +1,182 @@
/* mpz_congruent_p -- test congruence of two mpz's.
Copyright 2001, 2002, 2005 Free Software Foundation, Inc.
This file is part of the GNU MP Library.
The GNU MP Library is free software; you can redistribute it and/or modify
it under the terms of either:
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
or
* the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any
later version.
or both in parallel, as here.
The GNU MP Library 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 copies of the GNU General Public License and the
GNU Lesser General Public License along with the GNU MP Library. If not,
see https://www.gnu.org/licenses/. */
#include "gmp-impl.h"
#include "longlong.h"
/* For big divisors this code is only very slightly better than the user
doing a combination of mpz_sub and mpz_tdiv_r, but it's quite convenient,
and perhaps in the future can be improved, in similar ways to
mpn_divisible_p perhaps.
The csize==1 / dsize==1 special case makes mpz_congruent_p as good as
mpz_congruent_ui_p on relevant operands, though such a combination
probably doesn't occur often.
Alternatives:
If c<d then it'd work to just form a%d and compare a and c (either as
a==c or a+c==d depending on the signs), but the saving from avoiding the
abs(a-c) calculation would be small compared to the division.
Similarly if both a<d and c<d then it would work to just compare a and c
(a==c or a+c==d), but this isn't considered a particularly important case
and so isn't done for the moment.
Low zero limbs on d could be stripped and the corresponding limbs of a
and c tested and skipped, but doing so would introduce a borrow when a
and c differ in sign and have non-zero skipped limbs. It doesn't seem
worth the complications to do this, since low zero limbs on d should
occur only rarely. */
int
mpz_congruent_p (mpz_srcptr a, mpz_srcptr c, mpz_srcptr d)
{
mp_size_t asize, csize, dsize, sign;
mp_srcptr ap, cp, dp;
mp_ptr xp;
mp_limb_t alow, clow, dlow, dmask, r;
int result;
TMP_DECL;
dsize = SIZ(d);
if (UNLIKELY (dsize == 0))
return (mpz_cmp (a, c) == 0);
dsize = ABS(dsize);
dp = PTR(d);
if (ABSIZ(a) < ABSIZ(c))
MPZ_SRCPTR_SWAP (a, c);
asize = SIZ(a);
csize = SIZ(c);
sign = (asize ^ csize);
asize = ABS(asize);
ap = PTR(a);
if (csize == 0)
return mpn_divisible_p (ap, asize, dp, dsize);
csize = ABS(csize);
cp = PTR(c);
alow = ap[0];
clow = cp[0];
dlow = dp[0];
/* Check a==c mod low zero bits of dlow. This might catch a few cases of
a!=c quickly, and it helps the csize==1 special cases below. */
dmask = LOW_ZEROS_MASK (dlow) & GMP_NUMB_MASK;
alow = (sign >= 0 ? alow : -alow);
if (((alow-clow) & dmask) != 0)
return 0;
if (csize == 1)
{
if (dsize == 1)
{
cong_1:
if (sign < 0)
NEG_MOD (clow, clow, dlow);
if (ABOVE_THRESHOLD (asize, BMOD_1_TO_MOD_1_THRESHOLD))
{
r = mpn_mod_1 (ap, asize, dlow);
if (clow < dlow)
return r == clow;
else
return r == (clow % dlow);
}
if ((dlow & 1) == 0)
{
/* Strip low zero bits to get odd d required by modexact. If
d==e*2^n then a==c mod d if and only if both a==c mod e and
a==c mod 2^n, the latter having been done above. */
unsigned twos;
count_trailing_zeros (twos, dlow);
dlow >>= twos;
}
r = mpn_modexact_1c_odd (ap, asize, dlow, clow);
return r == 0 || r == dlow;
}
/* dlow==0 is avoided since we don't want to bother handling extra low
zero bits if dsecond is even (would involve borrow if a,c differ in
sign and alow,clow!=0). */
if (dsize == 2 && dlow != 0)
{
mp_limb_t dsecond = dp[1];
if (dsecond <= dmask)
{
unsigned twos;
count_trailing_zeros (twos, dlow);
dlow = (dlow >> twos) | (dsecond << (GMP_NUMB_BITS-twos));
ASSERT_LIMB (dlow);
/* dlow will be odd here, so the test for it even under cong_1
is unnecessary, but the rest of that code is wanted. */
goto cong_1;
}
}
}
TMP_MARK;
xp = TMP_ALLOC_LIMBS (asize+1);
/* calculate abs(a-c) */
if (sign >= 0)
{
/* same signs, subtract */
if (asize > csize || mpn_cmp (ap, cp, asize) >= 0)
ASSERT_NOCARRY (mpn_sub (xp, ap, asize, cp, csize));
else
ASSERT_NOCARRY (mpn_sub_n (xp, cp, ap, asize));
MPN_NORMALIZE (xp, asize);
}
else
{
/* different signs, add */
mp_limb_t carry;
carry = mpn_add (xp, ap, asize, cp, csize);
xp[asize] = carry;
asize += (carry != 0);
}
result = mpn_divisible_p (xp, asize, dp, dsize);
TMP_FREE;
return result;
}

View File

@@ -0,0 +1,149 @@
/* mpz_congruent_2exp_p -- test congruence of mpz mod 2^n.
Copyright 2001, 2002, 2013 Free Software Foundation, Inc.
This file is part of the GNU MP Library.
The GNU MP Library is free software; you can redistribute it and/or modify
it under the terms of either:
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
or
* the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any
later version.
or both in parallel, as here.
The GNU MP Library 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 copies of the GNU General Public License and the
GNU Lesser General Public License along with the GNU MP Library. If not,
see https://www.gnu.org/licenses/. */
#include "gmp-impl.h"
int
mpz_congruent_2exp_p (mpz_srcptr a, mpz_srcptr c, mp_bitcnt_t d) __GMP_NOTHROW
{
mp_size_t i, dlimbs;
unsigned dbits;
mp_ptr ap, cp;
mp_limb_t dmask, alimb, climb, sum;
mp_size_t as, cs, asize, csize;
as = SIZ(a);
asize = ABS(as);
cs = SIZ(c);
csize = ABS(cs);
if (asize < csize)
{
MPZ_SRCPTR_SWAP (a, c);
MP_SIZE_T_SWAP (asize, csize);
}
dlimbs = d / GMP_NUMB_BITS;
dbits = d % GMP_NUMB_BITS;
dmask = (CNST_LIMB(1) << dbits) - 1;
ap = PTR(a);
cp = PTR(c);
if (csize == 0)
goto a_zeros;
if ((cs ^ as) >= 0)
{
/* same signs, direct comparison */
/* a==c for limbs in common */
if (mpn_cmp (ap, cp, MIN (csize, dlimbs)) != 0)
return 0;
/* if that's all of dlimbs, then a==c for remaining bits */
if (csize > dlimbs)
return ((ap[dlimbs]-cp[dlimbs]) & dmask) == 0;
a_zeros:
/* a remains, need all zero bits */
/* if d covers all of a and c, then must be exactly equal */
if (asize <= dlimbs)
return asize == csize;
/* whole limbs zero */
for (i = csize; i < dlimbs; i++)
if (ap[i] != 0)
return 0;
/* partial limb zero */
return (ap[dlimbs] & dmask) == 0;
}
else
{
/* different signs, negated comparison */
/* common low zero limbs, stopping at first non-zeros, which must
match twos complement */
i = 0;
do
{
ASSERT (i < csize); /* always have a non-zero limb on c */
alimb = ap[i];
climb = cp[i];
sum = (alimb + climb) & GMP_NUMB_MASK;
if (i >= dlimbs)
return (sum & dmask) == 0;
++i;
/* require both zero, or first non-zeros as twos-complements */
if (sum != 0)
return 0;
} while (alimb == 0);
/* further limbs matching as ones-complement */
for (; i < csize; ++i)
{
alimb = ap[i];
climb = cp[i];
sum = alimb ^ climb ^ GMP_NUMB_MASK;
if (i >= dlimbs)
return (sum & dmask) == 0;
if (sum != 0)
return 0;
}
/* no more c, so require all 1 bits in a */
if (asize < dlimbs)
return 0; /* not enough a */
/* whole limbs */
for ( ; i < dlimbs; i++)
if (ap[i] != GMP_NUMB_MAX)
return 0;
/* if only whole limbs, no further fetches from a */
if (dbits == 0)
return 1;
/* need enough a */
if (asize == dlimbs)
return 0;
return ((ap[dlimbs]+1) & dmask) == 0;
}
}

View File

@@ -0,0 +1,115 @@
/* mpz_congruent_ui_p -- test congruence of mpz and ulong.
Copyright 2000-2002, 2012 Free Software Foundation, Inc.
This file is part of the GNU MP Library.
The GNU MP Library is free software; you can redistribute it and/or modify
it under the terms of either:
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
or
* the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any
later version.
or both in parallel, as here.
The GNU MP Library 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 copies of the GNU General Public License and the
GNU Lesser General Public License along with the GNU MP Library. If not,
see https://www.gnu.org/licenses/. */
#include "gmp-impl.h"
#include "longlong.h"
/* There's some explicit checks for c<d since it seems reasonably likely an
application might use that in a test.
Hopefully the compiler can generate something good for r==(c%d), though
if modexact is being used exclusively then that's not reached. */
int
mpz_congruent_ui_p (mpz_srcptr a, unsigned long cu, unsigned long du)
{
mp_srcptr ap;
mp_size_t asize;
mp_limb_t c, d, r;
if (UNLIKELY (du == 0))
return (mpz_cmp_ui (a, cu) == 0);
asize = SIZ(a);
if (asize == 0)
{
if (cu < du)
return cu == 0;
else
return (cu % du) == 0;
}
/* For nails don't try to be clever if c or d is bigger than a limb, just
fake up some mpz_t's and go to the main mpz_congruent_p. */
if (du > GMP_NUMB_MAX || cu > GMP_NUMB_MAX)
{
mp_limb_t climbs[2], dlimbs[2];
mpz_t cz, dz;
ALLOC(cz) = 2;
PTR(cz) = climbs;
ALLOC(dz) = 2;
PTR(dz) = dlimbs;
mpz_set_ui (cz, cu);
mpz_set_ui (dz, du);
return mpz_congruent_p (a, cz, dz);
}
/* NEG_MOD works on limbs, so convert ulong to limb */
c = cu;
d = du;
if (asize < 0)
{
asize = -asize;
NEG_MOD (c, c, d);
}
ap = PTR (a);
if (ABOVE_THRESHOLD (asize, BMOD_1_TO_MOD_1_THRESHOLD))
{
r = mpn_mod_1 (ap, asize, d);
if (c < d)
return r == c;
else
return r == (c % d);
}
if ((d & 1) == 0)
{
/* Strip low zero bits to get odd d required by modexact. If
d==e*2^n then a==c mod d if and only if both a==c mod 2^n
and a==c mod e. */
unsigned twos;
if ((ap[0]-c) & LOW_ZEROS_MASK (d))
return 0;
count_trailing_zeros (twos, d);
d >>= twos;
}
r = mpn_modexact_1c_odd (ap, asize, d, c);
return r == 0 || r == d;
}

View File

@@ -0,0 +1,68 @@
/* mpz_divexact_ui -- exact division mpz by ulong.
Copyright 2001, 2002, 2012 Free Software Foundation, Inc.
This file is part of the GNU MP Library.
The GNU MP Library is free software; you can redistribute it and/or modify
it under the terms of either:
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
or
* the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any
later version.
or both in parallel, as here.
The GNU MP Library 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 copies of the GNU General Public License and the
GNU Lesser General Public License along with the GNU MP Library. If not,
see https://www.gnu.org/licenses/. */
#include "gmp-impl.h"
void
mpz_divexact_ui (mpz_ptr dst, mpz_srcptr src, unsigned long divisor)
{
mp_size_t size, abs_size;
mp_ptr dst_ptr;
if (UNLIKELY (divisor == 0))
DIVIDE_BY_ZERO;
/* For nails don't try to be clever if d is bigger than a limb, just fake
up an mpz_t and go to the main mpz_divexact. */
if (divisor > GMP_NUMB_MAX)
{
mp_limb_t dlimbs[2];
mpz_t dz;
ALLOC(dz) = 2;
PTR(dz) = dlimbs;
mpz_set_ui (dz, divisor);
mpz_divexact (dst, src, dz);
return;
}
size = SIZ(src);
if (size == 0)
{
SIZ(dst) = 0;
return;
}
abs_size = ABS (size);
dst_ptr = MPZ_REALLOC (dst, abs_size);
MPN_DIVREM_OR_DIVEXACT_1 (dst_ptr, PTR(src), abs_size, (mp_limb_t) divisor);
abs_size -= (dst_ptr[abs_size-1] == 0);
SIZ(dst) = (size >= 0 ? abs_size : -abs_size);
}

View File

@@ -0,0 +1,156 @@
/* mpz_divexact_gcd -- exact division optimized for GCDs.
THE FUNCTIONS IN THIS FILE ARE FOR INTERNAL USE AND ARE ALMOST CERTAIN TO
BE SUBJECT TO INCOMPATIBLE CHANGES IN FUTURE GNU MP RELEASES.
Copyright 2000, 2005, 2011, 2012 Free Software Foundation, Inc.
This file is part of the GNU MP Library.
The GNU MP Library is free software; you can redistribute it and/or modify
it under the terms of either:
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
or
* the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any
later version.
or both in parallel, as here.
The GNU MP Library 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 copies of the GNU General Public License and the
GNU Lesser General Public License along with the GNU MP Library. If not,
see https://www.gnu.org/licenses/. */
#include "gmp-impl.h"
#include "longlong.h"
/* Set q to a/d, expecting d to be from a GCD and therefore usually small.
The distribution of GCDs of random numbers can be found in Knuth volume 2
section 4.5.2 theorem D.
GCD chance
1 60.8%
2^k 20.2% (1<=k<32)
3*2^k 9.0% (1<=k<32)
other 10.1%
Only the low limb is examined for optimizations, since GCDs bigger than
2^32 (or 2^64) will occur very infrequently.
Future: This could change to an mpn_divexact_gcd, possibly partly
inlined, if/when the relevant mpq functions change to an mpn based
implementation. */
#if GMP_NUMB_BITS % 2 == 0
static void
mpz_divexact_by3 (mpz_ptr q, mpz_srcptr a)
{
mp_size_t size = SIZ(a);
mp_size_t abs_size = ABS(size);
mp_ptr qp;
qp = MPZ_REALLOC (q, abs_size);
mpn_bdiv_dbm1 (qp, PTR(a), abs_size, GMP_NUMB_MASK / 3);
abs_size -= (qp[abs_size-1] == 0);
SIZ(q) = (size>0 ? abs_size : -abs_size);
}
#endif
#if GMP_NUMB_BITS % 4 == 0
static void
mpz_divexact_by5 (mpz_ptr q, mpz_srcptr a)
{
mp_size_t size = SIZ(a);
mp_size_t abs_size = ABS(size);
mp_ptr qp;
qp = MPZ_REALLOC (q, abs_size);
mpn_bdiv_dbm1 (qp, PTR(a), abs_size, GMP_NUMB_MASK / 5);
abs_size -= (qp[abs_size-1] == 0);
SIZ(q) = (size>0 ? abs_size : -abs_size);
}
#endif
static void
mpz_divexact_limb (mpz_ptr q, mpz_srcptr a, mp_limb_t d)
{
mp_size_t size = SIZ(a);
mp_size_t abs_size = ABS(size);
mp_ptr qp;
qp = MPZ_REALLOC (q, abs_size);
MPN_DIVREM_OR_DIVEXACT_1 (qp, PTR(a), abs_size, d);
abs_size -= (qp[abs_size-1] == 0);
SIZ(q) = (size > 0 ? abs_size : -abs_size);
}
void
mpz_divexact_gcd (mpz_ptr q, mpz_srcptr a, mpz_srcptr d)
{
ASSERT (mpz_sgn (d) > 0);
if (SIZ(a) == 0)
{
SIZ(q) = 0;
return;
}
if (SIZ(d) == 1)
{
mp_limb_t dl = PTR(d)[0];
int twos;
if ((dl & 1) == 0)
{
count_trailing_zeros (twos, dl);
dl >>= twos;
mpz_tdiv_q_2exp (q, a, twos);
a = q;
}
if (dl == 1)
{
if (q != a)
mpz_set (q, a);
return;
}
#if GMP_NUMB_BITS % 2 == 0
if (dl == 3)
{
mpz_divexact_by3 (q, a);
return;
}
#endif
#if GMP_NUMB_BITS % 4 == 0
if (dl == 5)
{
mpz_divexact_by5 (q, a);
return;
}
#endif
mpz_divexact_limb (q, a, dl);
return;
}
mpz_divexact (q, a, d);
}

View File

@@ -0,0 +1,89 @@
/* mpz_divexact -- finds quotient when known that quot * den == num && den != 0.
Contributed to the GNU project by Niels Möller.
Copyright 1991, 1993-1998, 2000-2002, 2005-2007, 2009, 2012 Free Software
Foundation, Inc.
This file is part of the GNU MP Library.
The GNU MP Library is free software; you can redistribute it and/or modify
it under the terms of either:
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
or
* the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any
later version.
or both in parallel, as here.
The GNU MP Library 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 copies of the GNU General Public License and the
GNU Lesser General Public License along with the GNU MP Library. If not,
see https://www.gnu.org/licenses/. */
#include "gmp-impl.h"
void
mpz_divexact (mpz_ptr quot, mpz_srcptr num, mpz_srcptr den)
{
mp_ptr qp;
mp_size_t qn;
mp_srcptr np, dp;
mp_size_t nn, dn;
TMP_DECL;
#if WANT_ASSERT
{
mpz_t rem;
mpz_init (rem);
mpz_tdiv_r (rem, num, den);
ASSERT (SIZ(rem) == 0);
mpz_clear (rem);
}
#endif
nn = ABSIZ (num);
dn = ABSIZ (den);
if (nn < dn)
{
/* This special case avoids segfaults below when the function is
incorrectly called with |N| < |D|, N != 0. It also handles the
well-defined case N = 0. */
SIZ(quot) = 0;
return;
}
qn = nn - dn + 1;
TMP_MARK;
if (quot == num || quot == den)
qp = TMP_ALLOC_LIMBS (qn);
else
qp = MPZ_NEWALLOC (quot, qn);
np = PTR(num);
dp = PTR(den);
mpn_divexact (qp, np, nn, dp, dn);
MPN_NORMALIZE (qp, qn);
if (qp != PTR(quot))
MPN_COPY (MPZ_NEWALLOC (quot, qn), qp, qn);
SIZ(quot) = (SIZ(num) ^ SIZ(den)) >= 0 ? qn : -qn;
TMP_FREE;
}

View File

@@ -0,0 +1,43 @@
/* mpz_divisible_p -- mpz by mpz divisibility test
Copyright 2001, 2002 Free Software Foundation, Inc.
This file is part of the GNU MP Library.
The GNU MP Library is free software; you can redistribute it and/or modify
it under the terms of either:
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
or
* the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any
later version.
or both in parallel, as here.
The GNU MP Library 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 copies of the GNU General Public License and the
GNU Lesser General Public License along with the GNU MP Library. If not,
see https://www.gnu.org/licenses/. */
#include "gmp-impl.h"
int
mpz_divisible_p (mpz_srcptr a, mpz_srcptr d)
{
mp_size_t dsize = SIZ(d);
mp_size_t asize = SIZ(a);
if (UNLIKELY (dsize == 0))
return (asize == 0);
return mpn_divisible_p (PTR(a), ABS(asize), PTR(d), ABS(dsize));
}

View File

@@ -0,0 +1,60 @@
/* mpz_divisible_2exp_p -- mpz by 2^n divisibility test
Copyright 2001, 2002 Free Software Foundation, Inc.
This file is part of the GNU MP Library.
The GNU MP Library is free software; you can redistribute it and/or modify
it under the terms of either:
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
or
* the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any
later version.
or both in parallel, as here.
The GNU MP Library 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 copies of the GNU General Public License and the
GNU Lesser General Public License along with the GNU MP Library. If not,
see https://www.gnu.org/licenses/. */
#include "gmp-impl.h"
int
mpz_divisible_2exp_p (mpz_srcptr a, mp_bitcnt_t d) __GMP_NOTHROW
{
mp_size_t i, dlimbs;
unsigned dbits;
mp_ptr ap;
mp_limb_t dmask;
mp_size_t asize;
asize = ABSIZ(a);
dlimbs = d / GMP_NUMB_BITS;
/* if d covers the whole of a, then only a==0 is divisible */
if (asize <= dlimbs)
return asize == 0;
/* whole limbs must be zero */
ap = PTR(a);
for (i = 0; i < dlimbs; i++)
if (ap[i] != 0)
return 0;
/* left over bits must be zero */
dbits = d % GMP_NUMB_BITS;
dmask = (CNST_LIMB(1) << dbits) - 1;
return (ap[dlimbs] & dmask) == 0;
}

View File

@@ -0,0 +1,80 @@
/* mpz_divisible_ui_p -- mpz by ulong divisibility test.
Copyright 2000-2002 Free Software Foundation, Inc.
This file is part of the GNU MP Library.
The GNU MP Library is free software; you can redistribute it and/or modify
it under the terms of either:
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
or
* the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any
later version.
or both in parallel, as here.
The GNU MP Library 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 copies of the GNU General Public License and the
GNU Lesser General Public License along with the GNU MP Library. If not,
see https://www.gnu.org/licenses/. */
#include "gmp-impl.h"
#include "longlong.h"
int
mpz_divisible_ui_p (mpz_srcptr a, unsigned long d)
{
mp_size_t asize;
mp_ptr ap;
unsigned twos;
asize = SIZ(a);
if (UNLIKELY (d == 0))
return (asize == 0);
if (asize == 0) /* 0 divisible by any d */
return 1;
/* For nails don't try to be clever if d is bigger than a limb, just fake
up an mpz_t and go to the main mpz_divisible_p. */
if (d > GMP_NUMB_MAX)
{
mp_limb_t dlimbs[2];
mpz_t dz;
ALLOC(dz) = 2;
PTR(dz) = dlimbs;
mpz_set_ui (dz, d);
return mpz_divisible_p (a, dz);
}
ap = PTR(a);
asize = ABS(asize); /* ignore sign of a */
if (ABOVE_THRESHOLD (asize, BMOD_1_TO_MOD_1_THRESHOLD))
return mpn_mod_1 (ap, asize, (mp_limb_t) d) == 0;
if (! (d & 1))
{
/* Strip low zero bits to get odd d required by modexact. If d==e*2^n
and a is divisible by 2^n and by e, then it's divisible by d. */
if ((ap[0] & LOW_ZEROS_MASK (d)) != 0)
return 0;
count_trailing_zeros (twos, (mp_limb_t) d);
d >>= twos;
}
return mpn_modexact_1_odd (ap, asize, (mp_limb_t) d) == 0;
}

View File

@@ -0,0 +1,48 @@
/* mpz_dump - Dump an integer to stdout.
THIS IS AN INTERNAL FUNCTION WITH A MUTABLE INTERFACE. IT IS NOT SAFE TO
CALL THIS FUNCTION DIRECTLY. IN FACT, IT IS ALMOST GUARANTEED THAT THIS
FUNCTION WILL CHANGE OR DISAPPEAR IN A FUTURE GNU MP RELEASE.
Copyright 1999-2001 Free Software Foundation, Inc.
This file is part of the GNU MP Library.
The GNU MP Library is free software; you can redistribute it and/or modify
it under the terms of either:
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
or
* the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any
later version.
or both in parallel, as here.
The GNU MP Library 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 copies of the GNU General Public License and the
GNU Lesser General Public License along with the GNU MP Library. If not,
see https://www.gnu.org/licenses/. */
#include <stdio.h>
#include <string.h> /* for strlen */
#include "gmp-impl.h"
void
mpz_dump (mpz_srcptr u)
{
char *str;
str = mpz_get_str (0, 10, u);
printf ("%s\n", str);
(*__gmp_free_func) (str, strlen (str) + 1);
}

View File

@@ -0,0 +1,189 @@
/* mpz_export -- create word data from mpz.
Copyright 2002, 2003, 2012 Free Software Foundation, Inc.
This file is part of the GNU MP Library.
The GNU MP Library is free software; you can redistribute it and/or modify
it under the terms of either:
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
or
* the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any
later version.
or both in parallel, as here.
The GNU MP Library 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 copies of the GNU General Public License and the
GNU Lesser General Public License along with the GNU MP Library. If not,
see https://www.gnu.org/licenses/. */
#include <stdio.h> /* for NULL */
#include "gmp-impl.h"
#include "longlong.h"
#if HAVE_LIMB_BIG_ENDIAN
#define HOST_ENDIAN 1
#endif
#if HAVE_LIMB_LITTLE_ENDIAN
#define HOST_ENDIAN (-1)
#endif
#ifndef HOST_ENDIAN
static const mp_limb_t endian_test = (CNST_LIMB(1) << (GMP_LIMB_BITS-7)) - 1;
#define HOST_ENDIAN (* (signed char *) &endian_test)
#endif
void *
mpz_export (void *data, size_t *countp, int order,
size_t size, int endian, size_t nail, mpz_srcptr z)
{
mp_size_t zsize;
mp_srcptr zp;
size_t count, dummy;
unsigned long numb;
unsigned align;
ASSERT (order == 1 || order == -1);
ASSERT (endian == 1 || endian == 0 || endian == -1);
ASSERT (nail <= 8*size);
ASSERT (nail < 8*size || SIZ(z) == 0); /* nail < 8*size+(SIZ(z)==0) */
if (countp == NULL)
countp = &dummy;
zsize = SIZ(z);
if (zsize == 0)
{
*countp = 0;
return data;
}
zsize = ABS (zsize);
zp = PTR(z);
numb = 8*size - nail;
MPN_SIZEINBASE_2EXP (count, zp, zsize, numb);
*countp = count;
if (data == NULL)
data = (*__gmp_allocate_func) (count*size);
if (endian == 0)
endian = HOST_ENDIAN;
align = ((char *) data - (char *) NULL) % sizeof (mp_limb_t);
if (nail == GMP_NAIL_BITS)
{
if (size == sizeof (mp_limb_t) && align == 0)
{
if (order == -1 && endian == HOST_ENDIAN)
{
MPN_COPY ((mp_ptr) data, zp, (mp_size_t) count);
return data;
}
if (order == 1 && endian == HOST_ENDIAN)
{
MPN_REVERSE ((mp_ptr) data, zp, (mp_size_t) count);
return data;
}
if (order == -1 && endian == -HOST_ENDIAN)
{
MPN_BSWAP ((mp_ptr) data, zp, (mp_size_t) count);
return data;
}
if (order == 1 && endian == -HOST_ENDIAN)
{
MPN_BSWAP_REVERSE ((mp_ptr) data, zp, (mp_size_t) count);
return data;
}
}
}
{
mp_limb_t limb, wbitsmask;
size_t i, numb;
mp_size_t j, wbytes, woffset;
unsigned char *dp;
int lbits, wbits;
mp_srcptr zend;
numb = size * 8 - nail;
/* whole bytes per word */
wbytes = numb / 8;
/* possible partial byte */
wbits = numb % 8;
wbitsmask = (CNST_LIMB(1) << wbits) - 1;
/* offset to get to the next word */
woffset = (endian >= 0 ? size : - (mp_size_t) size)
+ (order < 0 ? size : - (mp_size_t) size);
/* least significant byte */
dp = (unsigned char *) data
+ (order >= 0 ? (count-1)*size : 0) + (endian >= 0 ? size-1 : 0);
#define EXTRACT(N, MASK) \
do { \
if (lbits >= (N)) \
{ \
*dp = limb MASK; \
limb >>= (N); \
lbits -= (N); \
} \
else \
{ \
mp_limb_t newlimb; \
newlimb = (zp == zend ? 0 : *zp++); \
*dp = (limb | (newlimb << lbits)) MASK; \
limb = newlimb >> ((N)-lbits); \
lbits += GMP_NUMB_BITS - (N); \
} \
} while (0)
zend = zp + zsize;
lbits = 0;
limb = 0;
for (i = 0; i < count; i++)
{
for (j = 0; j < wbytes; j++)
{
EXTRACT (8, + 0);
dp -= endian;
}
if (wbits != 0)
{
EXTRACT (wbits, & wbitsmask);
dp -= endian;
j++;
}
for ( ; j < size; j++)
{
*dp = '\0';
dp -= endian;
}
dp += woffset;
}
ASSERT (zp == PTR(z) + ABSIZ(z));
/* low byte of word after most significant */
ASSERT (dp == (unsigned char *) data
+ (order < 0 ? count*size : - (mp_size_t) size)
+ (endian >= 0 ? (mp_size_t) size - 1 : 0));
}
return data;
}

View File

@@ -0,0 +1,122 @@
/* mpz_fac_ui(RESULT, N) -- Set RESULT to N!.
Contributed to the GNU project by Marco Bodrato.
Copyright 1991, 1993-1995, 2000-2003, 2011, 2012, 2015, 2021 Free
Software Foundation, Inc.
This file is part of the GNU MP Library.
The GNU MP Library is free software; you can redistribute it and/or modify
it under the terms of either:
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
or
* the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any
later version.
or both in parallel, as here.
The GNU MP Library 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 copies of the GNU General Public License and the
GNU Lesser General Public License along with the GNU MP Library. If not,
see https://www.gnu.org/licenses/. */
#include "gmp-impl.h"
#define FACTOR_LIST_STORE(P, PR, MAX_PR, VEC, I) \
do { \
if ((PR) > (MAX_PR)) { \
(VEC)[(I)++] = (PR); \
(PR) = (P); \
} else \
(PR) *= (P); \
} while (0)
#if TUNE_PROGRAM_BUILD
#define FACTORS_PER_LIMB (GMP_NUMB_BITS / (LOG2C(FAC_DSC_THRESHOLD_LIMIT-1)+1))
#else
#define FACTORS_PER_LIMB (GMP_NUMB_BITS / (LOG2C(FAC_ODD_THRESHOLD)+1))
#endif
/* Computes n!, the factorial of n.
WARNING: it assumes that n fits in a limb!
*/
void
mpz_fac_ui (mpz_ptr x, unsigned long n)
{
static const mp_limb_t table[] = { ONE_LIMB_FACTORIAL_TABLE };
ASSERT (n <= GMP_NUMB_MAX);
if (n < numberof (table))
{
MPZ_NEWALLOC (x, 1)[0] = table[n];
SIZ (x) = 1;
}
else if (BELOW_THRESHOLD (n, FAC_ODD_THRESHOLD))
{
mp_limb_t prod, max_prod;
mp_size_t j;
mp_ptr factors;
mp_limb_t fac, diff = n - numberof (table);
TMP_SDECL;
TMP_SMARK;
factors = TMP_SALLOC_LIMBS (2 + diff / FACTORS_PER_LIMB);
factors[0] = table[numberof (table)-1];
j = 1;
if ((diff & 1) == 0)
{
prod = n;
/* if (diff != 0) */
fac = --n * numberof (table);
}
else
{
prod = n * numberof (table);
fac = prod + --diff;
}
#if TUNE_PROGRAM_BUILD
max_prod = GMP_NUMB_MAX / (FAC_DSC_THRESHOLD_LIMIT * FAC_DSC_THRESHOLD_LIMIT);
#else
max_prod = GMP_NUMB_MAX /
(((FAC_ODD_THRESHOLD + numberof (table) + 1) / 2) *
((FAC_ODD_THRESHOLD + numberof (table)) / 2));
#endif
for (;diff != 0; fac += (diff -= 2))
FACTOR_LIST_STORE (fac, prod, max_prod, factors, j);
factors[j++] = prod;
mpz_prodlimbs (x, factors, j);
TMP_SFREE;
}
else
{
mp_limb_t count;
mpz_oddfac_1 (x, n, 0);
if (n <= TABLE_LIMIT_2N_MINUS_POPC_2N)
count = __gmp_fac2cnt_table[n / 2 - 1];
else
{
popc_limb (count, n);
count = n - count;
}
mpz_mul_2exp (x, x, count);
}
}
#undef FACTORS_PER_LIMB
#undef FACTOR_LIST_STORE

View File

@@ -0,0 +1,52 @@
/* mpz_fdiv_q -- Division rounding the quotient towards -infinity.
The remainder gets the same sign as the denominator.
Copyright 1994-1996, 2000, 2001, 2005, 2012 Free Software Foundation, Inc.
This file is part of the GNU MP Library.
The GNU MP Library is free software; you can redistribute it and/or modify
it under the terms of either:
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
or
* the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any
later version.
or both in parallel, as here.
The GNU MP Library 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 copies of the GNU General Public License and the
GNU Lesser General Public License along with the GNU MP Library. If not,
see https://www.gnu.org/licenses/. */
#include "gmp-impl.h"
void
mpz_fdiv_q (mpz_ptr quot, mpz_srcptr dividend, mpz_srcptr divisor)
{
mp_size_t dividend_size = SIZ (dividend);
mp_size_t divisor_size = SIZ (divisor);
mpz_t rem;
TMP_DECL;
TMP_MARK;
MPZ_TMP_INIT (rem, ABS (divisor_size));
mpz_tdiv_qr (quot, rem, dividend, divisor);
if ((divisor_size ^ dividend_size) < 0 && SIZ (rem) != 0)
mpz_sub_ui (quot, quot, 1L);
TMP_FREE;
}

View File

@@ -0,0 +1,100 @@
/* mpz_fdiv_q_ui -- Division rounding the quotient towards -infinity.
The remainder gets the same sign as the denominator.
Copyright 1994-1996, 1999, 2001, 2002, 2004, 2012 Free Software Foundation,
Inc.
This file is part of the GNU MP Library.
The GNU MP Library is free software; you can redistribute it and/or modify
it under the terms of either:
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
or
* the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any
later version.
or both in parallel, as here.
The GNU MP Library 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 copies of the GNU General Public License and the
GNU Lesser General Public License along with the GNU MP Library. If not,
see https://www.gnu.org/licenses/. */
#include "gmp-impl.h"
unsigned long int
mpz_fdiv_q_ui (mpz_ptr quot, mpz_srcptr dividend, unsigned long int divisor)
{
mp_size_t ns, nn, qn;
mp_ptr np, qp;
mp_limb_t rl;
if (UNLIKELY (divisor == 0))
DIVIDE_BY_ZERO;
ns = SIZ(dividend);
if (ns == 0)
{
SIZ(quot) = 0;
return 0;
}
nn = ABS(ns);
qp = MPZ_REALLOC (quot, nn);
np = PTR(dividend);
#if BITS_PER_ULONG > GMP_NUMB_BITS /* avoid warnings about shift amount */
if (divisor > GMP_NUMB_MAX)
{
mp_limb_t dp[2], rp[2];
if (nn == 1) /* tdiv_qr requirements; tested above for 0 */
{
qp[0] = 0;
rl = np[0];
qn = 1; /* a white lie, fixed below */
}
else
{
dp[0] = divisor & GMP_NUMB_MASK;
dp[1] = divisor >> GMP_NUMB_BITS;
mpn_tdiv_qr (qp, rp, (mp_size_t) 0, np, nn, dp, (mp_size_t) 2);
rl = rp[0] + (rp[1] << GMP_NUMB_BITS);
qn = nn - 2 + 1;
}
if (rl != 0 && ns < 0)
{
mpn_incr_u (qp, (mp_limb_t) 1);
rl = divisor - rl;
}
qn -= qp[qn - 1] == 0; qn -= qn != 0 && qp[qn - 1] == 0;
}
else
#endif
{
rl = mpn_divrem_1 (qp, (mp_size_t) 0, np, nn, (mp_limb_t) divisor);
if (rl != 0 && ns < 0)
{
mpn_incr_u (qp, (mp_limb_t) 1);
rl = divisor - rl;
}
qn = nn - (qp[nn - 1] == 0);
}
SIZ(quot) = ns >= 0 ? qn : -qn;
return rl;
}

View File

@@ -0,0 +1,64 @@
/* mpz_fdiv_qr -- Division rounding the quotient towards -infinity.
The remainder gets the same sign as the denominator.
Copyright 1994-1996, 2000, 2001, 2005, 2012 Free Software Foundation, Inc.
This file is part of the GNU MP Library.
The GNU MP Library is free software; you can redistribute it and/or modify
it under the terms of either:
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
or
* the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any
later version.
or both in parallel, as here.
The GNU MP Library 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 copies of the GNU General Public License and the
GNU Lesser General Public License along with the GNU MP Library. If not,
see https://www.gnu.org/licenses/. */
#include "gmp-impl.h"
void
mpz_fdiv_qr (mpz_ptr quot, mpz_ptr rem, mpz_srcptr dividend, mpz_srcptr divisor)
{
mp_size_t divisor_size = SIZ (divisor);
mp_size_t xsize;
mpz_t temp_divisor; /* N.B.: lives until function returns! */
TMP_DECL;
TMP_MARK;
/* We need the original value of the divisor after the quotient and
remainder have been preliminary calculated. We have to copy it to
temporary space if it's the same variable as either QUOT or REM. */
if (quot == divisor || rem == divisor)
{
MPZ_TMP_INIT (temp_divisor, ABS (divisor_size));
mpz_set (temp_divisor, divisor);
divisor = temp_divisor;
}
xsize = SIZ (dividend) ^ divisor_size;;
mpz_tdiv_qr (quot, rem, dividend, divisor);
if (xsize < 0 && SIZ (rem) != 0)
{
mpz_sub_ui (quot, quot, 1L);
mpz_add (rem, rem, divisor);
}
TMP_FREE;
}

View File

@@ -0,0 +1,116 @@
/* mpz_fdiv_qr_ui -- Division rounding the quotient towards -infinity.
The remainder gets the same sign as the denominator.
Copyright 1994-1996, 1999, 2001, 2002, 2004, 2012, 2015 Free Software
Foundation, Inc.
This file is part of the GNU MP Library.
The GNU MP Library is free software; you can redistribute it and/or modify
it under the terms of either:
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
or
* the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any
later version.
or both in parallel, as here.
The GNU MP Library 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 copies of the GNU General Public License and the
GNU Lesser General Public License along with the GNU MP Library. If not,
see https://www.gnu.org/licenses/. */
#include "gmp-impl.h"
unsigned long int
mpz_fdiv_qr_ui (mpz_ptr quot, mpz_ptr rem, mpz_srcptr dividend, unsigned long int divisor)
{
mp_size_t ns, nn, qn;
mp_ptr np, qp;
mp_limb_t rl;
if (UNLIKELY (divisor == 0))
DIVIDE_BY_ZERO;
ns = SIZ(dividend);
if (ns == 0)
{
SIZ(quot) = 0;
SIZ(rem) = 0;
return 0;
}
nn = ABS(ns);
qp = MPZ_REALLOC (quot, nn);
np = PTR(dividend);
#if BITS_PER_ULONG > GMP_NUMB_BITS /* avoid warnings about shift amount */
if (divisor > GMP_NUMB_MAX)
{
mp_limb_t dp[2];
mp_ptr rp;
mp_size_t rn;
rp = MPZ_REALLOC (rem, 2);
if (nn == 1) /* tdiv_qr requirements; tested above for 0 */
{
qp[0] = 0;
qn = 1; /* a white lie, fixed below */
rl = np[0];
rp[0] = rl;
}
else
{
dp[0] = divisor & GMP_NUMB_MASK;
dp[1] = divisor >> GMP_NUMB_BITS;
mpn_tdiv_qr (qp, rp, (mp_size_t) 0, np, nn, dp, (mp_size_t) 2);
rl = rp[0] + (rp[1] << GMP_NUMB_BITS);
qn = nn - 2 + 1;
}
if (rl != 0 && ns < 0)
{
mpn_incr_u (qp, (mp_limb_t) 1);
rl = divisor - rl;
rp[0] = rl & GMP_NUMB_MASK;
rp[1] = rl >> GMP_NUMB_BITS;
}
qn -= qp[qn - 1] == 0; qn -= qn != 0 && qp[qn - 1] == 0;
rn = 1 + (rl > GMP_NUMB_MAX); rn -= (rp[rn - 1] == 0);
SIZ(rem) = rn;
}
else
#endif
{
rl = mpn_divrem_1 (qp, (mp_size_t) 0, np, nn, (mp_limb_t) divisor);
if (rl == 0)
SIZ(rem) = 0;
else
{
if (ns < 0)
{
mpn_incr_u (qp, (mp_limb_t) 1);
rl = divisor - rl;
}
MPZ_NEWALLOC (rem, 1)[0] = rl;
SIZ(rem) = rl != 0;
}
qn = nn - (qp[nn - 1] == 0);
}
SIZ(quot) = ns >= 0 ? qn : -qn;
return rl;
}

View File

@@ -0,0 +1,59 @@
/* mpz_fdiv_r -- Division rounding the quotient towards -infinity.
The remainder gets the same sign as the denominator.
Copyright 1994-1996, 2001, 2005, 2012 Free Software Foundation, Inc.
This file is part of the GNU MP Library.
The GNU MP Library is free software; you can redistribute it and/or modify
it under the terms of either:
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
or
* the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any
later version.
or both in parallel, as here.
The GNU MP Library 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 copies of the GNU General Public License and the
GNU Lesser General Public License along with the GNU MP Library. If not,
see https://www.gnu.org/licenses/. */
#include "gmp-impl.h"
void
mpz_fdiv_r (mpz_ptr rem, mpz_srcptr dividend, mpz_srcptr divisor)
{
mp_size_t divisor_size = SIZ (divisor);
mpz_t temp_divisor; /* N.B.: lives until function returns! */
TMP_DECL;
TMP_MARK;
/* We need the original value of the divisor after the remainder has been
preliminary calculated. We have to copy it to temporary space if it's
the same variable as REM. */
if (rem == divisor)
{
MPZ_TMP_INIT (temp_divisor, ABS (divisor_size));
mpz_set (temp_divisor, divisor);
divisor = temp_divisor;
}
mpz_tdiv_r (rem, dividend, divisor);
if ((divisor_size ^ SIZ (dividend)) < 0 && SIZ (rem) != 0)
mpz_add (rem, rem, divisor);
TMP_FREE;
}

View File

@@ -0,0 +1,107 @@
/* mpz_fdiv_r_ui -- Division rounding the quotient towards -infinity.
The remainder gets the same sign as the denominator.
Copyright 1994-1996, 2001, 2002, 2004, 2005, 2012, 2015 Free Software
Foundation, Inc.
This file is part of the GNU MP Library.
The GNU MP Library is free software; you can redistribute it and/or modify
it under the terms of either:
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
or
* the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any
later version.
or both in parallel, as here.
The GNU MP Library 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 copies of the GNU General Public License and the
GNU Lesser General Public License along with the GNU MP Library. If not,
see https://www.gnu.org/licenses/. */
#include "gmp-impl.h"
unsigned long int
mpz_fdiv_r_ui (mpz_ptr rem, mpz_srcptr dividend, unsigned long int divisor)
{
mp_size_t ns, nn;
mp_ptr np;
mp_limb_t rl;
if (UNLIKELY (divisor == 0))
DIVIDE_BY_ZERO;
ns = SIZ(dividend);
if (ns == 0)
{
SIZ(rem) = 0;
return 0;
}
nn = ABS(ns);
np = PTR(dividend);
#if BITS_PER_ULONG > GMP_NUMB_BITS /* avoid warnings about shift amount */
if (divisor > GMP_NUMB_MAX)
{
mp_limb_t dp[2];
mp_ptr rp, qp;
mp_size_t rn;
TMP_DECL;
rp = MPZ_REALLOC (rem, 2);
if (nn == 1) /* tdiv_qr requirements; tested above for 0 */
{
rl = np[0];
rp[0] = rl;
}
else
{
TMP_MARK;
dp[0] = divisor & GMP_NUMB_MASK;
dp[1] = divisor >> GMP_NUMB_BITS;
qp = TMP_ALLOC_LIMBS (nn - 2 + 1);
mpn_tdiv_qr (qp, rp, (mp_size_t) 0, np, nn, dp, (mp_size_t) 2);
TMP_FREE;
rl = rp[0] + (rp[1] << GMP_NUMB_BITS);
}
if (rl != 0 && ns < 0)
{
rl = divisor - rl;
rp[0] = rl & GMP_NUMB_MASK;
rp[1] = rl >> GMP_NUMB_BITS;
}
rn = 1 + (rl > GMP_NUMB_MAX); rn -= (rp[rn - 1] == 0);
SIZ(rem) = rn;
}
else
#endif
{
rl = mpn_mod_1 (np, nn, (mp_limb_t) divisor);
if (rl == 0)
SIZ(rem) = 0;
else
{
if (ns < 0)
rl = divisor - rl;
MPZ_NEWALLOC (rem, 1)[0] = rl;
SIZ(rem) = 1;
}
}
return rl;
}

View File

@@ -0,0 +1,100 @@
/* mpz_fdiv_ui -- Division rounding the quotient towards -infinity.
The remainder gets the same sign as the denominator.
Copyright 1994-1996, 2001, 2002, 2004, 2005, 2012 Free Software Foundation,
Inc.
This file is part of the GNU MP Library.
The GNU MP Library is free software; you can redistribute it and/or modify
it under the terms of either:
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
or
* the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any
later version.
or both in parallel, as here.
The GNU MP Library 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 copies of the GNU General Public License and the
GNU Lesser General Public License along with the GNU MP Library. If not,
see https://www.gnu.org/licenses/. */
#include "gmp-impl.h"
unsigned long int
mpz_fdiv_ui (mpz_srcptr dividend, unsigned long int divisor)
{
mp_size_t ns, nn;
mp_ptr np;
mp_limb_t rl;
if (UNLIKELY (divisor == 0))
DIVIDE_BY_ZERO;
ns = SIZ(dividend);
if (ns == 0)
{
return 0;
}
nn = ABS(ns);
np = PTR(dividend);
#if BITS_PER_ULONG > GMP_NUMB_BITS /* avoid warnings about shift amount */
if (divisor > GMP_NUMB_MAX)
{
mp_limb_t dp[2], rp[2];
mp_ptr qp;
mp_size_t rn;
TMP_DECL;
if (nn == 1) /* tdiv_qr requirements; tested above for 0 */
{
rl = np[0];
rp[0] = rl;
}
else
{
TMP_MARK;
dp[0] = divisor & GMP_NUMB_MASK;
dp[1] = divisor >> GMP_NUMB_BITS;
qp = TMP_ALLOC_LIMBS (nn - 2 + 1);
mpn_tdiv_qr (qp, rp, (mp_size_t) 0, np, nn, dp, (mp_size_t) 2);
TMP_FREE;
rl = rp[0] + (rp[1] << GMP_NUMB_BITS);
}
if (rl != 0 && ns < 0)
{
rl = divisor - rl;
rp[0] = rl & GMP_NUMB_MASK;
rp[1] = rl >> GMP_NUMB_BITS;
}
rn = 1 + (rl > GMP_NUMB_MAX); rn -= (rp[rn - 1] == 0);
}
else
#endif
{
rl = mpn_mod_1 (np, nn, (mp_limb_t) divisor);
if (rl == 0)
;
else
{
if (ns < 0)
rl = divisor - rl;
}
}
return rl;
}

View File

@@ -0,0 +1,58 @@
/* mpz_fib2_ui -- calculate Fibonacci numbers.
Copyright 2001, 2012, 2014, 2015 Free Software Foundation, Inc.
This file is part of the GNU MP Library.
The GNU MP Library is free software; you can redistribute it and/or modify
it under the terms of either:
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
or
* the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any
later version.
or both in parallel, as here.
The GNU MP Library 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 copies of the GNU General Public License and the
GNU Lesser General Public License along with the GNU MP Library. If not,
see https://www.gnu.org/licenses/. */
#include <stdio.h>
#include "gmp-impl.h"
void
mpz_fib2_ui (mpz_ptr fn, mpz_ptr fnsub1, unsigned long n)
{
mp_ptr fp, f1p;
mp_size_t size;
if (n <= FIB_TABLE_LIMIT)
{
MPZ_NEWALLOC (fn, 1)[0] = FIB_TABLE (n);
SIZ(fn) = (n != 0); /* F[0]==0, others are !=0 */
MPZ_NEWALLOC (fnsub1, 1)[0] = FIB_TABLE ((int) n - 1);
SIZ(fnsub1) = (n != 1); /* F[1-1]==0, others are !=0 */
return;
}
size = MPN_FIB2_SIZE (n);
fp = MPZ_NEWALLOC (fn, size);
f1p = MPZ_NEWALLOC (fnsub1, size);
size = mpn_fib2_ui (fp, f1p, n);
SIZ(fn) = size;
SIZ(fnsub1) = size - (f1p[size-1] == 0);
}

View File

@@ -0,0 +1,158 @@
/* mpz_fib_ui -- calculate Fibonacci numbers.
Copyright 2000-2002, 2005, 2012, 2014, 2015 Free Software Foundation, Inc.
This file is part of the GNU MP Library.
The GNU MP Library is free software; you can redistribute it and/or modify
it under the terms of either:
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
or
* the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any
later version.
or both in parallel, as here.
The GNU MP Library 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 copies of the GNU General Public License and the
GNU Lesser General Public License along with the GNU MP Library. If not,
see https://www.gnu.org/licenses/. */
#include <stdio.h>
#include "gmp-impl.h"
#include "longlong.h"
/* change to "#define TRACE(x) x" to get some traces */
#define TRACE(x)
/* In the F[2k+1] below for k odd, the -2 won't give a borrow from the low
limb because the result F[2k+1] is an F[4m+3] and such numbers are always
== 1, 2 or 5 mod 8, whereas an underflow would leave 6 or 7. (This is
the same as in mpn_fib2_ui.)
In the F[2k+1] for k even, the +2 won't give a carry out of the low limb
in normal circumstances. This is an F[4m+1] and we claim that F[3*2^b+1]
== 1 mod 2^b is the first F[4m+1] congruent to 0 or 1 mod 2^b, and hence
if n < 2^GMP_NUMB_BITS then F[n] cannot have a low limb of 0 or 1. No
proof for this claim, but it's been verified up to b==32 and has such a
nice pattern it must be true :-). Of interest is that F[3*2^b] == 0 mod
2^(b+1) seems to hold too.
When n >= 2^GMP_NUMB_BITS, which can arise in a nails build, then the low
limb of F[4m+1] can certainly be 1, and an mpn_add_1 must be used. */
void
mpz_fib_ui (mpz_ptr fn, unsigned long n)
{
mp_ptr fp, xp, yp;
mp_size_t size, xalloc;
unsigned long n2;
mp_limb_t c;
TMP_DECL;
if (n <= FIB_TABLE_LIMIT)
{
MPZ_NEWALLOC (fn, 1)[0] = FIB_TABLE (n);
SIZ(fn) = (n != 0); /* F[0]==0, others are !=0 */
return;
}
n2 = n/2;
xalloc = MPN_FIB2_SIZE (n2) + 1;
fp = MPZ_NEWALLOC (fn, 2 * xalloc);
TMP_MARK;
TMP_ALLOC_LIMBS_2 (xp,xalloc, yp,xalloc);
size = mpn_fib2_ui (xp, yp, n2);
TRACE (printf ("mpz_fib_ui last step n=%lu size=%ld bit=%lu\n",
n >> 1, size, n&1);
mpn_trace ("xp", xp, size);
mpn_trace ("yp", yp, size));
if (n & 1)
{
/* F[2k+1] = (2F[k]+F[k-1])*(2F[k]-F[k-1]) + 2*(-1)^k */
mp_size_t xsize, ysize;
#if HAVE_NATIVE_mpn_add_n_sub_n
xp[size] = mpn_lshift (xp, xp, size, 1);
yp[size] = 0;
ASSERT_NOCARRY (mpn_add_n_sub_n (xp, yp, xp, yp, size+1));
xsize = size + (xp[size] != 0);
ASSERT (yp[size] <= 1);
ysize = size + yp[size];
#else
mp_limb_t c2;
c2 = mpn_lshift (fp, xp, size, 1);
c = c2 + mpn_add_n (xp, fp, yp, size);
xp[size] = c;
xsize = size + (c != 0);
c2 -= mpn_sub_n (yp, fp, yp, size);
yp[size] = c2;
ASSERT (c2 <= 1);
ysize = size + c2;
#endif
size = xsize + ysize;
c = mpn_mul (fp, xp, xsize, yp, ysize);
#if GMP_NUMB_BITS >= BITS_PER_ULONG
/* no overflow, see comments above */
ASSERT (n & 2 ? fp[0] >= 2 : fp[0] <= GMP_NUMB_MAX-2);
fp[0] += (n & 2 ? -CNST_LIMB(2) : CNST_LIMB(2));
#else
if (n & 2)
{
ASSERT (fp[0] >= 2);
fp[0] -= 2;
}
else
{
ASSERT (c != GMP_NUMB_MAX); /* because it's the high of a mul */
c += mpn_add_1 (fp, fp, size-1, CNST_LIMB(2));
fp[size-1] = c;
}
#endif
}
else
{
/* F[2k] = F[k]*(F[k]+2F[k-1]) */
mp_size_t xsize, ysize;
#if HAVE_NATIVE_mpn_addlsh1_n
c = mpn_addlsh1_n (yp, xp, yp, size);
#else
c = mpn_lshift (yp, yp, size, 1);
c += mpn_add_n (yp, yp, xp, size);
#endif
yp[size] = c;
xsize = size;
ysize = size + (c != 0);
size += ysize;
c = mpn_mul (fp, yp, ysize, xp, xsize);
}
/* one or two high zeros */
size -= (c == 0);
size -= (fp[size-1] == 0);
SIZ(fn) = size;
TRACE (printf ("done special, size=%ld\n", size);
mpn_trace ("fp ", fp, size));
TMP_FREE;
}

View File

@@ -0,0 +1,60 @@
/* int mpz_fits_X_p (mpz_t z) -- test whether z fits signed type X.
Copyright 1997, 2000-2002 Free Software Foundation, Inc.
This file is part of the GNU MP Library.
The GNU MP Library is free software; you can redistribute it and/or modify
it under the terms of either:
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
or
* the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any
later version.
or both in parallel, as here.
The GNU MP Library 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 copies of the GNU General Public License and the
GNU Lesser General Public License along with the GNU MP Library. If not,
see https://www.gnu.org/licenses/. */
#include "gmp-impl.h"
int
FUNCTION (mpz_srcptr z) __GMP_NOTHROW
{
mp_size_t n = SIZ(z);
mp_ptr p = PTR(z);
mp_limb_t limb = p[0];
if (n == 0)
return 1;
if (n == 1)
return limb <= MAXIMUM;
if (n == -1)
return limb <= NEG_CAST (mp_limb_t, MINIMUM);
#if GMP_NAIL_BITS != 0
{
if ((p[1] >> GMP_NAIL_BITS) == 0)
{
limb += p[1] << GMP_NUMB_BITS;
if (n == 2)
return limb <= MAXIMUM;
if (n == -2)
return limb <= NEG_CAST (mp_limb_t, MINIMUM);
}
}
#endif
return 0;
}

View File

@@ -0,0 +1,36 @@
/* int mpz_fits_sint_p (mpz_t z) -- test whether z fits an int.
Copyright 1997, 2000, 2001 Free Software Foundation, Inc.
This file is part of the GNU MP Library.
The GNU MP Library is free software; you can redistribute it and/or modify
it under the terms of either:
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
or
* the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any
later version.
or both in parallel, as here.
The GNU MP Library 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 copies of the GNU General Public License and the
GNU Lesser General Public License along with the GNU MP Library. If not,
see https://www.gnu.org/licenses/. */
#define FUNCTION mpz_fits_sint_p
#define MAXIMUM INT_MAX
#define MINIMUM INT_MIN
#include "fits_s.h"

View File

@@ -0,0 +1,36 @@
/* int mpz_fits_slong_p (mpz_t z) -- test whether z fits a long.
Copyright 1997, 2000, 2001 Free Software Foundation, Inc.
This file is part of the GNU MP Library.
The GNU MP Library is free software; you can redistribute it and/or modify
it under the terms of either:
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
or
* the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any
later version.
or both in parallel, as here.
The GNU MP Library 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 copies of the GNU General Public License and the
GNU Lesser General Public License along with the GNU MP Library. If not,
see https://www.gnu.org/licenses/. */
#define FUNCTION mpz_fits_slong_p
#define MAXIMUM LONG_MAX
#define MINIMUM LONG_MIN
#include "fits_s.h"

View File

@@ -0,0 +1,36 @@
/* int mpz_fits_sshort_p (mpz_t z) -- test whether z fits a short.
Copyright 1997, 2000, 2001 Free Software Foundation, Inc.
This file is part of the GNU MP Library.
The GNU MP Library is free software; you can redistribute it and/or modify
it under the terms of either:
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
or
* the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any
later version.
or both in parallel, as here.
The GNU MP Library 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 copies of the GNU General Public License and the
GNU Lesser General Public License along with the GNU MP Library. If not,
see https://www.gnu.org/licenses/. */
#define FUNCTION mpz_fits_sshort_p
#define MAXIMUM SHRT_MAX
#define MINIMUM SHRT_MIN
#include "fits_s.h"

View File

@@ -0,0 +1,33 @@
/* mpz_fits_uint_p -- test whether z fits an unsigned int.
Copyright 1997, 2000, 2001 Free Software Foundation, Inc.
This file is part of the GNU MP Library.
The GNU MP Library is free software; you can redistribute it and/or modify
it under the terms of either:
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
or
* the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any
later version.
or both in parallel, as here.
The GNU MP Library 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 copies of the GNU General Public License and the
GNU Lesser General Public License along with the GNU MP Library. If not,
see https://www.gnu.org/licenses/. */
#define __GMP_FORCE_mpz_fits_uint_p 1
#include "gmp-impl.h"

View File

@@ -0,0 +1,33 @@
/* mpz_fits_ulong_p -- test whether z fits an unsigned long.
Copyright 1997, 2000, 2001 Free Software Foundation, Inc.
This file is part of the GNU MP Library.
The GNU MP Library is free software; you can redistribute it and/or modify
it under the terms of either:
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
or
* the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any
later version.
or both in parallel, as here.
The GNU MP Library 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 copies of the GNU General Public License and the
GNU Lesser General Public License along with the GNU MP Library. If not,
see https://www.gnu.org/licenses/. */
#define __GMP_FORCE_mpz_fits_ulong_p 1
#include "gmp-impl.h"

View File

@@ -0,0 +1,33 @@
/* mpz_fits_ushort_p -- test whether z fits an unsigned short.
Copyright 1997, 2000, 2001 Free Software Foundation, Inc.
This file is part of the GNU MP Library.
The GNU MP Library is free software; you can redistribute it and/or modify
it under the terms of either:
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
or
* the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any
later version.
or both in parallel, as here.
The GNU MP Library 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 copies of the GNU General Public License and the
GNU Lesser General Public License along with the GNU MP Library. If not,
see https://www.gnu.org/licenses/. */
#define __GMP_FORCE_mpz_fits_ushort_p 1
#include "gmp-impl.h"

View File

@@ -0,0 +1,164 @@
/* mpz/gcd.c: Calculate the greatest common divisor of two integers.
Copyright 1991, 1993, 1994, 1996, 2000-2002, 2005, 2010, 2015, 2016
Free Software Foundation, Inc.
This file is part of the GNU MP Library.
The GNU MP Library is free software; you can redistribute it and/or modify
it under the terms of either:
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
or
* the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any
later version.
or both in parallel, as here.
The GNU MP Library 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 copies of the GNU General Public License and the
GNU Lesser General Public License along with the GNU MP Library. If not,
see https://www.gnu.org/licenses/. */
#include "gmp-impl.h"
#include "longlong.h"
void
mpz_gcd (mpz_ptr g, mpz_srcptr u, mpz_srcptr v)
{
unsigned long int g_zero_bits, u_zero_bits, v_zero_bits;
mp_size_t g_zero_limbs, u_zero_limbs, v_zero_limbs;
mp_ptr tp;
mp_ptr up;
mp_size_t usize;
mp_ptr vp;
mp_size_t vsize;
mp_size_t gsize;
TMP_DECL;
up = PTR(u);
usize = ABSIZ (u);
vp = PTR(v);
vsize = ABSIZ (v);
/* GCD(0, V) == V. */
if (usize == 0)
{
SIZ (g) = vsize;
if (g == v)
return;
tp = MPZ_NEWALLOC (g, vsize);
MPN_COPY (tp, vp, vsize);
return;
}
/* GCD(U, 0) == U. */
if (vsize == 0)
{
SIZ (g) = usize;
if (g == u)
return;
tp = MPZ_NEWALLOC (g, usize);
MPN_COPY (tp, up, usize);
return;
}
if (usize == 1)
{
SIZ (g) = 1;
MPZ_NEWALLOC (g, 1)[0] = mpn_gcd_1 (vp, vsize, up[0]);
return;
}
if (vsize == 1)
{
SIZ(g) = 1;
MPZ_NEWALLOC (g, 1)[0] = mpn_gcd_1 (up, usize, vp[0]);
return;
}
TMP_MARK;
/* Eliminate low zero bits from U and V and move to temporary storage. */
tp = up;
while (*tp == 0)
tp++;
u_zero_limbs = tp - up;
usize -= u_zero_limbs;
count_trailing_zeros (u_zero_bits, *tp);
up = TMP_ALLOC_LIMBS (usize);
if (u_zero_bits != 0)
{
mpn_rshift (up, tp, usize, u_zero_bits);
usize -= up[usize - 1] == 0;
}
else
MPN_COPY (up, tp, usize);
tp = vp;
while (*tp == 0)
tp++;
v_zero_limbs = tp - vp;
vsize -= v_zero_limbs;
count_trailing_zeros (v_zero_bits, *tp);
vp = TMP_ALLOC_LIMBS (vsize);
if (v_zero_bits != 0)
{
mpn_rshift (vp, tp, vsize, v_zero_bits);
vsize -= vp[vsize - 1] == 0;
}
else
MPN_COPY (vp, tp, vsize);
if (u_zero_limbs > v_zero_limbs)
{
g_zero_limbs = v_zero_limbs;
g_zero_bits = v_zero_bits;
}
else
{
g_zero_limbs = u_zero_limbs;
if (u_zero_limbs < v_zero_limbs)
g_zero_bits = u_zero_bits;
else /* Equal. */
g_zero_bits = MIN (u_zero_bits, v_zero_bits);
}
/* Call mpn_gcd. The 2nd argument must not have more bits than the 1st. */
vsize = (usize < vsize || (usize == vsize && up[usize-1] < vp[vsize-1]))
? mpn_gcd (vp, vp, vsize, up, usize)
: mpn_gcd (vp, up, usize, vp, vsize);
/* Here G <-- V << (g_zero_limbs*GMP_LIMB_BITS + g_zero_bits). */
gsize = vsize + g_zero_limbs;
if (g_zero_bits != 0)
{
mp_limb_t cy_limb;
gsize += (vp[vsize - 1] >> (GMP_NUMB_BITS - g_zero_bits)) != 0;
tp = MPZ_NEWALLOC (g, gsize);
MPN_ZERO (tp, g_zero_limbs);
tp = tp + g_zero_limbs;
cy_limb = mpn_lshift (tp, vp, vsize, g_zero_bits);
if (cy_limb != 0)
tp[vsize] = cy_limb;
}
else
{
tp = MPZ_NEWALLOC (g, gsize);
MPN_ZERO (tp, g_zero_limbs);
MPN_COPY (tp + g_zero_limbs, vp, vsize);
}
SIZ (g) = gsize;
TMP_FREE;
}

View File

@@ -0,0 +1,92 @@
/* mpz_gcd_ui -- Calculate the greatest common divisor of two integers.
Copyright 1994, 1996, 1999-2004, 2015, 2022 Free Software Foundation, Inc.
This file is part of the GNU MP Library.
The GNU MP Library is free software; you can redistribute it and/or modify
it under the terms of either:
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
or
* the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any
later version.
or both in parallel, as here.
The GNU MP Library 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 copies of the GNU General Public License and the
GNU Lesser General Public License along with the GNU MP Library. If not,
see https://www.gnu.org/licenses/. */
#include <stdio.h> /* for NULL */
#include "gmp-impl.h"
unsigned long int
mpz_gcd_ui (mpz_ptr w, mpz_srcptr u, unsigned long int v)
{
mp_size_t un;
mp_limb_t res;
#if BITS_PER_ULONG > GMP_NUMB_BITS /* avoid warnings about shift amount */
if (v > GMP_NUMB_MAX)
{
mpz_t vz, lw;
mp_limb_t vlimbs[2], wlimbs[2];
if (w == NULL)
{
PTR(lw) = wlimbs;
ALLOC(lw) = 2;
SIZ(lw) = 0;
w = lw;
}
vlimbs[0] = v & GMP_NUMB_MASK;
vlimbs[1] = v >> GMP_NUMB_BITS;
PTR(vz) = vlimbs;
SIZ(vz) = 2;
mpz_gcd (w, u, vz);
/* because v!=0 we will have w<=v hence fitting a ulong */
ASSERT (mpz_fits_ulong_p (w));
return mpz_get_ui (w);
}
#endif
un = ABSIZ(u);
if (un == 0)
res = v;
else if (v == 0)
{
if (w != NULL)
{
if (u != w)
{
MPZ_NEWALLOC (w, un);
MPN_COPY (PTR(w), PTR(u), un);
}
SIZ(w) = un;
}
/* Return u if it fits a ulong, otherwise 0. */
res = PTR(u)[0];
return (un == 1 && res <= ULONG_MAX ? res : 0);
}
else
res = mpn_gcd_1 (PTR(u), un, (mp_limb_t) v);
if (w != NULL)
{
MPZ_NEWALLOC (w, 1)[0] = res;
SIZ(w) = res != 0;
}
return res;
}

View File

@@ -0,0 +1,135 @@
/* mpz_gcdext(g, s, t, a, b) -- Set G to gcd(a, b), and S and T such that
g = as + bt.
Copyright 1991, 1993-1997, 2000, 2001, 2005, 2011, 2012, 2015 Free
Software Foundation, Inc.
This file is part of the GNU MP Library.
The GNU MP Library is free software; you can redistribute it and/or modify
it under the terms of either:
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
or
* the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any
later version.
or both in parallel, as here.
The GNU MP Library 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 copies of the GNU General Public License and the
GNU Lesser General Public License along with the GNU MP Library. If not,
see https://www.gnu.org/licenses/. */
#include <stdio.h> /* for NULL */
#include "gmp-impl.h"
void
mpz_gcdext (mpz_ptr g, mpz_ptr s, mpz_ptr t, mpz_srcptr a, mpz_srcptr b)
{
mp_size_t asize, bsize;
mp_ptr tmp_ap, tmp_bp;
mp_size_t gsize, ssize, tmp_ssize;
mp_ptr gp, tmp_gp, tmp_sp;
TMP_DECL;
/* mpn_gcdext requires that Usize >= Vsize. Therefore, we often
have to swap U and V. The computed cofactor will be the
"smallest" one, which is faster to produce. The wanted one will
be computed here; this is needed anyway when both are requested. */
asize = ABSIZ (a);
bsize = ABSIZ (b);
ASSERT (s != NULL);
if (asize < bsize)
{
MPZ_SRCPTR_SWAP (a, b);
MP_SIZE_T_SWAP (asize, bsize);
MPZ_PTR_SWAP (s, t);
}
if (bsize == 0)
{
/* g = |a|, s = sgn(a), t = 0. */
ssize = SIZ (a) >= 0 ? (asize != 0) : -1;
if (g != NULL)
{
/* If g == a, then ALLOC(g) == ALLOC(a) >= asize, i.e.
the next MPZ_NEWALLOC returns the old PTR(a) .*/
gp = MPZ_NEWALLOC (g, asize);
MPN_COPY (gp, PTR (a), asize);
SIZ (g) = asize;
}
if (t != NULL)
SIZ (t) = 0;
if (s != NULL)
{
SIZ (s) = ssize;
MPZ_NEWALLOC (s, 1)[0] = 1;
}
return;
}
TMP_MARK;
TMP_ALLOC_LIMBS_2 (tmp_gp, bsize, tmp_sp, asize + bsize + bsize + 1);
tmp_bp = tmp_sp + bsize + 1;
tmp_ap = tmp_bp + bsize;
MPN_COPY (tmp_ap, PTR (a), asize);
MPN_COPY (tmp_bp, PTR (b), bsize);
gsize = mpn_gcdext (tmp_gp, tmp_sp, &tmp_ssize, tmp_ap, asize, tmp_bp, bsize);
ssize = ABS (tmp_ssize);
tmp_ssize = SIZ (a) >= 0 ? tmp_ssize : -tmp_ssize;
if (t != NULL)
{
mpz_t x;
mpz_t gtmp, stmp;
PTR (gtmp) = tmp_gp;
SIZ (gtmp) = gsize;
PTR (stmp) = tmp_sp;
SIZ (stmp) = tmp_ssize;
ASSERT (ssize <= bsize); /* ssize*2 + asize + 1 <= asize + bsize*2 + 1 */
PTR (x) = tmp_sp + ssize;
ALLOC (x) = ssize + asize + 1;
mpz_mul (x, stmp, a);
mpz_sub (x, gtmp, x);
mpz_divexact (t, x, b);
}
if (s != NULL)
{
mp_ptr sp;
sp = MPZ_NEWALLOC (s, ssize);
MPN_COPY (sp, tmp_sp, ssize);
SIZ (s) = tmp_ssize;
}
if (g != NULL)
{
gp = MPZ_NEWALLOC (g, gsize);
MPN_COPY (gp, tmp_gp, gsize);
SIZ (g) = gsize;
}
TMP_FREE;
}

View File

@@ -0,0 +1,43 @@
/* double mpz_get_d (mpz_t src) -- Return the double approximation to SRC.
Copyright 1996, 1997, 2000-2003 Free Software Foundation, Inc.
This file is part of the GNU MP Library.
The GNU MP Library is free software; you can redistribute it and/or modify
it under the terms of either:
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
or
* the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any
later version.
or both in parallel, as here.
The GNU MP Library 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 copies of the GNU General Public License and the
GNU Lesser General Public License along with the GNU MP Library. If not,
see https://www.gnu.org/licenses/. */
#include "gmp-impl.h"
double
mpz_get_d (mpz_srcptr z)
{
mp_size_t size;
size = SIZ (z);
if (UNLIKELY (size == 0))
return 0.0;
return mpn_get_d (PTR (z), ABS (size), size, 0L);
}

View File

@@ -0,0 +1,53 @@
/* double mpz_get_d_2exp (signed long int *exp, mpz_t src).
Copyright 2001, 2003, 2004, 2012 Free Software Foundation, Inc.
This file is part of the GNU MP Library.
The GNU MP Library is free software; you can redistribute it and/or modify
it under the terms of either:
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
or
* the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any
later version.
or both in parallel, as here.
The GNU MP Library 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 copies of the GNU General Public License and the
GNU Lesser General Public License along with the GNU MP Library. If not,
see https://www.gnu.org/licenses/. */
#include "gmp-impl.h"
#include "longlong.h"
double
mpz_get_d_2exp (signed long int *exp2, mpz_srcptr src)
{
mp_size_t size, abs_size;
mp_srcptr ptr;
long exp;
size = SIZ(src);
if (UNLIKELY (size == 0))
{
*exp2 = 0;
return 0.0;
}
ptr = PTR(src);
abs_size = ABS(size);
MPN_SIZEINBASE_2EXP(exp, ptr, abs_size, 1);
*exp2 = exp;
return mpn_get_d (ptr, abs_size, size, -exp);
}

View File

@@ -0,0 +1,52 @@
/* mpz_get_si(integer) -- Return the least significant digit from INTEGER.
Copyright 1991, 1993-1995, 2000-2002, 2006, 2012 Free Software Foundation, Inc.
This file is part of the GNU MP Library.
The GNU MP Library is free software; you can redistribute it and/or modify
it under the terms of either:
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
or
* the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any
later version.
or both in parallel, as here.
The GNU MP Library 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 copies of the GNU General Public License and the
GNU Lesser General Public License along with the GNU MP Library. If not,
see https://www.gnu.org/licenses/. */
#include "gmp-impl.h"
signed long int
mpz_get_si (mpz_srcptr z) __GMP_NOTHROW
{
mp_ptr zp = PTR (z);
mp_size_t size = SIZ (z);
mp_limb_t zl = zp[0];
#if GMP_NAIL_BITS != 0
if (ULONG_MAX > GMP_NUMB_MAX && ABS (size) >= 2)
zl |= zp[1] << GMP_NUMB_BITS;
#endif
if (size > 0)
return zl & LONG_MAX;
else if (size < 0)
/* This expression is necessary to properly handle 0x80000000 */
return -1 - (long) ((zl - 1) & LONG_MAX);
else
return 0;
}

View File

@@ -0,0 +1,115 @@
/* mpz_get_str (string, base, mp_src) -- Convert the multiple precision
number MP_SRC to a string STRING of base BASE. If STRING is NULL
allocate space for the result. In any case, return a pointer to the
result. If STRING is not NULL, the caller must ensure enough space is
available to store the result.
Copyright 1991, 1993, 1994, 1996, 2000-2002, 2005, 2012, 2017 Free
Software Foundation, Inc.
This file is part of the GNU MP Library.
The GNU MP Library is free software; you can redistribute it and/or modify
it under the terms of either:
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
or
* the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any
later version.
or both in parallel, as here.
The GNU MP Library 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 copies of the GNU General Public License and the
GNU Lesser General Public License along with the GNU MP Library. If not,
see https://www.gnu.org/licenses/. */
#include <string.h> /* for strlen */
#include "gmp-impl.h"
#include "longlong.h"
char *
mpz_get_str (char *res_str, int base, mpz_srcptr x)
{
mp_ptr xp;
mp_size_t x_size = SIZ (x);
char *return_str;
size_t str_size;
size_t alloc_size = 0;
const char *num_to_text;
int i;
TMP_DECL;
num_to_text = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
if (base > 1)
{
if (base <= 36)
num_to_text = "0123456789abcdefghijklmnopqrstuvwxyz";
else if (UNLIKELY (base > 62))
return NULL;
}
else if (base > -2)
{
base = 10;
}
else
{
base = -base;
if (UNLIKELY (base > 36))
return NULL;
}
/* allocate string for the user if necessary */
if (res_str == NULL)
{
/* digits, null terminator, possible minus sign */
MPN_SIZEINBASE (alloc_size, PTR(x), ABS(x_size), base);
alloc_size += 1 + (x_size<0);
res_str = __GMP_ALLOCATE_FUNC_TYPE (alloc_size, char);
}
return_str = res_str;
if (x_size < 0)
{
*res_str++ = '-';
x_size = -x_size;
}
/* mpn_get_str clobbers its input on non power-of-2 bases */
TMP_MARK;
xp = PTR (x);
if (! POW2_P (base))
{
xp = TMP_ALLOC_LIMBS (x_size | 1); /* |1 in case x_size==0 */
MPN_COPY (xp, PTR (x), x_size);
}
str_size = mpn_get_str ((unsigned char *) res_str, base, xp, x_size);
ASSERT (alloc_size == 0 || str_size <= alloc_size - (SIZ(x) < 0));
/* Convert result to printable chars. */
for (i = 0; i < str_size; i++)
res_str[i] = num_to_text[(int) res_str[i]];
res_str[str_size] = 0;
TMP_FREE;
/* if allocated then resize down to the actual space required */
if (alloc_size != 0)
{
size_t actual_size = str_size + 1 + (res_str - return_str);
ASSERT (actual_size == strlen (return_str) + 1);
__GMP_REALLOCATE_FUNC_MAYBE_TYPE (return_str, alloc_size, actual_size,
char);
}
return return_str;
}

View File

@@ -0,0 +1,33 @@
/* mpz_get_ui(integer) -- Return the least significant digit from INTEGER.
Copyright 1991, 1993-1995, 2001 Free Software Foundation, Inc.
This file is part of the GNU MP Library.
The GNU MP Library is free software; you can redistribute it and/or modify
it under the terms of either:
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
or
* the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any
later version.
or both in parallel, as here.
The GNU MP Library 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 copies of the GNU General Public License and the
GNU Lesser General Public License along with the GNU MP Library. If not,
see https://www.gnu.org/licenses/. */
#define __GMP_FORCE_mpz_get_ui 1
#include "gmp-impl.h"

View File

@@ -0,0 +1,33 @@
/* mpz_getlimbn(integer,n) -- Return the N:th limb from INTEGER.
Copyright 1993-1996, 2001 Free Software Foundation, Inc.
This file is part of the GNU MP Library.
The GNU MP Library is free software; you can redistribute it and/or modify
it under the terms of either:
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
or
* the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any
later version.
or both in parallel, as here.
The GNU MP Library 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 copies of the GNU General Public License and the
GNU Lesser General Public License along with the GNU MP Library. If not,
see https://www.gnu.org/licenses/. */
#define __GMP_FORCE_mpz_getlimbn 1
#include "gmp-impl.h"

View File

@@ -0,0 +1,174 @@
/* mpz_hamdist -- calculate hamming distance.
Copyright 1994, 1996, 2001, 2002, 2009-2011 Free Software Foundation, Inc.
This file is part of the GNU MP Library.
The GNU MP Library is free software; you can redistribute it and/or modify
it under the terms of either:
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
or
* the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any
later version.
or both in parallel, as here.
The GNU MP Library 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 copies of the GNU General Public License and the
GNU Lesser General Public License along with the GNU MP Library. If not,
see https://www.gnu.org/licenses/. */
#include "gmp-impl.h"
mp_bitcnt_t
mpz_hamdist (mpz_srcptr u, mpz_srcptr v) __GMP_NOTHROW
{
mp_srcptr up, vp;
mp_size_t usize, vsize;
mp_bitcnt_t count;
usize = SIZ(u);
vsize = SIZ(v);
up = PTR(u);
vp = PTR(v);
if (usize >= 0)
{
if (vsize < 0)
return ~ (mp_bitcnt_t) 0;
/* positive/positive */
if (usize < vsize)
MPN_SRCPTR_SWAP (up,usize, vp,vsize);
count = 0;
if (vsize != 0)
count = mpn_hamdist (up, vp, vsize);
usize -= vsize;
if (usize != 0)
count += mpn_popcount (up + vsize, usize);
return count;
}
else
{
mp_limb_t ulimb, vlimb;
mp_size_t old_vsize, step;
if (vsize >= 0)
return ~ (mp_bitcnt_t) 0;
/* negative/negative */
usize = -usize;
vsize = -vsize;
/* skip common low zeros */
for (;;)
{
ASSERT (usize > 0);
ASSERT (vsize > 0);
usize--;
vsize--;
ulimb = *up++;
vlimb = *vp++;
if (ulimb != 0)
break;
if (vlimb != 0)
{
MPN_SRCPTR_SWAP (up,usize, vp,vsize);
ulimb = vlimb;
vlimb = 0;
break;
}
}
/* twos complement first non-zero limbs (ulimb is non-zero, but vlimb
might be zero) */
ulimb = -ulimb;
vlimb = -vlimb;
popc_limb (count, (ulimb ^ vlimb) & GMP_NUMB_MASK);
if (vlimb == 0)
{
mp_bitcnt_t twoscount;
/* first non-zero of v */
old_vsize = vsize;
do
{
ASSERT (vsize > 0);
vsize--;
vlimb = *vp++;
}
while (vlimb == 0);
/* part of u corresponding to skipped v zeros */
step = old_vsize - vsize - 1;
count += step * GMP_NUMB_BITS;
step = MIN (step, usize);
if (step != 0)
{
count -= mpn_popcount (up, step);
usize -= step;
up += step;
}
/* First non-zero vlimb as twos complement, xor with ones
complement ulimb. Note -v^(~0^u) == (v-1)^u. */
vlimb--;
if (usize != 0)
{
usize--;
vlimb ^= *up++;
}
popc_limb (twoscount, vlimb);
count += twoscount;
}
/* Overlapping part of u and v, if any. Ones complement both, so just
plain hamdist. */
step = MIN (usize, vsize);
if (step != 0)
{
count += mpn_hamdist (up, vp, step);
usize -= step;
vsize -= step;
up += step;
vp += step;
}
/* Remaining high part of u or v, if any, ones complement but xor
against all ones in the other, so plain popcount. */
if (usize != 0)
{
remaining:
count += mpn_popcount (up, usize);
}
else if (vsize != 0)
{
up = vp;
usize = vsize;
goto remaining;
}
return count;
}
}

View File

@@ -0,0 +1,166 @@
/* mpz_import -- set mpz from word data.
Copyright 2002, 2012, 2021, 2022 Free Software Foundation, Inc.
This file is part of the GNU MP Library.
The GNU MP Library is free software; you can redistribute it and/or modify
it under the terms of either:
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
or
* the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any
later version.
or both in parallel, as here.
The GNU MP Library 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 copies of the GNU General Public License and the
GNU Lesser General Public License along with the GNU MP Library. If not,
see https://www.gnu.org/licenses/. */
#include <stdio.h>
#include "gmp-impl.h"
#if HAVE_LIMB_BIG_ENDIAN
#define HOST_ENDIAN 1
#endif
#if HAVE_LIMB_LITTLE_ENDIAN
#define HOST_ENDIAN (-1)
#endif
#ifndef HOST_ENDIAN
static const mp_limb_t endian_test = (CNST_LIMB(1) << (GMP_LIMB_BITS-7)) - 1;
#define HOST_ENDIAN (* (signed char *) &endian_test)
#endif
void
mpz_import (mpz_ptr z, size_t count, int order,
size_t size, int endian, size_t nail, const void *data)
{
mp_size_t zsize;
mp_ptr zp;
ASSERT (order == 1 || order == -1);
ASSERT (endian == 1 || endian == 0 || endian == -1);
ASSERT (nail <= 8*size);
zsize = BITS_TO_LIMBS (count * (8*size - nail));
zp = MPZ_NEWALLOC (z, zsize);
if (endian == 0)
endian = HOST_ENDIAN;
/* Can't use these special cases with nails currently, since they don't
mask out the nail bits in the input data. */
if (nail == 0 && GMP_NAIL_BITS == 0
&& size == sizeof (mp_limb_t)
&& (((char *) data - (char *) NULL) % sizeof (mp_limb_t)) == 0 /* align */)
{
if (order == -1)
{
if (endian == HOST_ENDIAN)
MPN_COPY (zp, (mp_srcptr) data, (mp_size_t) count);
else /* if (endian == - HOST_ENDIAN) */
MPN_BSWAP (zp, (mp_srcptr) data, (mp_size_t) count);
}
else /* if (order == 1) */
{
if (endian == HOST_ENDIAN)
MPN_REVERSE (zp, (mp_srcptr) data, (mp_size_t) count);
else /* if (endian == - HOST_ENDIAN) */
MPN_BSWAP_REVERSE (zp, (mp_srcptr) data, (mp_size_t) count);
}
}
else
{
mp_limb_t limb, byte, wbitsmask;
size_t i, j, numb, wbytes;
mp_size_t woffset;
unsigned char *dp;
int lbits, wbits;
numb = size * 8 - nail;
/* whole bytes to process */
wbytes = numb / 8;
/* partial byte to process */
wbits = numb % 8;
wbitsmask = (CNST_LIMB(1) << wbits) - 1;
/* offset to get to the next word after processing wbytes and wbits */
woffset = (numb + 7) / 8;
woffset = (endian >= 0 ? woffset : -woffset)
+ (order < 0 ? size : - (mp_size_t) size);
/* least significant byte */
dp = (unsigned char *) data
+ (order >= 0 ? (count-1)*size : 0) + (endian >= 0 ? size-1 : 0);
#define ACCUMULATE(N) \
do { \
ASSERT (lbits < GMP_NUMB_BITS); \
ASSERT (limb <= (CNST_LIMB(1) << lbits) - 1); \
\
limb |= (mp_limb_t) byte << lbits; \
lbits += (N); \
if (lbits >= GMP_NUMB_BITS) \
{ \
*zp++ = limb & GMP_NUMB_MASK; \
lbits -= GMP_NUMB_BITS; \
ASSERT (lbits < (N)); \
limb = byte >> ((N) - lbits); \
} \
} while (0)
limb = 0;
lbits = 0;
for (i = 0; i < count; i++)
{
for (j = 0; j < wbytes; j++)
{
byte = *dp;
dp -= endian;
ACCUMULATE (8);
}
if (wbits != 0)
{
byte = *dp & wbitsmask;
dp -= endian;
ACCUMULATE (wbits);
}
dp += woffset;
}
if (lbits != 0)
{
ASSERT (lbits <= GMP_NUMB_BITS);
ASSERT_LIMB (limb);
*zp++ = limb;
}
ASSERT (zp == PTR(z) + zsize);
/* low byte of word after most significant */
ASSERT (dp == (unsigned char *) data
+ (order < 0 ? count*size : - (mp_size_t) size)
+ (endian >= 0 ? (mp_size_t) size - 1 : 0));
}
zp = PTR(z);
MPN_NORMALIZE (zp, zsize);
SIZ(z) = zsize;
}

View File

@@ -0,0 +1,41 @@
/* mpz_init() -- Make a new multiple precision number with value 0.
Copyright 1991, 1993-1995, 2000-2002, 2012, 2015 Free Software
Foundation, Inc.
This file is part of the GNU MP Library.
The GNU MP Library is free software; you can redistribute it and/or modify
it under the terms of either:
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
or
* the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any
later version.
or both in parallel, as here.
The GNU MP Library 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 copies of the GNU General Public License and the
GNU Lesser General Public License along with the GNU MP Library. If not,
see https://www.gnu.org/licenses/. */
#include "gmp-impl.h"
void
mpz_init (mpz_ptr x) __GMP_NOTHROW
{
static const mp_limb_t dummy_limb=0xc1a0;
ALLOC (x) = 0;
PTR (x) = (mp_ptr) &dummy_limb;
SIZ (x) = 0;
}

View File

@@ -0,0 +1,50 @@
/* mpz_init2 -- initialize mpz, with requested size in bits.
Copyright 2001, 2002, 2008, 2021, 2022 Free Software Foundation, Inc.
This file is part of the GNU MP Library.
The GNU MP Library is free software; you can redistribute it and/or modify
it under the terms of either:
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
or
* the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any
later version.
or both in parallel, as here.
The GNU MP Library 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 copies of the GNU General Public License and the
GNU Lesser General Public License along with the GNU MP Library. If not,
see https://www.gnu.org/licenses/. */
#include "gmp-impl.h"
void
mpz_init2 (mpz_ptr x, mp_bitcnt_t bits)
{
mp_size_t new_alloc;
bits -= (bits != 0); /* Round down, except if 0 */
new_alloc = 1 + bits / GMP_NUMB_BITS;
if (sizeof (unsigned long) > sizeof (int)) /* param vs _mp_size field */
{
if (UNLIKELY (new_alloc > INT_MAX))
MPZ_OVERFLOW;
}
PTR(x) = __GMP_ALLOCATE_FUNC_LIMBS (new_alloc);
ALLOC(x) = new_alloc;
SIZ(x) = 0;
}

View File

@@ -0,0 +1,53 @@
/* mpz_inits() -- Initialize multiple mpz_t variables and set them to 0.
Copyright 2009, 2015 Free Software Foundation, Inc.
This file is part of the GNU MP Library.
The GNU MP Library is free software; you can redistribute it and/or modify
it under the terms of either:
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
or
* the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any
later version.
or both in parallel, as here.
The GNU MP Library 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 copies of the GNU General Public License and the
GNU Lesser General Public License along with the GNU MP Library. If not,
see https://www.gnu.org/licenses/. */
#include <stdarg.h>
#include "gmp-impl.h"
void
mpz_inits (mpz_ptr x, ...) __GMP_NOTHROW
{
static const mp_limb_t dummy_limb=0xc1a0;
va_list ap;
va_start (ap, x);
do
{
ALLOC (x) = 0;
PTR (x) = (mp_ptr) &dummy_limb;
SIZ (x) = 0;
x = va_arg (ap, mpz_ptr);
}
while (x != NULL);
va_end (ap);
}

View File

@@ -0,0 +1,172 @@
/* mpz_inp_raw -- read an mpz_t in raw format.
Copyright 2001, 2002, 2005, 2012, 2016, 2021 Free Software Foundation, Inc.
This file is part of the GNU MP Library.
The GNU MP Library is free software; you can redistribute it and/or modify
it under the terms of either:
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
or
* the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any
later version.
or both in parallel, as here.
The GNU MP Library 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 copies of the GNU General Public License and the
GNU Lesser General Public License along with the GNU MP Library. If not,
see https://www.gnu.org/licenses/. */
#include <stdio.h>
#include "gmp-impl.h"
/* NTOH_LIMB_FETCH fetches a limb which is in network byte order (ie. big
endian) and produces a normal host byte order result. */
#if HAVE_LIMB_BIG_ENDIAN
#define NTOH_LIMB_FETCH(limb, src) do { (limb) = *(src); } while (0)
#endif
#if HAVE_LIMB_LITTLE_ENDIAN
#define NTOH_LIMB_FETCH(limb, src) BSWAP_LIMB_FETCH (limb, src)
#endif
#ifndef NTOH_LIMB_FETCH
#define NTOH_LIMB_FETCH(limb, src) \
do { \
const unsigned char *__p = (const unsigned char *) (src); \
mp_limb_t __limb; \
int __i; \
__limb = 0; \
for (__i = 0; __i < GMP_LIMB_BYTES; __i++) \
__limb = (__limb << 8) | __p[__i]; \
(limb) = __limb; \
} while (0)
#endif
/* Enhancement: The byte swap loop ought to be safe to vectorize on Cray
etc, but someone who knows what they're doing needs to check it. */
size_t
mpz_inp_raw (mpz_ptr x, FILE *fp)
{
unsigned char csize_bytes[4];
mp_size_t csize, abs_xsize, i;
size_t size;
size_t abs_csize;
char *cp;
mp_ptr xp, sp, ep;
mp_limb_t slimb, elimb;
if (fp == 0)
fp = stdin;
/* 4 bytes for size */
if (UNLIKELY (fread (csize_bytes, sizeof (csize_bytes), 1, fp) != 1))
return 0;
size = (((size_t) csize_bytes[0] << 24) + ((size_t) csize_bytes[1] << 16) +
((size_t) csize_bytes[2] << 8) + ((size_t) csize_bytes[3]));
if (size < 0x80000000u)
csize = size;
else
csize = size - 0x80000000u - 0x80000000u;
abs_csize = ABS (csize);
if (UNLIKELY (abs_csize > ~(mp_bitcnt_t) 0 / 8))
return 0; /* Bit size overflows */
/* round up to a multiple of limbs */
abs_xsize = BITS_TO_LIMBS ((mp_bitcnt_t) abs_csize * 8);
if (abs_xsize != 0)
{
xp = MPZ_NEWALLOC (x, abs_xsize);
/* Get limb boundaries right in the read, for the benefit of the
non-nails case. */
xp[0] = 0;
cp = (char *) (xp + abs_xsize) - abs_csize;
if (UNLIKELY (fread (cp, abs_csize, 1, fp) != 1))
return 0;
if (GMP_NAIL_BITS == 0)
{
/* Reverse limbs to least significant first, and byte swap. If
abs_xsize is odd then on the last iteration elimb and slimb are
the same. It doesn't seem extra code to handle that case
separately, to save an NTOH. */
sp = xp;
ep = xp + abs_xsize-1;
for (i = 0; i < (abs_xsize+1)/2; i++)
{
NTOH_LIMB_FETCH (elimb, ep);
NTOH_LIMB_FETCH (slimb, sp);
*sp++ = elimb;
*ep-- = slimb;
}
}
else
{
/* It ought to be possible to do the transformation in-place, but
for now it's easier to use an extra temporary area. */
mp_limb_t byte, limb;
int bits;
mp_size_t tpos;
mp_ptr tp;
TMP_DECL;
TMP_MARK;
tp = TMP_ALLOC_LIMBS (abs_xsize);
limb = 0;
bits = 0;
tpos = 0;
for (i = abs_csize-1; i >= 0; i--)
{
byte = (unsigned char) cp[i];
limb |= (byte << bits);
bits += 8;
if (bits >= GMP_NUMB_BITS)
{
ASSERT (tpos < abs_xsize);
tp[tpos++] = limb & GMP_NUMB_MASK;
bits -= GMP_NUMB_BITS;
ASSERT (bits < 8);
limb = byte >> (8 - bits);
}
}
if (bits != 0)
{
ASSERT (tpos < abs_xsize);
tp[tpos++] = limb;
}
ASSERT (tpos == abs_xsize);
MPN_COPY (xp, tp, abs_xsize);
TMP_FREE;
}
/* GMP 1.x mpz_out_raw wrote high zero bytes, strip any high zero
limbs resulting from this. Should be a non-zero value here, but
for safety don't assume that. */
MPN_NORMALIZE (xp, abs_xsize);
}
SIZ(x) = (csize >= 0 ? abs_xsize : -abs_xsize);
return abs_csize + 4;
}

View File

@@ -0,0 +1,173 @@
/* mpz_inp_str(dest_integer, stream, base) -- Input a number in base
BASE from stdio stream STREAM and store the result in DEST_INTEGER.
OF THE FUNCTIONS IN THIS FILE, ONLY mpz_inp_str IS FOR EXTERNAL USE, THE
REST ARE INTERNALS AND ARE ALMOST CERTAIN TO BE SUBJECT TO INCOMPATIBLE
CHANGES OR DISAPPEAR COMPLETELY IN FUTURE GNU MP RELEASES.
Copyright 1991, 1993, 1994, 1996, 1998, 2000-2003, 2011-2013 Free Software
Foundation, Inc.
This file is part of the GNU MP Library.
The GNU MP Library is free software; you can redistribute it and/or modify
it under the terms of either:
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
or
* the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any
later version.
or both in parallel, as here.
The GNU MP Library 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 copies of the GNU General Public License and the
GNU Lesser General Public License along with the GNU MP Library. If not,
see https://www.gnu.org/licenses/. */
#include <stdio.h>
#include <ctype.h>
#include "gmp-impl.h"
#include "longlong.h"
#define digit_value_tab __gmp_digit_value_tab
size_t
mpz_inp_str (mpz_ptr x, FILE *stream, int base)
{
int c;
size_t nread;
if (stream == 0)
stream = stdin;
nread = 0;
/* Skip whitespace. */
do
{
c = getc (stream);
nread++;
}
while (isspace (c));
return mpz_inp_str_nowhite (x, stream, base, c, nread);
}
/* shared by mpq_inp_str */
size_t
mpz_inp_str_nowhite (mpz_ptr x, FILE *stream, int base, int c, size_t nread)
{
char *str;
size_t alloc_size, str_size;
int negative;
mp_size_t xsize;
const unsigned char *digit_value;
ASSERT_ALWAYS (EOF == -1); /* FIXME: handle this by adding explicit */
/* comparisons of c and EOF before each */
/* read of digit_value[]. */
digit_value = digit_value_tab;
if (base > 36)
{
/* For bases > 36, use the collating sequence
0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz. */
digit_value += 208;
if (UNLIKELY (base > 62))
return 0; /* too large base */
}
negative = 0;
if (c == '-')
{
negative = 1;
c = getc (stream);
nread++;
}
if (c == EOF || digit_value[c] >= (base == 0 ? 10 : base))
return 0; /* error if no digits */
/* If BASE is 0, try to find out the base by looking at the initial
characters. */
if (base == 0)
{
base = 10;
if (c == '0')
{
base = 8;
c = getc (stream);
nread++;
if (c == 'x' || c == 'X')
{
base = 16;
c = getc (stream);
nread++;
}
else if (c == 'b' || c == 'B')
{
base = 2;
c = getc (stream);
nread++;
}
}
}
/* Skip leading zeros. */
while (c == '0')
{
c = getc (stream);
nread++;
}
alloc_size = 100;
str = __GMP_ALLOCATE_FUNC_TYPE (alloc_size, char);
str_size = 0;
while (c != EOF)
{
int dig;
dig = digit_value[c];
if (dig >= base)
break;
if (str_size >= alloc_size)
{
size_t old_alloc_size = alloc_size;
alloc_size = alloc_size * 3 / 2;
str = __GMP_REALLOCATE_FUNC_TYPE (str, old_alloc_size, alloc_size, char);
}
str[str_size++] = dig;
c = getc (stream);
}
nread += str_size;
ungetc (c, stream);
nread--;
/* Make sure the string is not empty, mpn_set_str would fail. */
if (str_size == 0)
{
SIZ (x) = 0;
}
else
{
LIMBS_PER_DIGIT_IN_BASE (xsize, str_size, base);
MPZ_NEWALLOC (x, xsize);
/* Convert the byte array in base BASE to our bignum format. */
xsize = mpn_set_str (PTR (x), (unsigned char *) str, str_size, base);
SIZ (x) = negative ? -xsize : xsize;
}
(*__gmp_free_func) (str, alloc_size);
return nread;
}

View File

@@ -0,0 +1,72 @@
/* mpz_invert (inv, x, n). Find multiplicative inverse of X in Z(N).
If X has an inverse, return non-zero and store inverse in INVERSE,
otherwise, return 0 and put garbage in INVERSE.
Copyright 1996-2001, 2005, 2012, 2014 Free Software Foundation, Inc.
This file is part of the GNU MP Library.
The GNU MP Library is free software; you can redistribute it and/or modify
it under the terms of either:
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
or
* the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any
later version.
or both in parallel, as here.
The GNU MP Library 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 copies of the GNU General Public License and the
GNU Lesser General Public License along with the GNU MP Library. If not,
see https://www.gnu.org/licenses/. */
#include "gmp-impl.h"
int
mpz_invert (mpz_ptr inverse, mpz_srcptr x, mpz_srcptr n)
{
mpz_t gcd, tmp;
mp_size_t xsize, nsize, size;
TMP_DECL;
xsize = ABSIZ (x);
nsize = ABSIZ (n);
size = MAX (xsize, nsize) + 1;
TMP_MARK;
MPZ_TMP_INIT (gcd, size);
MPZ_TMP_INIT (tmp, size);
mpz_gcdext (gcd, tmp, (mpz_ptr) 0, x, n);
/* If no inverse existed, return with an indication of that. */
if (!MPZ_EQUAL_1_P (gcd))
{
TMP_FREE;
return 0;
}
/* Make sure we return a positive inverse. */
if (SIZ (tmp) < 0)
{
if (SIZ (n) < 0)
mpz_sub (inverse, tmp, n);
else
mpz_add (inverse, tmp, n);
}
else
mpz_set (inverse, tmp);
TMP_FREE;
return 1;
}

View File

@@ -0,0 +1,184 @@
/* mpz_ior -- Logical inclusive or.
Copyright 1991, 1993, 1994, 1996, 1997, 2000, 2001, 2005, 2012, 2013,
2015-2018 Free Software Foundation, Inc.
This file is part of the GNU MP Library.
The GNU MP Library is free software; you can redistribute it and/or modify
it under the terms of either:
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
or
* the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any
later version.
or both in parallel, as here.
The GNU MP Library 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 copies of the GNU General Public License and the
GNU Lesser General Public License along with the GNU MP Library. If not,
see https://www.gnu.org/licenses/. */
#include "gmp-impl.h"
void
mpz_ior (mpz_ptr res, mpz_srcptr op1, mpz_srcptr op2)
{
mp_srcptr op1_ptr, op2_ptr;
mp_size_t op1_size, op2_size;
mp_ptr res_ptr;
mp_size_t res_size;
mp_size_t i;
op1_size = SIZ(op1);
op2_size = SIZ(op2);
if (op1_size < op2_size)
{
MPZ_SRCPTR_SWAP (op1, op2);
MP_SIZE_T_SWAP (op1_size, op2_size);
}
op1_ptr = PTR(op1);
res_ptr = PTR(res);
if (op2_size >= 0)
{
if (res_ptr != op1_ptr)
{
res_ptr = MPZ_REALLOC (res, op1_size);
/* No overlapping possible: op1_ptr = PTR(op1); */
MPN_COPY (res_ptr + op2_size, op1_ptr + op2_size,
op1_size - op2_size);
}
if (LIKELY (op2_size != 0))
mpn_ior_n (res_ptr, op1_ptr, PTR(op2), op2_size);
SIZ(res) = op1_size;
}
else
{
mp_ptr opx;
TMP_DECL;
TMP_MARK;
if (op1_size < 0)
{
mp_ptr opy;
/* Both operands are negative, so will be the result.
-((-OP1) | (-OP2)) = -(~(OP1 - 1) | ~(OP2 - 1)) =
= ~(~(OP1 - 1) | ~(OP2 - 1)) + 1 =
= ((OP1 - 1) & (OP2 - 1)) + 1 */
res_size = -op1_size;
/* Possible optimization: Decrease mpn_sub precision,
as we won't use the entire res of both. */
TMP_ALLOC_LIMBS_2 (opx, res_size, opy, res_size);
mpn_sub_1 (opx, op1_ptr, res_size, (mp_limb_t) 1);
op1_ptr = opx;
mpn_sub_1 (opy, PTR(op2), res_size, (mp_limb_t) 1);
op2_ptr = opy;
/* First loop finds the size of the result. */
for (i = res_size; --i >= 0;)
if ((op1_ptr[i] & op2_ptr[i]) != 0)
break;
res_size = i + 1;
res_ptr = MPZ_NEWALLOC (res, res_size + 1);
if (res_size != 0)
{
/* Second loop computes the real result. */
mpn_and_n (res_ptr, op1_ptr, op2_ptr, res_size);
res_ptr[res_size] = 0;
MPN_INCR_U (res_ptr, res_size + 1, 1);
res_size += res_ptr[res_size];
}
else
{
res_ptr[0] = 1;
res_size = 1;
}
SIZ(res) = -res_size;
}
else
{
mp_limb_t cy;
mp_size_t count;
/* Operand 2 negative, so will be the result.
-(OP1 | (-OP2)) = -(OP1 | ~(OP2 - 1)) =
= ~(OP1 | ~(OP2 - 1)) + 1 =
= (~OP1 & (OP2 - 1)) + 1 */
op2_size = -op2_size;
res_ptr = MPZ_REALLOC (res, op2_size);
op1_ptr = PTR(op1);
opx = TMP_ALLOC_LIMBS (op2_size);
mpn_sub_1 (opx, PTR(op2), op2_size, (mp_limb_t) 1);
op2_ptr = opx;
op2_size -= op2_ptr[op2_size - 1] == 0;
if (op1_size >= op2_size)
{
/* We can just ignore the part of OP1 that stretches above OP2,
because the result limbs are zero there. */
/* First loop finds the size of the result. */
for (i = op2_size; --i >= 0;)
if ((~op1_ptr[i] & op2_ptr[i]) != 0)
break;
res_size = i + 1;
count = res_size;
}
else
{
res_size = op2_size;
/* Copy the part of OP2 that stretches above OP1, to RES. */
MPN_COPY (res_ptr + op1_size, op2_ptr + op1_size, op2_size - op1_size);
count = op1_size;
}
if (res_size != 0)
{
/* Second loop computes the real result. */
if (LIKELY (count != 0))
mpn_andn_n (res_ptr, op2_ptr, op1_ptr, count);
cy = mpn_add_1 (res_ptr, res_ptr, res_size, (mp_limb_t) 1);
if (cy)
{
res_ptr[res_size] = cy;
++res_size;
}
}
else
{
res_ptr[0] = 1;
res_size = 1;
}
SIZ(res) = -res_size;
}
TMP_FREE;
}
}

View File

@@ -0,0 +1,52 @@
/* mpz_init_set (src_integer) -- Make a new multiple precision number with
a value copied from SRC_INTEGER.
Copyright 1991, 1993, 1994, 1996, 2000-2002, 2012 Free Software Foundation,
Inc.
This file is part of the GNU MP Library.
The GNU MP Library is free software; you can redistribute it and/or modify
it under the terms of either:
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
or
* the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any
later version.
or both in parallel, as here.
The GNU MP Library 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 copies of the GNU General Public License and the
GNU Lesser General Public License along with the GNU MP Library. If not,
see https://www.gnu.org/licenses/. */
#include "gmp-impl.h"
void
mpz_init_set (mpz_ptr w, mpz_srcptr u)
{
mp_ptr wp, up;
mp_size_t usize, size;
usize = SIZ (u);
size = ABS (usize);
ALLOC (w) = MAX (size, 1);
wp = __GMP_ALLOCATE_FUNC_LIMBS (ALLOC (w));
PTR (w) = wp;
up = PTR (u);
MPN_COPY (wp, up, size);
SIZ (w) = usize;
}

View File

@@ -0,0 +1,43 @@
/* mpz_init_set_d(integer, val) -- Initialize and assign INTEGER with a double
value VAL.
Copyright 1996, 2000, 2001, 2012, 2015 Free Software Foundation, Inc.
This file is part of the GNU MP Library.
The GNU MP Library is free software; you can redistribute it and/or modify
it under the terms of either:
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
or
* the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any
later version.
or both in parallel, as here.
The GNU MP Library 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 copies of the GNU General Public License and the
GNU Lesser General Public License along with the GNU MP Library. If not,
see https://www.gnu.org/licenses/. */
#include "gmp-impl.h"
void
mpz_init_set_d (mpz_ptr dest, double val)
{
static const mp_limb_t dummy_limb=0xc1a0;
ALLOC (dest) = 0;
SIZ (dest) = 0;
PTR (dest) = (mp_ptr) &dummy_limb;
mpz_set_d (dest, val);
}

View File

@@ -0,0 +1,58 @@
/* mpz_init_set_si(dest,val) -- Make a new multiple precision in DEST and
assign VAL to the new number.
Copyright 1991, 1993-1995, 2000-2002, 2012 Free Software Foundation, Inc.
This file is part of the GNU MP Library.
The GNU MP Library is free software; you can redistribute it and/or modify
it under the terms of either:
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
or
* the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any
later version.
or both in parallel, as here.
The GNU MP Library 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 copies of the GNU General Public License and the
GNU Lesser General Public License along with the GNU MP Library. If not,
see https://www.gnu.org/licenses/. */
#include "gmp-impl.h"
void
mpz_init_set_si (mpz_ptr dest, signed long int val)
{
mp_size_t size;
mp_limb_t vl;
ALLOC (dest) = 1;
PTR (dest) = __GMP_ALLOCATE_FUNC_LIMBS (1);
vl = (mp_limb_t) ABS_CAST (unsigned long int, val);
PTR (dest)[0] = vl & GMP_NUMB_MASK;
size = vl != 0;
#if GMP_NAIL_BITS != 0
if (vl > GMP_NUMB_MAX)
{
MPZ_REALLOC (dest, 2);
PTR (dest)[1] = vl >> GMP_NUMB_BITS;
size = 2;
}
#endif
SIZ (dest) = val >= 0 ? size : -size;
}

View File

@@ -0,0 +1,47 @@
/* mpz_init_set_str(string, base) -- Convert the \0-terminated string STRING in
base BASE to a multiple precision integer. Allow white space in the string.
If BASE == 0 determine the base in the C standard way, i.e. 0xhh...h means
base 16, 0oo...o means base 8, otherwise assume base 10.
Copyright 1991, 1993-1995, 2000-2002, 2012 Free Software Foundation, Inc.
This file is part of the GNU MP Library.
The GNU MP Library is free software; you can redistribute it and/or modify
it under the terms of either:
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
or
* the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any
later version.
or both in parallel, as here.
The GNU MP Library 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 copies of the GNU General Public License and the
GNU Lesser General Public License along with the GNU MP Library. If not,
see https://www.gnu.org/licenses/. */
#include "gmp-impl.h"
int
mpz_init_set_str (mpz_ptr x, const char *str, int base)
{
static const mp_limb_t dummy_limb=0xc1a0;
ALLOC (x) = 0;
PTR (x) = (mp_ptr) &dummy_limb;
/* if str has no digits mpz_set_str leaves x->_mp_size unset */
SIZ (x) = 0;
return mpz_set_str (x, str, base);
}

View File

@@ -0,0 +1,58 @@
/* mpz_init_set_ui(dest,val) -- Make a new multiple precision in DEST and
assign VAL to the new number.
Copyright 1991, 1993-1995, 2000-2002, 2004, 2012 Free Software Foundation, Inc.
This file is part of the GNU MP Library.
The GNU MP Library is free software; you can redistribute it and/or modify
it under the terms of either:
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
or
* the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any
later version.
or both in parallel, as here.
The GNU MP Library 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 copies of the GNU General Public License and the
GNU Lesser General Public License along with the GNU MP Library. If not,
see https://www.gnu.org/licenses/. */
#include "gmp-impl.h"
void
mpz_init_set_ui (mpz_ptr dest, unsigned long int val)
{
mp_size_t size;
#if BITS_PER_ULONG > GMP_NUMB_BITS /* avoid warnings about shift amount */
if (val > GMP_NUMB_MAX)
{
ALLOC (dest) = 2;
PTR (dest) = __GMP_ALLOCATE_FUNC_LIMBS (2);
PTR (dest)[1] = val >> GMP_NUMB_BITS;
size = 2;
}
else
#endif
{
ALLOC (dest) = 1;
PTR (dest) = __GMP_ALLOCATE_FUNC_LIMBS (1);
size = val != 0;
}
PTR (dest)[0] = val & GMP_NUMB_MASK;
SIZ (dest) = size;
}

View File

@@ -0,0 +1,210 @@
/* mpz_jacobi, mpz_legendre, mpz_kronecker -- mpz/mpz Jacobi symbols.
Copyright 2000-2002, 2005, 2010-2012 Free Software Foundation, Inc.
This file is part of the GNU MP Library.
The GNU MP Library is free software; you can redistribute it and/or modify
it under the terms of either:
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
or
* the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any
later version.
or both in parallel, as here.
The GNU MP Library 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 copies of the GNU General Public License and the
GNU Lesser General Public License along with the GNU MP Library. If not,
see https://www.gnu.org/licenses/. */
#include <stdio.h>
#include "gmp-impl.h"
#include "longlong.h"
/* This code does triple duty as mpz_jacobi, mpz_legendre and
mpz_kronecker. For ABI compatibility, the link symbol is
__gmpz_jacobi, not __gmpz_kronecker, even though the latter would
be more logical.
mpz_jacobi could assume b is odd, but the improvements from that seem
small compared to other operations, and anything significant should be
checked at run-time since we'd like odd b to go fast in mpz_kronecker
too.
mpz_legendre could assume b is an odd prime, but knowing this doesn't
present any obvious benefits. Result 0 wouldn't arise (unless "a" is a
multiple of b), but the checking for that takes little time compared to
other operations.
Enhancements:
mpn_bdiv_qr should be used instead of mpn_tdiv_qr.
*/
int
mpz_jacobi (mpz_srcptr a, mpz_srcptr b)
{
mp_srcptr asrcp, bsrcp;
mp_size_t asize, bsize;
mp_limb_t alow, blow;
mp_ptr ap, bp;
unsigned btwos;
int result_bit1;
int res;
TMP_DECL;
asize = SIZ(a);
asrcp = PTR(a);
alow = asrcp[0];
bsize = SIZ(b);
bsrcp = PTR(b);
blow = bsrcp[0];
/* The MPN jacobi functions require positive a and b, and b odd. So
we must to handle the cases of a or b zero, then signs, and then
the case of even b.
*/
if (bsize == 0)
/* (a/0) = [ a = 1 or a = -1 ] */
return JACOBI_LS0 (alow, asize);
if (asize == 0)
/* (0/b) = [ b = 1 or b = - 1 ] */
return JACOBI_0LS (blow, bsize);
if ( (((alow | blow) & 1) == 0))
/* Common factor of 2 ==> (a/b) = 0 */
return 0;
if (bsize < 0)
{
/* (a/-1) = -1 if a < 0, +1 if a >= 0 */
result_bit1 = (asize < 0) << 1;
bsize = -bsize;
}
else
result_bit1 = 0;
JACOBI_STRIP_LOW_ZEROS (result_bit1, alow, bsrcp, bsize, blow);
count_trailing_zeros (btwos, blow);
blow >>= btwos;
if (bsize > 1 && btwos > 0)
{
mp_limb_t b1 = bsrcp[1];
blow |= b1 << (GMP_NUMB_BITS - btwos);
if (bsize == 2 && (b1 >> btwos) == 0)
bsize = 1;
}
if (asize < 0)
{
/* (-1/b) = -1 iff b = 3 (mod 4) */
result_bit1 ^= JACOBI_N1B_BIT1(blow);
asize = -asize;
}
JACOBI_STRIP_LOW_ZEROS (result_bit1, blow, asrcp, asize, alow);
/* Ensure asize >= bsize. Take advantage of the generalized
reciprocity law (a/b*2^n) = (b*2^n / a) * RECIP(a,b) */
if (asize < bsize)
{
MPN_SRCPTR_SWAP (asrcp, asize, bsrcp, bsize);
MP_LIMB_T_SWAP (alow, blow);
/* NOTE: The value of alow (old blow) is a bit subtle. For this code
path, we get alow as the low, always odd, limb of shifted A. Which is
what we need for the reciprocity update below.
However, all other uses of alow assumes that it is *not*
shifted. Luckily, alow matters only when either
+ btwos > 0, in which case A is always odd
+ asize == bsize == 1, in which case this code path is never
taken. */
count_trailing_zeros (btwos, blow);
blow >>= btwos;
if (bsize > 1 && btwos > 0)
{
mp_limb_t b1 = bsrcp[1];
blow |= b1 << (GMP_NUMB_BITS - btwos);
if (bsize == 2 && (b1 >> btwos) == 0)
bsize = 1;
}
result_bit1 ^= JACOBI_RECIP_UU_BIT1 (alow, blow);
}
if (bsize == 1)
{
result_bit1 ^= JACOBI_TWOS_U_BIT1(btwos, alow);
if (blow == 1)
return JACOBI_BIT1_TO_PN (result_bit1);
if (asize > 1)
JACOBI_MOD_OR_MODEXACT_1_ODD (result_bit1, alow, asrcp, asize, blow);
return mpn_jacobi_base (alow, blow, result_bit1);
}
/* Allocation strategy: For A, we allocate a working copy only for A % B, but
when A is much larger than B, we have to allocate space for the large
quotient. We use the same area, pointed to by bp, for both the quotient
A/B and the working copy of B. */
TMP_MARK;
if (asize >= 2*bsize)
TMP_ALLOC_LIMBS_2 (ap, bsize, bp, asize - bsize + 1);
else
TMP_ALLOC_LIMBS_2 (ap, bsize, bp, bsize);
/* In the case of even B, we conceptually shift out the powers of two first,
and then divide A mod B. Hence, when taking those powers of two into
account, we must use alow *before* the division. Doing the actual division
first is ok, because the point is to remove multiples of B from A, and
multiples of 2^k B are good enough. */
if (asize > bsize)
mpn_tdiv_qr (bp, ap, 0, asrcp, asize, bsrcp, bsize);
else
MPN_COPY (ap, asrcp, bsize);
if (btwos > 0)
{
result_bit1 ^= JACOBI_TWOS_U_BIT1(btwos, alow);
ASSERT_NOCARRY (mpn_rshift (bp, bsrcp, bsize, btwos));
bsize -= (ap[bsize-1] | bp[bsize-1]) == 0;
}
else
MPN_COPY (bp, bsrcp, bsize);
ASSERT (blow == bp[0]);
res = mpn_jacobi_n (ap, bp, bsize,
mpn_jacobi_init (ap[0], blow, (result_bit1>>1) & 1));
TMP_FREE;
return res;
}

View File

@@ -0,0 +1,137 @@
/* mpz_si_kronecker -- long+mpz Kronecker/Jacobi symbol.
Copyright 1999-2002 Free Software Foundation, Inc.
This file is part of the GNU MP Library.
The GNU MP Library is free software; you can redistribute it and/or modify
it under the terms of either:
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
or
* the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any
later version.
or both in parallel, as here.
The GNU MP Library 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 copies of the GNU General Public License and the
GNU Lesser General Public License along with the GNU MP Library. If not,
see https://www.gnu.org/licenses/. */
#include "gmp-impl.h"
#include "longlong.h"
int
mpz_si_kronecker (long a, mpz_srcptr b)
{
mp_srcptr b_ptr;
mp_limb_t b_low;
mp_size_t b_size;
mp_size_t b_abs_size;
mp_limb_t a_limb, b_rem;
unsigned twos;
int result_bit1;
#if GMP_NUMB_BITS < BITS_PER_ULONG
if (a > GMP_NUMB_MAX || a < -GMP_NUMB_MAX)
{
mp_limb_t alimbs[2];
mpz_t az;
ALLOC(az) = numberof (alimbs);
PTR(az) = alimbs;
mpz_set_si (az, a);
return mpz_kronecker (az, b);
}
#endif
b_size = SIZ (b);
if (b_size == 0)
return JACOBI_S0 (a); /* (a/0) */
/* account for the effect of the sign of b, then ignore it */
result_bit1 = JACOBI_BSGN_SS_BIT1 (a, b_size);
b_ptr = PTR(b);
b_low = b_ptr[0];
b_abs_size = ABS (b_size);
if ((b_low & 1) != 0)
{
/* b odd */
result_bit1 ^= JACOBI_ASGN_SU_BIT1 (a, b_low);
a_limb = ABS_CAST(mp_limb_t, a);
if ((a_limb & 1) == 0)
{
/* (0/b)=1 for b=+/-1, 0 otherwise */
if (a_limb == 0)
return (b_abs_size == 1 && b_low == 1);
/* a even, b odd */
count_trailing_zeros (twos, a_limb);
a_limb >>= twos;
/* (a*2^n/b) = (a/b) * twos(n,a) */
result_bit1 ^= JACOBI_TWOS_U_BIT1 (twos, b_low);
}
}
else
{
/* (even/even)=0, and (0/b)=0 for b!=+/-1 */
if ((a & 1) == 0)
return 0;
/* a odd, b even
Establish shifted b_low with valid bit1 for ASGN and RECIP below.
Zero limbs stripped are accounted for, but zero bits on b_low are
not because they remain in {b_ptr,b_abs_size} for the
JACOBI_MOD_OR_MODEXACT_1_ODD. */
JACOBI_STRIP_LOW_ZEROS (result_bit1, a, b_ptr, b_abs_size, b_low);
if ((b_low & 1) == 0)
{
if (UNLIKELY (b_low == GMP_NUMB_HIGHBIT))
{
/* need b_ptr[1] to get bit1 in b_low */
if (b_abs_size == 1)
{
/* (a/0x80000000) = (a/2)^(BPML-1) */
if ((GMP_NUMB_BITS % 2) == 0)
result_bit1 ^= JACOBI_TWO_U_BIT1 (a);
return JACOBI_BIT1_TO_PN (result_bit1);
}
/* b_abs_size > 1 */
b_low = b_ptr[1] << 1;
}
else
{
count_trailing_zeros (twos, b_low);
b_low >>= twos;
}
}
result_bit1 ^= JACOBI_ASGN_SU_BIT1 (a, b_low);
a_limb = (unsigned long) ABS(a);
}
if (a_limb == 1)
return JACOBI_BIT1_TO_PN (result_bit1); /* (1/b)=1 */
/* (a/b*2^n) = (b*2^n mod a / a) * recip(a,b) */
JACOBI_MOD_OR_MODEXACT_1_ODD (result_bit1, b_rem, b_ptr, b_abs_size, a_limb);
result_bit1 ^= JACOBI_RECIP_UU_BIT1 (a_limb, b_low);
return mpn_jacobi_base (b_rem, a_limb, result_bit1);
}

View File

@@ -0,0 +1,129 @@
/* mpz_ui_kronecker -- ulong+mpz Kronecker/Jacobi symbol.
Copyright 1999-2002 Free Software Foundation, Inc.
This file is part of the GNU MP Library.
The GNU MP Library is free software; you can redistribute it and/or modify
it under the terms of either:
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
or
* the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any
later version.
or both in parallel, as here.
The GNU MP Library 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 copies of the GNU General Public License and the
GNU Lesser General Public License along with the GNU MP Library. If not,
see https://www.gnu.org/licenses/. */
#include "gmp-impl.h"
#include "longlong.h"
int
mpz_ui_kronecker (unsigned long a, mpz_srcptr b)
{
mp_srcptr b_ptr;
mp_limb_t b_low;
int b_abs_size;
mp_limb_t b_rem;
int twos;
int result_bit1;
/* (a/-1)=1 when a>=0, so the sign of b is ignored */
b_abs_size = ABSIZ (b);
if (b_abs_size == 0)
return JACOBI_U0 (a); /* (a/0) */
if (a > GMP_NUMB_MAX)
{
mp_limb_t alimbs[2];
mpz_t az;
ALLOC(az) = numberof (alimbs);
PTR(az) = alimbs;
mpz_set_ui (az, a);
return mpz_kronecker (az, b);
}
b_ptr = PTR(b);
b_low = b_ptr[0];
result_bit1 = 0;
if (! (b_low & 1))
{
/* (0/b)=0 for b!=+/-1; and (even/even)=0 */
if (! (a & 1))
return 0;
/* a odd, b even
Establish shifted b_low with valid bit1 for the RECIP below. Zero
limbs stripped are accounted for, but zero bits on b_low are not
because they remain in {b_ptr,b_abs_size} for
JACOBI_MOD_OR_MODEXACT_1_ODD. */
JACOBI_STRIP_LOW_ZEROS (result_bit1, a, b_ptr, b_abs_size, b_low);
if (! (b_low & 1))
{
if (UNLIKELY (b_low == GMP_NUMB_HIGHBIT))
{
/* need b_ptr[1] to get bit1 in b_low */
if (b_abs_size == 1)
{
/* (a/0x80...00) == (a/2)^(NUMB-1) */
if ((GMP_NUMB_BITS % 2) == 0)
{
/* JACOBI_STRIP_LOW_ZEROS does nothing to result_bit1
when GMP_NUMB_BITS is even, so it's still 0. */
ASSERT (result_bit1 == 0);
result_bit1 = JACOBI_TWO_U_BIT1 (a);
}
return JACOBI_BIT1_TO_PN (result_bit1);
}
/* b_abs_size > 1 */
b_low = b_ptr[1] << 1;
}
else
{
count_trailing_zeros (twos, b_low);
b_low >>= twos;
}
}
}
else
{
if (a == 0) /* (0/b)=1 for b=+/-1, 0 otherwise */
return (b_abs_size == 1 && b_low == 1);
if (! (a & 1))
{
/* a even, b odd */
count_trailing_zeros (twos, a);
a >>= twos;
/* (a*2^n/b) = (a/b) * (2/a)^n */
result_bit1 = JACOBI_TWOS_U_BIT1 (twos, b_low);
}
}
if (a == 1)
return JACOBI_BIT1_TO_PN (result_bit1); /* (1/b)=1 */
/* (a/b*2^n) = (b*2^n mod a / a) * RECIP(a,b) */
JACOBI_MOD_OR_MODEXACT_1_ODD (result_bit1, b_rem, b_ptr, b_abs_size, a);
result_bit1 ^= JACOBI_RECIP_UU_BIT1 (a, b_low);
return mpn_jacobi_base (b_rem, (mp_limb_t) a, result_bit1);
}

View File

@@ -0,0 +1,92 @@
/* mpz_kronecker_si -- mpz+long Kronecker/Jacobi symbol.
Copyright 1999-2002 Free Software Foundation, Inc.
This file is part of the GNU MP Library.
The GNU MP Library is free software; you can redistribute it and/or modify
it under the terms of either:
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
or
* the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any
later version.
or both in parallel, as here.
The GNU MP Library 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 copies of the GNU General Public License and the
GNU Lesser General Public License along with the GNU MP Library. If not,
see https://www.gnu.org/licenses/. */
#include "gmp-impl.h"
#include "longlong.h"
/* After the absolute value of b is established it's treated as an unsigned
long, because 0x80..00 doesn't fit in a signed long. */
int
mpz_kronecker_si (mpz_srcptr a, long b)
{
mp_srcptr a_ptr;
mp_size_t a_size;
mp_limb_t a_rem, b_limb;
int result_bit1;
a_size = SIZ(a);
if (a_size == 0)
return JACOBI_0S (b);
#if GMP_NUMB_BITS < BITS_PER_ULONG
if (b > GMP_NUMB_MAX || b < -GMP_NUMB_MAX)
{
mp_limb_t blimbs[2];
mpz_t bz;
ALLOC(bz) = numberof (blimbs);
PTR(bz) = blimbs;
mpz_set_si (bz, b);
return mpz_kronecker (a, bz);
}
#endif
result_bit1 = JACOBI_BSGN_SS_BIT1 (a_size, b);
b_limb = ABS_CAST (unsigned long, b);
a_ptr = PTR(a);
if ((b_limb & 1) == 0)
{
mp_limb_t a_low = a_ptr[0];
int twos;
if (b_limb == 0)
return JACOBI_LS0 (a_low, a_size); /* (a/0) */
if (! (a_low & 1))
return 0; /* (even/even)=0 */
/* (a/2)=(2/a) for a odd */
count_trailing_zeros (twos, b_limb);
b_limb >>= twos;
result_bit1 ^= JACOBI_TWOS_U_BIT1 (twos, a_low);
}
if (b_limb == 1)
return JACOBI_BIT1_TO_PN (result_bit1); /* (a/1)=1 for any a */
result_bit1 ^= JACOBI_ASGN_SU_BIT1 (a_size, b_limb);
a_size = ABS(a_size);
/* (a/b) = (a mod b / b) */
JACOBI_MOD_OR_MODEXACT_1_ODD (result_bit1, a_rem, a_ptr, a_size, b_limb);
return mpn_jacobi_base (a_rem, b_limb, result_bit1);
}

View File

@@ -0,0 +1,88 @@
/* mpz_kronecker_ui -- mpz+ulong Kronecker/Jacobi symbol.
Copyright 1999-2002 Free Software Foundation, Inc.
This file is part of the GNU MP Library.
The GNU MP Library is free software; you can redistribute it and/or modify
it under the terms of either:
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
or
* the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any
later version.
or both in parallel, as here.
The GNU MP Library 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 copies of the GNU General Public License and the
GNU Lesser General Public License along with the GNU MP Library. If not,
see https://www.gnu.org/licenses/. */
#include "gmp-impl.h"
#include "longlong.h"
int
mpz_kronecker_ui (mpz_srcptr a, unsigned long b)
{
mp_srcptr a_ptr;
mp_size_t a_size;
mp_limb_t a_rem;
int result_bit1;
a_size = SIZ(a);
if (a_size == 0)
return JACOBI_0U (b);
if (b > GMP_NUMB_MAX)
{
mp_limb_t blimbs[2];
mpz_t bz;
ALLOC(bz) = numberof (blimbs);
PTR(bz) = blimbs;
mpz_set_ui (bz, b);
return mpz_kronecker (a, bz);
}
a_ptr = PTR(a);
if ((b & 1) != 0)
{
result_bit1 = JACOBI_ASGN_SU_BIT1 (a_size, b);
}
else
{
mp_limb_t a_low = a_ptr[0];
int twos;
if (b == 0)
return JACOBI_LS0 (a_low, a_size); /* (a/0) */
if (! (a_low & 1))
return 0; /* (even/even)=0 */
/* (a/2)=(2/a) for a odd */
count_trailing_zeros (twos, b);
b >>= twos;
result_bit1 = (JACOBI_TWOS_U_BIT1 (twos, a_low)
^ JACOBI_ASGN_SU_BIT1 (a_size, b));
}
if (b == 1)
return JACOBI_BIT1_TO_PN (result_bit1); /* (a/1)=1 for any a */
a_size = ABS(a_size);
/* (a/b) = (a mod b / b) */
JACOBI_MOD_OR_MODEXACT_1_ODD (result_bit1, a_rem, a_ptr, a_size, b);
return mpn_jacobi_base (a_rem, (mp_limb_t) b, result_bit1);
}

View File

@@ -0,0 +1,87 @@
/* mpz_lcm -- mpz/mpz least common multiple.
Copyright 1996, 2000, 2001, 2005, 2012 Free Software Foundation, Inc.
This file is part of the GNU MP Library.
The GNU MP Library is free software; you can redistribute it and/or modify
it under the terms of either:
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
or
* the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any
later version.
or both in parallel, as here.
The GNU MP Library 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 copies of the GNU General Public License and the
GNU Lesser General Public License along with the GNU MP Library. If not,
see https://www.gnu.org/licenses/. */
#include "gmp-impl.h"
void
mpz_lcm (mpz_ptr r, mpz_srcptr u, mpz_srcptr v)
{
mpz_t g;
mp_size_t usize, vsize;
TMP_DECL;
usize = SIZ (u);
vsize = SIZ (v);
if (usize == 0 || vsize == 0)
{
SIZ (r) = 0;
return;
}
usize = ABS (usize);
vsize = ABS (vsize);
if (vsize == 1 || usize == 1)
{
mp_limb_t vl, gl, c;
mp_srcptr up;
mp_ptr rp;
if (usize == 1)
{
usize = vsize;
MPZ_SRCPTR_SWAP (u, v);
}
MPZ_REALLOC (r, usize+1);
up = PTR(u);
vl = PTR(v)[0];
gl = mpn_gcd_1 (up, usize, vl);
vl /= gl;
rp = PTR(r);
c = mpn_mul_1 (rp, up, usize, vl);
rp[usize] = c;
usize += (c != 0);
SIZ(r) = usize;
return;
}
TMP_MARK;
MPZ_TMP_INIT (g, usize); /* v != 0 implies |gcd(u,v)| <= |u| */
mpz_gcd (g, u, v);
mpz_divexact (g, u, g);
mpz_mul (r, g, v);
SIZ (r) = ABS (SIZ (r)); /* result always positive */
TMP_FREE;
}

View File

@@ -0,0 +1,78 @@
/* mpz_lcm_ui -- least common multiple of mpz and ulong.
Copyright 2001, 2002, 2004 Free Software Foundation, Inc.
This file is part of the GNU MP Library.
The GNU MP Library is free software; you can redistribute it and/or modify
it under the terms of either:
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
or
* the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any
later version.
or both in parallel, as here.
The GNU MP Library 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 copies of the GNU General Public License and the
GNU Lesser General Public License along with the GNU MP Library. If not,
see https://www.gnu.org/licenses/. */
#include "gmp-impl.h"
#include "longlong.h"
void
mpz_lcm_ui (mpz_ptr r, mpz_srcptr u, unsigned long v)
{
mp_size_t usize;
mp_srcptr up;
mp_ptr rp;
unsigned long g;
mp_limb_t c;
#if BITS_PER_ULONG > GMP_NUMB_BITS /* avoid warnings about shift amount */
if (v > GMP_NUMB_MAX)
{
mpz_t vz;
mp_limb_t vlimbs[2];
vlimbs[0] = v & GMP_NUMB_MASK;
vlimbs[1] = v >> GMP_NUMB_BITS;
PTR(vz) = vlimbs;
SIZ(vz) = 2;
mpz_lcm (r, u, vz);
return;
}
#endif
/* result zero if either operand zero */
usize = SIZ(u);
if (usize == 0 || v == 0)
{
SIZ(r) = 0;
return;
}
usize = ABS(usize);
MPZ_REALLOC (r, usize+1);
up = PTR(u);
g = (unsigned long) mpn_gcd_1 (up, usize, (mp_limb_t) v);
v /= g;
rp = PTR(r);
c = mpn_mul_1 (rp, up, usize, (mp_limb_t) v);
rp[usize] = c;
usize += (c != 0);
SIZ(r) = usize;
}

View File

@@ -0,0 +1,39 @@
/* mpz_finish_limbs -- Update mpz after writing to the limb array.
Copyright 2013 Free Software Foundation, Inc.
This file is part of the GNU MP Library.
The GNU MP Library is free software; you can redistribute it and/or modify
it under the terms of either:
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
or
* the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any
later version.
or both in parallel, as here.
The GNU MP Library 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 copies of the GNU General Public License and the
GNU Lesser General Public License along with the GNU MP Library. If not,
see https://www.gnu.org/licenses/. */
#include "gmp-impl.h"
void
mpz_limbs_finish (mpz_ptr x, mp_size_t xs)
{
mp_size_t xn = ABS(xs);
MPN_NORMALIZE (PTR (x), xn);
SIZ (x) = xs < 0 ? -xn : xn;
}

View File

@@ -0,0 +1,38 @@
/* mpz_limbs_modify -- Read-and-modify access to the mpn-style limb array.
Copyright 2013 Free Software Foundation, Inc.
This file is part of the GNU MP Library.
The GNU MP Library is free software; you can redistribute it and/or modify
it under the terms of either:
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
or
* the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any
later version.
or both in parallel, as here.
The GNU MP Library 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 copies of the GNU General Public License and the
GNU Lesser General Public License along with the GNU MP Library. If not,
see https://www.gnu.org/licenses/. */
#include "gmp-impl.h"
mp_ptr
mpz_limbs_modify (mpz_ptr x, mp_size_t n)
{
ASSERT (n > 0);
return MPZ_REALLOC (x, n);
}

View File

@@ -0,0 +1,37 @@
/* mpz_limbs_read -- Read access to the mpn-style limb array.
Copyright 2013 Free Software Foundation, Inc.
This file is part of the GNU MP Library.
The GNU MP Library is free software; you can redistribute it and/or modify
it under the terms of either:
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
or
* the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any
later version.
or both in parallel, as here.
The GNU MP Library 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 copies of the GNU General Public License and the
GNU Lesser General Public License along with the GNU MP Library. If not,
see https://www.gnu.org/licenses/. */
#include "gmp-impl.h"
mp_srcptr
mpz_limbs_read (mpz_srcptr x)
{
return PTR(x);
}

View File

@@ -0,0 +1,38 @@
/* mpz_limbs_write -- Write access to the mpn-style limb array.
Copyright 2013 Free Software Foundation, Inc.
This file is part of the GNU MP Library.
The GNU MP Library is free software; you can redistribute it and/or modify
it under the terms of either:
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
or
* the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any
later version.
or both in parallel, as here.
The GNU MP Library 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 copies of the GNU General Public License and the
GNU Lesser General Public License along with the GNU MP Library. If not,
see https://www.gnu.org/licenses/. */
#include "gmp-impl.h"
mp_ptr
mpz_limbs_write (mpz_ptr x, mp_size_t n)
{
ASSERT (n > 0);
return MPZ_NEWALLOC (x, n);
}

View File

@@ -0,0 +1,127 @@
/* mpz_lucas_mod -- Helper function for the strong Lucas
primality test.
THE FUNCTIONS IN THIS FILE ARE FOR INTERNAL USE ONLY. THEY'RE ALMOST
CERTAIN TO BE SUBJECT TO INCOMPATIBLE CHANGES OR DISAPPEAR COMPLETELY IN
FUTURE GNU MP RELEASES.
Copyright 2018 Free Software Foundation, Inc.
Contributed by Marco Bodrato.
This file is part of the GNU MP Library.
The GNU MP Library is free software; you can redistribute it and/or modify
it under the terms of either:
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
or
* the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any
later version.
or both in parallel, as here.
The GNU MP Library 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 copies of the GNU General Public License and the
GNU Lesser General Public License along with the GNU MP Library. If not,
see https://www.gnu.org/licenses/. */
#include "gmp-impl.h"
/* Computes V_{k+1}, Q^{k+1} (mod n) for the Lucas' sequence */
/* with P=1, Q=Q; k = n>>b0. */
/* Requires n > 4; b0 > 0; -2*Q must not overflow a long. */
/* If U_{k+1}==0 (mod n) or V_{k+1}==0 (mod n), it returns 1, */
/* otherwise it returns 0 and sets V=V_{k+1} and Qk=Q^{k+1}. */
/* V will never grow beyond SIZ(n), Qk not beyond 2*SIZ(n). */
int
mpz_lucas_mod (mpz_ptr V, mpz_ptr Qk, long Q,
mp_bitcnt_t b0, mpz_srcptr n, mpz_ptr T1, mpz_ptr T2)
{
mp_bitcnt_t bs;
int res;
ASSERT (b0 > 0);
ASSERT (SIZ (n) > 1 || SIZ (n) > 0 && PTR (n) [0] > 4);
mpz_set_ui (V, 1); /* U1 = 1 */
bs = mpz_sizeinbase (n, 2) - 2;
if (UNLIKELY (bs < b0))
{
/* n = 2^b0 - 1, should we use Lucas-Lehmer instead? */
ASSERT (bs == b0 - 2);
mpz_set_si (Qk, Q);
return 0;
}
mpz_set_ui (Qk, 1); /* U2 = 1 */
do
{
/* We use the iteration suggested in "Elementary Number Theory" */
/* by Peter Hackman (November 1, 2009), section "L.XVII Scalar */
/* Formulas", from http://hackmat.se/kurser/TATM54/booktot.pdf */
/* U_{2k} = 2*U_{k+1}*U_k - P*U_k^2 */
/* U_{2k+1} = U_{k+1}^2 - Q*U_k^2 */
/* U_{2k+2} = P*U_{k+1}^2 - 2*Q*U_{k+1}*U_k */
/* We note that U_{2k+2} = P*U_{2k+1} - Q*U_{2k} */
/* The formulas are specialized for P=1, and only squares: */
/* U_{2k} = U_{k+1}^2 - |U_{k+1} - U_k|^2 */
/* U_{2k+1} = U_{k+1}^2 - Q*U_k^2 */
/* U_{2k+2} = U_{2k+1} - Q*U_{2k} */
mpz_mul (T1, Qk, Qk); /* U_{k+1}^2 */
mpz_sub (Qk, V, Qk); /* |U_{k+1} - U_k| */
mpz_mul (T2, Qk, Qk); /* |U_{k+1} - U_k|^2 */
mpz_mul (Qk, V, V); /* U_k^2 */
mpz_sub (T2, T1, T2); /* U_{k+1}^2 - (U_{k+1} - U_k)^2 */
if (Q > 0) /* U_{k+1}^2 - Q U_k^2 = U_{2k+1} */
mpz_submul_ui (T1, Qk, Q);
else
mpz_addmul_ui (T1, Qk, NEG_CAST (unsigned long, Q));
/* A step k->k+1 is performed if the bit in $n$ is 1 */
if (mpz_tstbit (n, bs))
{
/* U_{2k+2} = U_{2k+1} - Q*U_{2k} */
mpz_mul_si (T2, T2, Q);
mpz_sub (T2, T1, T2);
mpz_swap (T1, T2);
}
mpz_tdiv_r (Qk, T1, n);
mpz_tdiv_r (V, T2, n);
} while (--bs >= b0);
res = SIZ (Qk) == 0;
if (!res) {
mpz_mul_si (T1, V, -2*Q);
mpz_add (T1, Qk, T1); /* V_k = U_k - 2Q*U_{k-1} */
mpz_tdiv_r (V, T1, n);
res = SIZ (V) == 0;
if (!res && b0 > 1) {
/* V_k and Q^k will be needed for further check, compute them. */
/* FIXME: Here we compute V_k^2 and store V_k, but the former */
/* will be recomputed by the calling function, shoul we store */
/* that instead? */
mpz_mul (T2, T1, T1); /* V_k^2 */
mpz_mul (T1, Qk, Qk); /* P^2 U_k^2 = U_k^2 */
mpz_sub (T2, T2, T1);
ASSERT (SIZ (T2) == 0 || PTR (T2) [0] % 4 == 0);
mpz_tdiv_q_2exp (T2, T2, 2); /* (V_k^2 - P^2 U_k^2) / 4 */
if (Q > 0) /* (V_k^2 - (P^2 -4Q) U_k^2) / 4 = Q^k */
mpz_addmul_ui (T2, T1, Q);
else
mpz_submul_ui (T2, T1, NEG_CAST (unsigned long, Q));
mpz_tdiv_r (Qk, T2, n);
}
}
return res;
}

View File

@@ -0,0 +1,94 @@
/* mpz_lucnum2_ui -- calculate Lucas numbers.
Copyright 2001, 2003, 2005, 2012, 2015, 2016, 2018 Free Software
Foundation, Inc.
This file is part of the GNU MP Library.
The GNU MP Library is free software; you can redistribute it and/or modify
it under the terms of either:
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
or
* the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any
later version.
or both in parallel, as here.
The GNU MP Library 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 copies of the GNU General Public License and the
GNU Lesser General Public License along with the GNU MP Library. If not,
see https://www.gnu.org/licenses/. */
#include <stdio.h>
#include "gmp-impl.h"
void
mpz_lucnum2_ui (mpz_ptr ln, mpz_ptr lnsub1, unsigned long n)
{
mp_ptr lp, l1p, f1p;
mp_size_t size;
mp_limb_t c;
TMP_DECL;
ASSERT (ln != lnsub1);
/* handle small n quickly, and hide the special case for L[-1]=-1 */
if (n <= FIB_TABLE_LUCNUM_LIMIT)
{
mp_limb_t f = FIB_TABLE (n);
mp_limb_t f1 = FIB_TABLE ((int) n - 1);
/* L[n] = F[n] + 2F[n-1] */
MPZ_NEWALLOC (ln, 1)[0] = f + 2*f1;
SIZ(ln) = 1;
/* L[n-1] = 2F[n] - F[n-1], but allow for L[-1]=-1 */
MPZ_NEWALLOC (lnsub1, 1)[0] = (n == 0 ? 1 : 2*f - f1);
SIZ(lnsub1) = (n == 0 ? -1 : 1);
return;
}
TMP_MARK;
size = MPN_FIB2_SIZE (n);
f1p = TMP_ALLOC_LIMBS (size);
lp = MPZ_NEWALLOC (ln, size+1);
l1p = MPZ_NEWALLOC (lnsub1, size+1);
size = mpn_fib2_ui (l1p, f1p, n);
/* L[n] = F[n] + 2F[n-1] */
#if HAVE_NATIVE_mpn_addlsh1_n
c = mpn_addlsh1_n (lp, l1p, f1p, size);
#else
c = mpn_lshift (lp, f1p, size, 1);
c += mpn_add_n (lp, lp, l1p, size);
#endif
lp[size] = c;
SIZ(ln) = size + (c != 0);
/* L[n-1] = 2F[n] - F[n-1] */
#if HAVE_NATIVE_mpn_rsblsh1_n
c = mpn_rsblsh1_n (l1p, f1p, l1p, size);
#else
c = mpn_lshift (l1p, l1p, size, 1);
c -= mpn_sub_n (l1p, l1p, f1p, size);
#endif
ASSERT ((mp_limb_signed_t) c >= 0);
l1p[size] = c;
SIZ(lnsub1) = size + (c != 0);
TMP_FREE;
}

View File

@@ -0,0 +1,208 @@
/* mpz_lucnum_ui -- calculate Lucas number.
Copyright 2001, 2003, 2005, 2011, 2012, 2015, 2016 Free Software Foundation, Inc.
This file is part of the GNU MP Library.
The GNU MP Library is free software; you can redistribute it and/or modify
it under the terms of either:
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
or
* the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any
later version.
or both in parallel, as here.
The GNU MP Library 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 copies of the GNU General Public License and the
GNU Lesser General Public License along with the GNU MP Library. If not,
see https://www.gnu.org/licenses/. */
#include <stdio.h>
#include "gmp-impl.h"
/* change this to "#define TRACE(x) x" for diagnostics */
#define TRACE(x)
/* Notes:
For the +4 in L[2k+1] when k is even, all L[4m+3] == 4, 5 or 7 mod 8, so
there can't be an overflow applying +4 to just the low limb (since that
would leave 0, 1, 2 or 3 mod 8).
For the -4 in L[2k+1] when k is even, it seems (no proof) that
L[3*2^(b-2)-3] == -4 mod 2^b, so for instance with a 32-bit limb
L[0xBFFFFFFD] == 0xFFFFFFFC mod 2^32, and this implies a borrow from the
low limb. Obviously L[0xBFFFFFFD] is a huge number, but it's at least
conceivable to calculate it, so it probably should be handled.
For the -2 in L[2k] with k even, it seems (no proof) L[2^(b-1)] == -1 mod
2^b, so for instance in 32-bits L[0x80000000] has a low limb of
0xFFFFFFFF so there would have been a borrow. Again L[0x80000000] is
obviously huge, but probably should be made to work. */
void
mpz_lucnum_ui (mpz_ptr ln, unsigned long n)
{
mp_size_t lalloc, xalloc, lsize, xsize;
mp_ptr lp, xp;
mp_limb_t c;
int zeros;
TMP_DECL;
TRACE (printf ("mpn_lucnum_ui n=%lu\n", n));
if (n <= FIB_TABLE_LUCNUM_LIMIT)
{
/* L[n] = F[n] + 2F[n-1] */
MPZ_NEWALLOC (ln, 1)[0] = FIB_TABLE(n) + 2 * FIB_TABLE ((int) n - 1);
SIZ(ln) = 1;
return;
}
/* +1 since L[n]=F[n]+2F[n-1] might be 1 limb bigger than F[n], further +1
since square or mul used below might need an extra limb over the true
size */
lalloc = MPN_FIB2_SIZE (n) + 2;
lp = MPZ_NEWALLOC (ln, lalloc);
TMP_MARK;
xalloc = lalloc;
xp = TMP_ALLOC_LIMBS (xalloc);
/* Strip trailing zeros from n, until either an odd number is reached
where the L[2k+1] formula can be used, or until n fits within the
FIB_TABLE data. The table is preferred of course. */
zeros = 0;
for (;;)
{
if (n & 1)
{
/* L[2k+1] = 5*F[k-1]*(2*F[k]+F[k-1]) - 4*(-1)^k */
mp_size_t yalloc, ysize;
mp_ptr yp;
TRACE (printf (" initial odd n=%lu\n", n));
yalloc = MPN_FIB2_SIZE (n/2);
yp = TMP_ALLOC_LIMBS (yalloc);
ASSERT (xalloc >= yalloc);
xsize = mpn_fib2_ui (xp, yp, n/2);
/* possible high zero on F[k-1] */
ysize = xsize;
ysize -= (yp[ysize-1] == 0);
ASSERT (yp[ysize-1] != 0);
/* xp = 2*F[k] + F[k-1] */
#if HAVE_NATIVE_mpn_addlsh1_n
c = mpn_addlsh1_n (xp, yp, xp, xsize);
#else
c = mpn_lshift (xp, xp, xsize, 1);
c += mpn_add_n (xp, xp, yp, xsize);
#endif
ASSERT (xalloc >= xsize+1);
xp[xsize] = c;
xsize += (c != 0);
ASSERT (xp[xsize-1] != 0);
ASSERT (lalloc >= xsize + ysize);
c = mpn_mul (lp, xp, xsize, yp, ysize);
lsize = xsize + ysize;
lsize -= (c == 0);
/* lp = 5*lp */
#if HAVE_NATIVE_mpn_addlsh2_n
c = mpn_addlsh2_n (lp, lp, lp, lsize);
#else
/* FIXME: Is this faster than mpn_mul_1 ? */
c = mpn_lshift (xp, lp, lsize, 2);
c += mpn_add_n (lp, lp, xp, lsize);
#endif
ASSERT (lalloc >= lsize+1);
lp[lsize] = c;
lsize += (c != 0);
/* lp = lp - 4*(-1)^k */
if (n & 2)
{
/* no overflow, see comments above */
ASSERT (lp[0] <= MP_LIMB_T_MAX-4);
lp[0] += 4;
}
else
{
/* won't go negative */
MPN_DECR_U (lp, lsize, CNST_LIMB(4));
}
TRACE (mpn_trace (" l",lp, lsize));
break;
}
MP_PTR_SWAP (xp, lp); /* balance the swaps wanted in the L[2k] below */
zeros++;
n /= 2;
if (n <= FIB_TABLE_LUCNUM_LIMIT)
{
/* L[n] = F[n] + 2F[n-1] */
lp[0] = FIB_TABLE (n) + 2 * FIB_TABLE ((int) n - 1);
lsize = 1;
TRACE (printf (" initial small n=%lu\n", n);
mpn_trace (" l",lp, lsize));
break;
}
}
for ( ; zeros != 0; zeros--)
{
/* L[2k] = L[k]^2 + 2*(-1)^k */
TRACE (printf (" zeros=%d\n", zeros));
ASSERT (xalloc >= 2*lsize);
mpn_sqr (xp, lp, lsize);
lsize *= 2;
lsize -= (xp[lsize-1] == 0);
/* First time around the loop k==n determines (-1)^k, after that k is
always even and we set n=0 to indicate that. */
if (n & 1)
{
/* L[n]^2 == 0 or 1 mod 4, like all squares, so +2 gives no carry */
ASSERT (xp[0] <= MP_LIMB_T_MAX-2);
xp[0] += 2;
n = 0;
}
else
{
/* won't go negative */
MPN_DECR_U (xp, lsize, CNST_LIMB(2));
}
MP_PTR_SWAP (xp, lp);
ASSERT (lp[lsize-1] != 0);
}
/* should end up in the right spot after all the xp/lp swaps */
ASSERT (lp == PTR(ln));
SIZ(ln) = lsize;
TMP_FREE;
}

Some files were not shown because too many files have changed in this diff Show More