[AC 21.5] MPIR support
11 years, 3 months
Jerry James
APPROVE COMMIT 21.5
On Mon, Jun 17, 2013 at 7:54 PM, Stephen J. Turnbull <stephen(a)xemacs.org> wrote:
> +@item ratio
> +Then @code{ratiop(x)} is false for all x. Any attempt to create a ratio
> +causes an error to be raised. We would eventually like to define our
> +own structure consisting of two @code{Lisp_Object}s, which are presumed
> +to be integers (i.e., either fixnums or bignums).
>
> I don't agree with this. If we really want ratios to always be
> available, we should require one of the libraries, and bundle it if
> necessary. But I'm not sure it's not more trouble than it's worth. I
> agree that ratios are much more Lispy than floats, but really, given
> that everybody has floats in hardware, aren't they good enough?
Yes, I was recycling some old text here. On second thought, I agree
with you. If you want ratios, use one of the 3rd party libraries. I
have removed this text.
> On second thought, doesn't calc already provide this?
It does. It's very slow, ,though.
> SXEmacs apparently supports a pile of other numeric libraries. Is it
> worth asking for volunteers to add those?
I'm not sure it is. The BSDs all have BSD MP. Pretty much every
Linux distribution has GMP, and many have MPIR. GMP and MPIR are both
available on Windows, as well as several commercial Unices. I'm not
sure who we would be targeting with other numeric libraries.
Performance hasn't really been an issue in the past. It might become
more of an issue if some applications pop up that use bignums, ratios,
or bigfloats heavily. So far I have not seen any such applications,
though.
> +C code should use one of the following macros to create a Lisp integer,
> +depending on the type of the C integer to be converted.
> +@itemize @bullet
> +@item
> +@code{make_fixnum(x)} if x is guaranteed to fit into a Lisp fixnum.
>
> This is an optimization?
If the compiler can tell that the parameter is always in the fixnum
range, then a decent C optimizer should compile the two forms down to
the same code. If the compiler can't tell, but the human programmer
can, then it is an optimization. I think of it as more signaling my
intentions to other programmers: "I intend this to be used for fixnum
computations only."
I have added some text to clarify this point.
> +@item
> +@code{make_integer(x)} if x is a signed C integer of any type.
> +@item
> +@code{make_unsigned_integer(x)} if x is an unsigned C integer of any type.
> +@end itemize
>
> I believe these make fixnums when possible. That should be noted here.
Done.
> Which library, if either, do you recommend? If the recommendation is
> a strong preference, maybe it's worth noting here with your name and a
> date attached. Something like
I don't have a preference. I have seen MPIR programmers claim that
MPIR is faster and uses less memory than GMP, but I have no data
either way. I suspect that a typical XEmacs load won't stress either
library, so the difference is probably nothing to write home about.
For that reason, I decline to give a preference at this time.
I am attaching the revised patch which I will commit shortly.
--
Jerry James
http://www.jamezone.org/
_______________________________________________
XEmacs-Patches mailing list
XEmacs-Patches(a)xemacs.org
http://lists.xemacs.org/mailman/listinfo/xemacs-patches
commit/XEmacs: Jerry James: Support bignums with MPIR. Add documentation on the bignum, ratio,
11 years, 3 months
Bitbucket
1 new commit in XEmacs:
https://bitbucket.org/xemacs/xemacs/commits/a2912073be85/
Changeset: a2912073be85
User: Jerry James
Date: 2013-06-19 17:30:30
Summary: Support bignums with MPIR. Add documentation on the bignum, ratio,
and bigfloat implementations. See xemacs-patches message with ID
<CAHCOHQkytZao7Uk9ggeo1HKKJtN1bqO054X2mPsGYyQFjbHrZA(a)mail.gmail.com>
and following messages.
Affected #: 15 files
diff -r f6af091ac6548f5e840cb3c31107474eda04f1cb -r a2912073be852d27a0589444677b96ad7027f2e3 ChangeLog
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
+2013-06-17 Jerry James <james(a)xemacs.org>
+
+ * configure.ac: Support bignums with MPIR.
+
2013-06-17 Jerry James <james(a)xemacs.org>
* configure.ac: Add check for mp_set_memory_functions.
diff -r f6af091ac6548f5e840cb3c31107474eda04f1cb -r a2912073be852d27a0589444677b96ad7027f2e3 configure
--- a/configure
+++ b/configure
@@ -1968,7 +1968,8 @@
loaded libraries (Dynamic Shared Objects).
--with-bignum=TYPE Compile in support for bignums, ratios, or bigfloats
using library support. TYPE must be one of "gmp"
- (for GNU MP), "mp" (for BSD MP), or "no" (disabled).
+ (for GNU MP), "mpir" (for MPIR), "mp" (for BSD MP),
+ or "no" (disabled).
Platform Specific options
-------------------------
@@ -5178,14 +5179,14 @@
enableval="$with_bignum"
withval="$with_bignum"
_bignum_bogus=yes
- for x in no gmp mp ; do
+ for x in no gmp mpir mp ; do
if test $x = $with_bignum ; then
_bignum_bogus=no
fi
done
if test "$_bignum_bogus" = "yes" ; then
(echo "$progname: Usage error:"
-echo " " "The --with-bignum option must have one of these values: \`no',\`gmp',\`mp'."
+echo " " "The --with-bignum option must have one of these values: \`no',\`gmp',\`mpir',\`mp'."
echo " Use \`$progname --help' to show usage.") >&2 && exit 1
fi
unset _bignum_bogus
@@ -20779,6 +20780,62 @@
else
{ echo "Error:" "Required GMP numeric support cannot be provided." >&2; exit 1; }
fi
+elif test "$with_bignum" = "mpir"; then
+ ac_fn_c_check_header_mongrel "$LINENO" "mpir.h" "ac_cv_header_mpir_h" "$ac_includes_default"
+if test "x$ac_cv_header_mpir_h" = xyes; then :
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for __gmpz_init in -lmpir" >&5
+$as_echo_n "checking for __gmpz_init in -lmpir... " >&6; }
+if ${ac_cv_lib_mpir___gmpz_init+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lmpir $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char __gmpz_init ();
+int
+main ()
+{
+return __gmpz_init ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_mpir___gmpz_init=yes
+else
+ ac_cv_lib_mpir___gmpz_init=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_mpir___gmpz_init" >&5
+$as_echo "$ac_cv_lib_mpir___gmpz_init" >&6; }
+if test "x$ac_cv_lib_mpir___gmpz_init" = xyes; then :
+ have_mpz_init=yes
+fi
+
+fi
+
+
+ if test "$have_mpz_init" = "yes"; then
+ $as_echo "#define WITH_NUMBER_TYPES 1" >>confdefs.h
+
+ $as_echo "#define WITH_MPIR 1" >>confdefs.h
+
+ LIBS="-lmpir $LIBS" && if test "$verbose" = "yes"; then echo " Prepending \"-lmpir\" to \$LIBS"; fi
+ else
+ { echo "Error:" "Required MPIR numeric support cannot be provided." >&2; exit 1; }
+ fi
elif test "$with_bignum" = "mp"; then
for library in "" "-lcrypto"; do
ac_fn_c_check_header_mongrel "$LINENO" "mp.h" "ac_cv_header_mp_h" "$ac_includes_default"
@@ -21728,6 +21785,7 @@
test "$with_dnet" = yes && echo " Compiling in support for DNET."
test "$with_modules" = "yes" && echo " Compiling in support for dynamic shared object modules."
test "$with_bignum" = "gmp" && echo " Compiling in support for more number types using the GNU MP library."
+test "$with_bignum" = "mpir" && echo " Compiling in support for more number types using the MPIR library."
test "$with_bignum" = "mp" && echo " Compiling in support for more number types using the BSD MP library."
if test "$with_union_type" = yes ; then
echo " Using the union type for Lisp_Objects."
diff -r f6af091ac6548f5e840cb3c31107474eda04f1cb -r a2912073be852d27a0589444677b96ad7027f2e3 configure.ac
--- a/configure.ac
+++ b/configure.ac
@@ -964,8 +964,9 @@
XE_KEYWORD_ARG([bignum],
AS_HELP_STRING([--with-bignum=TYPE],[Compile in support for bignums, ratios, or bigfloats
using library support. TYPE must be one of "gmp"
- (for GNU MP), "mp" (for BSD MP), or "no" (disabled).]),
- [], [with_bignum="no"],[no,gmp,mp])
+ (for GNU MP), "mpir" (for MPIR), "mp" (for BSD MP),
+ or "no" (disabled).]),
+ [], [with_bignum="no"],[no,gmp,mpir,mp])
dnl
XE_HELP_SUBSECTION([Platform Specific options])
XE_MERGED_ARG([workshop],
@@ -5264,6 +5265,16 @@
else
XE_DIE("Required GMP numeric support cannot be provided.")
fi
+elif test "$with_bignum" = "mpir"; then
+ AC_CHECK_HEADER(mpir.h, [
+ AC_CHECK_LIB(mpir, __gmpz_init, have_mpz_init=yes)])
+ if test "$have_mpz_init" = "yes"; then
+ AC_DEFINE(WITH_NUMBER_TYPES)
+ AC_DEFINE(WITH_MPIR)
+ XE_PREPEND(-lmpir, LIBS)
+ else
+ XE_DIE("Required MPIR numeric support cannot be provided.")
+ fi
elif test "$with_bignum" = "mp"; then
for library in "" "-lcrypto"; do
AC_CHECK_HEADER(mp.h, [
@@ -5932,6 +5943,7 @@
test "$with_dnet" = yes && echo " Compiling in support for DNET."
test "$with_modules" = "yes" && echo " Compiling in support for dynamic shared object modules."
test "$with_bignum" = "gmp" && echo " Compiling in support for more number types using the GNU MP library."
+test "$with_bignum" = "mpir" && echo " Compiling in support for more number types using the MPIR library."
test "$with_bignum" = "mp" && echo " Compiling in support for more number types using the BSD MP library."
if test "$with_union_type" = yes ; then
echo " Using the union type for Lisp_Objects."
diff -r f6af091ac6548f5e840cb3c31107474eda04f1cb -r a2912073be852d27a0589444677b96ad7027f2e3 man/ChangeLog
--- a/man/ChangeLog
+++ b/man/ChangeLog
@@ -1,3 +1,18 @@
+2013-06-17 Jerry James <james(a)xemacs.org>
+
+ * internals/internals.texi (Numeric Types): New chapter describing
+ the implementation of bignums, ratios, and bigfloats.
+ * lispref/numbers.texi (The Bignum Extension): Update description
+ to include MPIR, fix broken URLs, and note that BSD MP support is
+ now more complete.
+ (Bignum Basics): Note MPIR support.
+ (Ratio Basics): Add a missing comma.
+ (Bigfloat Basics): Fix an incomplete sentence and add examples.
+ * xemacs-faq.texi (Q7.2.1): Update description to include MPIR,
+ note that BSD MP support is now more complete, and remove the
+ paragraph where I promise to write internals documentation.
+ (Q7.2.3): Update ancient section that mentions the Pentium III.
+
2013-01-22 Jerry James <james(a)xemacs.org>
* lispref/glyphs.texi (Image Instantiators): Add :visible to the
diff -r f6af091ac6548f5e840cb3c31107474eda04f1cb -r a2912073be852d27a0589444677b96ad7027f2e3 man/internals/internals.texi
--- a/man/internals/internals.texi
+++ b/man/internals/internals.texi
@@ -1,4 +1,4 @@
- \input texinfo @c -*-texinfo-*-
+\input texinfo @c -*-texinfo-*-
@c %**start of header
@setfilename ../../info/internals.info
@settitle XEmacs Internals Manual
@@ -88,6 +88,7 @@
@author Matthias Neubauer
@author Olivier Galibert
@author Andy Piper
+@author Jerry James
@page
@@ -353,6 +354,7 @@
* CVS Techniques::
* XEmacs from the Inside::
* Basic Types::
+* Numeric Types::
* Low-Level Allocation::
* The XEmacs Object System (Abstractly Speaking)::
* How Lisp Objects Are Represented in C::
@@ -3143,12 +3145,14 @@
@item @file{nt.c} @tab
@item @file{ntheap.c} @tab
@item @file{ntplay.c} @tab
-@item @file{number-gmp.c} @tab
-@item @file{number-gmp.h} @tab
-@item @file{number-mp.c} @tab
-@item @file{number-mp.h} @tab
-@item @file{number.c} @tab
-@item @file{number.h} @tab
+@item @file{number-gmp.c} @tab @ref{GMP and MPIR driver}
+@item @file{number-gmp.h} @tab @ref{GMP and MPIR driver}
+@item @file{number-mp.c} @tab @ref{BSD MP driver}
+@item @file{number-mp.h} @tab @ref{BSD MP driver}
+@item @file{number-mpir.c} @tab @ref{GMP and MPIR driver}
+@item @file{number-mpir.h} @tab @ref{GMP and MPIR driver}
+@item @file{number.c} @tab @ref{Abstract Numeric Interface}
+@item @file{number.h} @tab @ref{Abstract Numeric Interface}
@item @file{fontcolor-gtk-impl.h} @tab
@item @file{fontcolor-gtk.c} @tab
@item @file{fontcolor-gtk.h} @tab
@@ -7230,14 +7234,569 @@
of obscure and unwanted interactions occurring than if they were to
change the C code.
-@node Basic Types, Low-Level Allocation, XEmacs from the Inside, Top
+@node Basic Types, Numeric Types, XEmacs from the Inside, Top
@chapter Basic Types
@cindex basic types
@cindex types, basic
Not yet documented.
-@node Low-Level Allocation, The XEmacs Object System (Abstractly Speaking), Basic Types, Top
+@node Numeric Types, Low-Level Allocation, Basic Types, Top
+@chapter Numeric Types
+@cindex numeric types
+@cindex types, numeric
+
+@menu
+* Abstract Numeric Interface::
+* GMP and MPIR driver::
+* BSD MP driver::
+* Numeric driver interface::
+@end menu
+
+@node Abstract Numeric Interface, GMP and MPIR driver, Numeric Types, Numeric Types
+@section Abstract Interface
+@cindex abstract numeric interface
+
+The following types are always defined in the same manner:
+@itemize
+@item fixnum
+Whatever fits in the @code{Lisp_Object} type.
+@item integer
+The union of the @code{fixnum} and @code{bignum} types.
+@item rational
+The union of the @code{integer} and @code{ratio} types.
+@item float
+The equivalent of a C @code{double}.
+@item floating
+The union of the @code{float} and @code{bigfloat} types.
+@item real
+The union of the @code{rational} and @code{floating} types.
+@item number
+The union of the @code{real} and @code{complex} types. Since there is
+no @code{complex} type, this is currently equivalent to the @code{real}
+type.
+@end itemize
+
+The remaining types (@code{bignum}, @code{ratio}, and @code{bigfloat})
+are defined by library-specific drivers, as detailed in the remaining
+sections of this chapter. A given driver may define one or more of
+these types to be empty. In fact, the default configuration makes all
+three types empty, so that @code{integer} and @code{rational} are the
+same types as @code{fixnum}, etc. The configure script sets zero or
+more of the symbols @code{HAVE_BIGNUM}, @code{HAVE_RATIO}, and
+@code{HAVE_BIGFLOAT} to indicate which types are nonempty. These are
+the consequences of an empty type:
+@itemize
+@item bignum
+Then @code{bignump(x)} is false for all x. Any attempt to create a
+bignum causes an error to be raised.
+@item ratio
+Then @code{ratiop(x)} is false for all x. Any attempt to create a ratio
+causes an error to be raised.
+@item bigfloat
+Then @code{bigfloat(x)} is false for all x. Any attempt to create a
+bigfloat causes an error to be raised.
+@end itemize
+
+We @code{(provide)} the following symbols, so that Lisp code can
+determine when the various numeric types are available for use:
+@itemize @bullet
+@item
+@code{(provide 'bignum)} if @code{HAVE_BIGNUM} is set
+@item
+@code{(provde 'ratio)} if @code{HAVE_RATIO} is set
+@item
+@code{(provide 'bigfloat)} if @code{HAVE_BIGFLOAT} is set
+@end itemize
+
+C code should use one of the following macros to create a Lisp integer,
+depending on the type of the C integer to be converted.
+@itemize @bullet
+@item
+@code{make_fixnum(x)} if x is guaranteed to fit into a Lisp fixnum.
+@item
+@code{make_integer(x)} if x is a signed C integer of any type.
+@item
+@code{make_unsigned_integer(x)} if x is an unsigned C integer of any type.
+@end itemize
+
+The @code{make_integer(x)} and @code{make_unsigned_integer(x)} macros
+both create a fixnum if possible, and a bignum otherwise. The value
+@code{x} can be a C integer of any size up to and including the size
+of a C @code{long long int}. The @code{make_fixnum(x)} macro is
+intended to signal the programmer's intent that only fixnum-sized
+integers will be used. In some cases, if the compiler cannot prove
+that the parameter is always in the fixnum range, this macro is also a
+code optimization.
+
+@node GMP and MPIR driver, BSD MP driver, Abstract Numeric Interface, Numeric Types
+@section GMP driver
+@cindex gmp
+@cindex mpir
+
+The GNU Multiple Precision library (@uref{http://gmplib.org/}) and its
+fork, the Multiple Precision Integers and Rationals library
+(@uref{http://www.mpir.org/}), provide large integers, ratios, and
+floating point numbers. The same driver supports both GMP and MPIR, and
+provides all 3 of the optional types: bignums, ratios, and bigfloats,
+implemented with the types @code{mpz_t}, @code{mpq_t}, and @code{mpf_t},
+respectively. Most of the abstract numeric interface is defined in
+terms of macros that expand directly into GMP or MPIR API calls, since
+GMP and MPIR provide a rich interface.
+
+@node BSD MP driver, Numeric driver interface, GMP and MPIR driver, Numeric Types
+@section BSD MP driver
+@cindex BSD mp
+
+The BSD MP interface is less rich than its GMP and MPIR counterparts.
+It provides only large integers, implemented as type @code{MINT *};
+ratios and bigfloats are not available. BSD MP libraries are supplied
+by multiple vendors, with some small variations. This driver is
+intended to work with any variation.
+
+Some BSD MP libraries use function names that are likely cause name
+collisions, such as @code{gcd}, @code{mult}, and @code{pow}. Others
+follow the Single Unix Specification recommendation (see
+@uref{http://www.unix.com/man-page/all/3mp/mp_mcmp/}) and prefix all of
+the function names with ``mp_'': @code{mp_gcd}, @code{mp_mult},
+@code{mp_pow}, etc. The XEmacs configure script detects which of the
+two interfaces is in use, and defines @code{MP_PREFIX} for the latter
+case. We use macros (@code{MP_MULT}, etc.) to hide this difference.
+
+Another variation is that some, but not all, BSD MP libraries supply a
+function named @code{move} or @code{mp_move} that copies its first
+argument into its second argument. We define the move operation as
+setting the destination number to the source number plus zero for those
+libraries that do not supply this function.
+
+The BSD MP interface does not directly support many of the operations
+that we need, so the implementations sometimes consist of complex
+functions. See the implementation of @code{bignum_random}, for
+example.
+
+@node Numeric driver interface, , BSD MP driver, Numeric Types
+@section Numeric driver interface
+@cindex numeric driver interface
+
+@menu
+* Bignum interface::
+* Ratio interface::
+* Bigfloat interface::
+@end menu
+
+@node Bignum interface, Ratio interface, Numeric driver interface, Numeric driver interface
+@subsection Bignum interface
+@cindex bignum interface
+
+Each bignum implementation defines @code{HAVE_BIGNUM} and an appropriate
+bignum type. For example, the GMP driver uses this definition:
+
+@example
+typedef mpz_t bignum;
+@end example
+
+The following names are defined for each driver, either as real C
+functions or as C preprocessor macros.
+@itemize
+@item void bignum_init(bignum b)
+Does any necessary initialization before the bignum @code{b} can be
+used. This function typically allocates memory for the bignum.
+@item void bignum_fini(bignum b)
+Cleans up any resources held by the bignum @code{b}, typically
+deallocating the memory dedicated to that bignum. The object referred
+to by @code{b} must not be accessed after this call returns.
+@item unsigned int bignum_hashcode(bignum b)
+Returns a hash code for the bignum, suitable for use in XEmacs hash
+tables.
+@item int bignum_sign(bignum b)
+Returns a positive value, zero, or a negative value to indicate that
+@code{b} is positive, zero, or negative, respectively.
+@item int bignum_evenp(bignum b)
+Returns a nonzero value if @code{b} is an even number, zero if it is odd.
+@item int bignum_oddp(bignum b)
+Returns a nonzero value if @code{b} is an odd number, zero if it is even.
+@item int bignum_fits_int_p(bignum b)
+Returns a nonzero value if @code{b} can be represented in a C
+@code{int}, zero otherwise.
+@item int bignum_fits_uint_p(bignum b)
+Returns a nonzero value if @code{b} can be represented in a C
+@code{unsigned int}, zero otherwise.
+@item int bignum_fits_long_p(bignum b)
+Returns a nonzero value if @code{b} can be represented in a C
+@code{long int}, zero otherwise.
+@item int bignum_fits_ulong_p(bignum b)
+Returns a nonzero value if @code{b} can be represented in a C
+@code{unsigned long int}, zero otherwise.
+@item int bignum_fits_llong_p(bignum b)
+Returns a nonzero value if @code{b} can be represented in a C
+@code{long long int}, zero otherwise.
+@item int bignum_fits_ullong_p(bignum b)
+Returns a nonzero value if @code{b} can be represented in a C
+@code{unsigned long long int}, zero otherwise.
+@item void bignum_to_string(bignum b, int base)
+Converts @code{b} into a string representation using the given base,
+which is an integer between 2 and 36, inclusive.
+@item int bignum_to_int(bignum b)
+Converts @code{b} into a C @code{int}. If @code{b} does not fit into a
+C @code{int}, the results are undefined.
+@item unsigned int bignum_to_uint(bignum b)
+Converts @code{b} into a C @code{unsigned int}. If @code{b} does not
+fit into a C @code{unsigned int}, the results are undefined.
+@item long bignum_to_long(bignum b)
+Converts @code{b} into a C @code{long int}. If @code{b} does not fit
+into a C @code{long int}, the results are undefined.
+@item unsigned long bignum_to_ulong(bignum b)
+Converts @code{b} into a C @code{unsigned long int}. If @code{b} does
+not fit into a C @code{unsigned long int}, the results are undefined.
+@item long long bignum_to_llong(bignum b)
+Converts @code{b} into a C @code{long long int}. If @code{b} does not
+fit into a C @code{long long int}, the results are undefined.
+@item unsigned long long bignum_to_ullong(bignum b)
+Converts @code{b} into a C @code{unsigned long long int}. If @code{b}
+does not fit into a C @code{unsigned long long int}, the results are
+undefined.
+@item double bignum_to_double(bignum b)
+Converts @code{b} into a C @code{double}. If @code{b} is too large to
+represent as a C @code{double}, the results are implementation-specific.
+Typically, the result is positive or negative infinity, for
+implementations that can represent infinity.
+@item void bignum_set(bignum b1, bignum b2)
+Assigns the value of @code{b2} to the bignum @code{b1} by copying.
+@item void bignum_set_string(bignum b, const char *s, int base)
+Assigns @code{b} the value of the integer contained in string @code{s},
+which is a number in base @code{base}.
+@item void bignum_set_long(bignum b, long l)
+Assigns @code{b} the value of the long integer @code{l}.
+@item void bignum_set_ulong(bignum b, unsigned long l)
+Assigns @code{b} the value of the unsigned long integer @code{l}.
+@item void bignum_set_llong(bignum b, long long l)
+Assigns @code{b} the value of the long long integer @code{l}.
+@item void bignum_set_ullong(bignum b, unsigned long long l)
+Assigns @code{b} the value of the unsigned long long integer @code{l}.
+@item void bignum_set_double(bignum b, double d)
+Assigns @code{b} to the truncated value of @code{d}; i.e, the fractional
+part of @code{d} is dropped.
+@item void bignum_set_ratio(bignum b, ratio r)
+Assigns @code{b} to the truncated value of @code{r}; i.e., the
+non-integer part of @code{r} is dropped. This function exists only if
+the driver supports ratios.
+@item void bignum_set_bigfloat(bignum b, bigfloat f)
+Assigns @code{b} to the truncated value of @code{f}; i.e., the
+fractional part of @code{f} is dropped. This function exists only if
+the driver supports bigfloats.
+@item int bignum_cmp(bignum b1, bignum b2)
+Returns a positive value, zero, or a negative value as @code{b1} is
+greater than, equal to, or less than @code{b2}, respectively.
+@item int bignum_lt(bignum b1, bignum b2)
+Returns nonzero if @code{b1} is less than @code{b2}, zero otherwise.
+@item int bignum_le(bignum b1, bignum b2)
+Returns nonzero if @code{b1} is less than or equal to @code{b2}, zero
+otherwise.
+@item int bignum_eql(bignum b1, bignum b2)
+Returns nonzero if @code{b1} is equal to @code{b2}, zero otherwise.
+@item int bignum_ge(bignum b1, bignum b2)
+Returns nonzero if @code{b1} is greater than or equal to @code{b2}, zero
+otherwise.
+@item int bignum_gt(bignum b1, bignum b2)
+Returns nonzero if @code{b1} is greater than @code{b2}, zero otherwise.
+@item void bignum_neg(bignum b, bignum b2)
+Sets @code{b} to the negation of @code{b2}.
+@item void bignum_abs(bignum b, bignum b2)
+Sets @code{b} to the absolute value of @code{b2}.
+@item void bignum_add(bignum b, bignum b1, bignum b2)
+Sets @code{b} to the sum of @code{b1} and @code{b2}.
+@item void bignum_sub(bignum b, bignum b1, bignum b2)
+Sets @code{b} to the value of @code{b1} minus @code{b2}.
+@item void bignum_mul(bignum b, bignum b1, bignum b2)
+Sets @code{b} to the product of @code{b1} and @code{b2}.
+@item int bignum_divisible_p(bignum b1, bignum b2)
+Returns nonzero if @code{b1} is evenly divisible by @code{b2}.
+@item void bignum_div(bignum b, bignum b1, bignum b2)
+Sets @code{b} to the truncated value of @code{b1} divided by @code{b2}.
+That is, this function rounds toward zero.
+@item void bignum_ceil(bignum b, bignum b1, bignum b2)
+Sets @code{b} to the ceiling of @code{b1} divided by @code{b2}. That
+is, ths function rounds toward positive infinity.
+@item void bignum_floor(bignum b, bignum b1, bignum b2)
+Sets @code{b} to the floor of @code{b1} divided by @code{b2}. That is,
+ths function rounds toward negative infinity.
+@item void bignum_mod(bignum b, bignum b1, bignum b2)
+Sets @code{b} to @code{b1} mod @code{b2}; i.e., the remainder after
+dividing @code{b1} by @code{b2}. The sign is ignored; @code{b} is
+always nonnegative after this operation.
+@item void bignum_pow(bignum res, bignum b, unsigned int pow)
+Sets @code{res} to @code{b} to the @code{pow}th power.
+@item void bignum_gcd(bignum res, bignum b1, bignum b2)
+Sets @code{res} to the greatest common divisor of @code{b1} and
+@code{b2}.
+@item void bignum_lcm(bignum res, bignum b1, bignum b2)
+Sets @code{res} to the least common multiple of @code{b1} and @code{b2}.
+@item void bignum_and(bignum res, bignum b1, bignum b2)
+Sets @code{res} to the bitwise AND of @code{b1} and @code{b2}.
+@item void bignum_ior(bignum res, bignum b1, bignum b2)
+Sets @code{res} to the bitwise inclusive OR of @code{b1} and @code{b2}.
+@item void bignum_xor(bignum res, bignum b1, bignum b2)
+Sets @code{res} to the bitwise exclusive OR of @code{b1} and @code{b2}.
+@item void bignum_not(bignum res, bignum b)
+Sets @code{res} to the bitwise NOT of @code{b}.
+@item void bignum_setbit(bignum b, unsigned int bit)
+Sets the @code{bit}th bit of @code{b} to one, where the zeroth bit is
+the least significant.
+@item void bignum_clrbit(bignum b, unsigned int bit)
+Clears the @code{bit}th bit of @code{b} (i.e., sets it to zero), where
+the zeroth bit is the least significant.
+@item int bignum_testbit(bignum b, unsigned int bit)
+Returns the @code{bit}th bit of @code{b}, where the zeroth bit is the
+least significant.
+@item void bignum_lshift(bignum res, bignum b, unsigned int bits)
+Sets @code{res} to the value of @code{b} shifted left by @code{bits}
+bits.
+@item void bignum_rshift(bignum res, bignum b, unsigned int bits)
+Sets @code{res} to the value of @code{b} shifted right by @code{bits}
+bits.
+@item void bignum_random_seed(unsigned int seed)
+If the implementing library has its own pseudorandom number generator,
+then this function seeds the generator. If there is no generator, this
+function is a no-op.
+@item void bignum_random(bignum res, bignum limit)
+Sets @code{res} to a random number between zero (inclusive) and
+@code{limit} (exclusive).
+@end itemize
+
+@node Ratio interface, Bigfloat interface, Bignum interface, Numeric driver interface
+@subsection Ratio interface
+@cindex ratio interface
+
+Each ratio implementation defines @code{HAVE_RATIO} and an appropriate
+ratio type. For example, the GMP driver uses this definition:
+
+@example
+typedef mpq_t ratio;
+@end example
+
+The following names are defined for each driver, either as real C
+functions or as C preprocessor macros.
+@itemize
+@item void ratio_init(ratio r)
+Does any necessary initialization before the ratio @code{r} can be
+used. This function typically allocates memory for the ratio.
+@item void ratio_fini(ratio r)
+Cleans up any resources held by the ratio @code{r}, typically
+deallocating the memory dedicated to that ratio. The object referred
+to by @code{r} must not be accessed after this call returns.
+@item unsigned int ratio_hashcode(ratio r)
+Returns a hash code for the ratio, suitable for use in XEmacs hash
+tables.
+@item int ratio_sign(ratio r)
+Returns a positive value, zero, or a negative value to indicate that
+@code{r} is positive, zero, or negative, respectively.
+@item bignum ratio_numerator(ratio r)
+Returns the numerator of @code{r}.
+@item bignum ratio_denominator(ratio r)
+Returns the denominator of @code{r}.
+@item void ratio_canonicalize(ratio r)
+Removes any common factors from the numerator and denominator of
+@code{r}.
+@item void ratio_to_string(ratio r, int base)
+Converts @code{r} into a string representation using the given base,
+which is an integer between 2 and 36, inclusive.
+@item int ratio_to_int(ratio r)
+Converts @code{r} into a C @code{int} by truncating the ratio. If the
+truncation of @code{r} does not fit into a C @code{int}, the results are
+undefined.
+@item unsigned int ratio_to_uint(ratio r)
+Converts @code{r} into a C @code{unsigned int} by truncating the ratio.
+If the truncation of @code{r} does not fit into a C @code{unsigned int},
+the results are undefined.
+@item long ratio_to_long(ratio r)
+Converts @code{r} into a C @code{long int} by truncating the ratio. If
+the truncation of @code{r} does not fit into a C @code{long int}, the
+results are undefined.
+@item unsigned long ratio_to_ulong(ratio r)
+Converts @code{r} into a C @code{unsigned long int} by truncating the
+ratio. If @code{r} does not fit into a C @code{unsigned long int}, the
+results are undefined.
+@item double ratio_to_double(ratio r)
+Converts @code{r} into a C @code{double}. If @code{r} is too large to
+represent as a C @code{double}, the results are implementation-specific.
+Typically, the result is positive or negative infinity, for
+implementations that can represent infinity.
+@item void ratio_set(ratio r1, ratio r2)
+Assigns the value of @code{r2} to the ratio @code{r1} by copying.
+@item void ratio_set_string(ratio r, const char *s, int base)
+Assigns @code{r} the value of the ratio contained in string @code{s},
+which is a pair of numbers in base @code{base} separated by a forward
+slash.
+@item void ratio_set_long(ratio r, long l)
+Assigns @code{r} the value of the long integer @code{l}.
+@item void ratio_set_ulong(ratio r, unsigned long l)
+Assigns @code{r} the value of the unsigned long integer @code{l}.
+@item void ratio_set_double(ratio r, double d)
+Assigns @code{r} to the exact value of @code{d}. There is no rounding.
+@item void ratio_set_bignum(ratio r, bignum b)
+Assigns @code{r} to the value of @code{b}; i.e., the denominator is set
+to one.
+@item void ratio_set_bigfloat(ratio b, bigfloat f)
+Assigns @code{b} to the exact value of @code{f}. There is no rounding.
+This function exists only if the driver supports bigfloats.
+@item void ratio_set_long_ulong(ratio r, long num, unsigned long den)
+Assigns @code{r} the canonicalized ratio resulting from the division of
+@code{num} by @code{den}.
+@item void ratio_set_ulong_ulong(ratio r, unsigned long num, unsigned long den)
+Assigns @code{r} the canonicalized ratio resulting from the division of
+@code{num} by @code{den}.
+@item void ratio_set_bignum_bignum(ratio r, bignum num, bignum den)
+Assigns @code{r} the canonicalized ratio resulting from the division of
+@code{num} by @code{den}.
+@item int ratio_cmp(ratio r1, ratio r2)
+Returns a positive value, zero, or a negative value as @code{r1} is
+greater than, equal to, or less than @code{r2}, respectively.
+@item int ratio_lt(ratio r1, ratio r2)
+Returns nonzero if @code{r1} is less than @code{r2}, zero otherwise.
+@item int ratio_le(ratio r1, ratio r2)
+Returns nonzero if @code{r1} is less than or equal to @code{r2}, zero
+otherwise.
+@item int ratio_eql(ratio r1, ratio r2)
+Returns nonzero if @code{r1} is equal to @code{r2}, zero otherwise.
+@item int ratio_ge(ratio r1, ratio r2)
+Returns nonzero if @code{r1} is greater than or equal to @code{r2}, zero
+otherwise.
+@item int ratio_gt(ratio r1, ratio r2)
+Returns nonzero if @code{r1} is greater than @code{r2}, zero otherwise.
+@item void ratio_neg(ratio q, ratio q2)
+Sets @code{q} to the negation of @code{q2}.
+@item void ratio_abs(ratio q, ratio q2)
+Sets @code{q} to the absolute value of @code{q2}.
+@item void ratio_inv(ratio q, ratio q2)
+Sets @code{q} to the inverse of @code{q2}.
+@item void ratio_add(ratio res, ratio q1, ratio q2)
+Sets @code{res} to the sum of @code{q1} and @code{q2}.
+@item void ratio_sub(ratio res, ratio q1, ratio q2)
+Sets @code{res} to the value of @code{q1} minus @code{q2}.
+@item void ratio_mul(ratio res, ratio q1, ratio q2)
+Sets @code{res} to the product of @code{q1} and @code{q2}.
+@item void ratio_div(ratio res, ratio q1, ratio q2)
+Sets @code{res} to the value of @code{q1} divided by @code{q2}.
+@end itemize
+
+@node Bigfloat interface, , Ratio interface, Numeric driver interface
+@subsection Bigfloat interface
+@cindex bigfloat interface
+
+Each bigfloat implementation defines @code{HAVE_BIGFLOAT} and an
+appropriate bigfloat type. For example, the GMP driver uses this
+definition:
+
+@example
+typedef mpf_t bigfloat;
+@end example
+
+The following names are defined for each driver, either as real C
+functions or as C preprocessor macros.
+@itemize
+@item void bigfloat_init(bigfloat f)
+Does any necessary initialization before the bigfloat @code{f} can be
+used. This function typically allocates memory for the bigfloat.
+@item void bigfloat_init_prec(bigfloat f, unsigned int prec)
+Like @code{bigfloat_init}, but also sets the precision of @code{f} to
+@emph{at least} @code{prec} bits.
+@item void bigfloat_fini(bigfloat f)
+Cleans up any resources held by the bigfloat @code{f}, typically
+deallocating the memory dedicated to that bigfloat. The object referred
+to by @code{f} must not be accessed after this call returns.
+@item unsigned int bigfloat_hashcode(bigfloat f)
+Returns a hash code for the bigfloat, suitable for use in XEmacs hash
+tables.
+@item int bigfloat_sign(bigfloat f)
+Returns a positive value, zero, or a negative value to indicate that
+@code{f} is positive, zero, or negative, respectively.
+@item unsigned int bigfloat_get_prec(bigfloat f)
+Returns the precision of @code{f} in bits.
+@item void bigfloat_set_prec(bigfloat f, unsigned int prec)
+Sets the precision of @code{f} to @emph{at least} @code{prec} bits.
+@item void bigfloat_set_default_prec(unsigned int prec)
+Sets the default precision of newly created bigfloats.
+@item unsigned int bigfloat_get_default_prec(void)
+Gets the default precision of newly created bigfloats.
+@item void bigfloat_to_string(bigfloat f, int base)
+Converts @code{f} into a string representation using the given base,
+which is an integer between 2 and 36, inclusive.
+@item int bigfloat_to_int(bigfloat f)
+Converts @code{f} into a C @code{int} by truncating the bigfloat. If the
+truncation of @code{f} does not fit into a C @code{int}, the results are
+undefined.
+@item unsigned int bigfloat_to_uint(bigfloat f)
+Converts @code{f} into a C @code{unsigned int} by truncating the bigfloat.
+If the truncation of @code{f} does not fit into a C @code{unsigned int},
+the results are undefined.
+@item long bigfloat_to_long(bigfloat f)
+Converts @code{f} into a C @code{long int} by truncating the bigfloat. If
+the truncation of @code{f} does not fit into a C @code{long int}, the
+results are undefined.
+@item unsigned long bigfloat_to_ulong(bigfloat f)
+Converts @code{f} into a C @code{unsigned long int} by truncating the
+bigfloat. If @code{f} does not fit into a C @code{unsigned long int}, the
+results are undefined.
+@item double bigfloat_to_double(bigfloat f)
+Converts @code{f} into a C @code{double}. If @code{f} is too large to
+represent as a C @code{double}, the results are implementation-specific.
+Typically, the result is positive or negative infinity, for
+implementations that can represent infinity.
+@item void bigfloat_set(bigfloat f1, bigfloat f2)
+Assigns the value of @code{f2} to the bigfloat @code{f1} by copying.
+@item void bigfloat_set_string(bigfloat f, const char *s, int base)
+Assigns @code{f} the value of the bigfloat contained in string @code{s}.
+@item void bigfloat_set_long(bigfloat f, long l)
+Assigns @code{f} the value of the long integer @code{l}.
+@item void bigfloat_set_ulong(bigfloat f, unsigned long l)
+Assigns @code{f} the value of the unsigned long integer @code{l}.
+@item void bigfloat_set_double(bigfloat f, double d)
+Assigns @code{f} the value of @code{d}.
+@item void bigfloat_set_bignum(bigfloat f, bignum b)
+Assigns @code{f} to the value of @code{b}.
+@item void bigfloat_set_ratio(bigfloat b, ratio r)
+Assigns @code{b} to the result of dividing the numerator of @code{r} by
+its denominator.
+@item int bigfloat_cmp(bigfloat f1, bigfloat f2)
+Returns a positive value, zero, or a negative value as @code{f1} is
+greater than, equal to, or less than @code{f2}, respectively.
+@item int bigfloat_lt(bigfloat f1, bigfloat f2)
+Returns nonzero if @code{f1} is less than @code{f2}, zero otherwise.
+@item int bigfloat_le(bigfloat f1, bigfloat f2)
+Returns nonzero if @code{f1} is less than or equal to @code{f2}, zero
+otherwise.
+@item int bigfloat_eql(bigfloat f1, bigfloat f2)
+Returns nonzero if @code{f1} is equal to @code{f2}, zero otherwise.
+@item int bigfloat_ge(bigfloat f1, bigfloat f2)
+Returns nonzero if @code{f1} is greater than or equal to @code{f2}, zero
+otherwise.
+@item int bigfloat_gt(bigfloat f1, bigfloat f2)
+Returns nonzero if @code{f1} is greater than @code{f2}, zero otherwise.
+@item void bigfloat_neg(bigfloat f, bigfloat f2)
+Sets @code{f} to the negation of @code{f2}.
+@item void bigfloat_abs(bigfloat f, bigfloat f2)
+Sets @code{f} to the absolute value of @code{f2}.
+@item void bigfloat_add(bigfloat res, bigfloat f1, bigfloat f2)
+Sets @code{res} to the sum of @code{f1} and @code{f2}.
+@item void bigfloat_sub(bigfloat res, bigfloat f1, bigfloat f2)
+Sets @code{res} to the value of @code{f1} minus @code{f2}.
+@item void bigfloat_mul(bigfloat res, bigfloat f1, bigfloat f2)
+Sets @code{res} to the product of @code{f1} and @code{f2}.
+@item void bigfloat_div(bigfloat res, bigfloat f1, bigfloat f2)
+Sets @code{res} to the value of @code{f1} divided by @code{f2}.
+@item void bigfloat_ceil(bigfloat res, bigfloat f)
+Sets @code{res} to the ceiling of @code{f}.
+@item void bigfloat_floor(bigfloat res, bigfloat f)
+Sets @code{res} to the floor of @code{f}.
+@item void bigfloat_trunc(bigfloat res, bigfloat f)
+Sets @code{res} to the truncation of @code{f}.
+@item void bigfloat_sqrt(bigfloat res, bigfloat f)
+Sets @code{res} to the square root of @code{f}.
+@item void bigfloat_pow(bigfloat res, bigfloat f, unsigned int exp)
+Sets @code{res} to the value of @code{f} raised to the @code{exp}th power.
+@end itemize
+
+@node Low-Level Allocation, The XEmacs Object System (Abstractly Speaking), Numeric Types, Top
@chapter Low-Level Allocation
@cindex low-level allocation
@cindex allocation, low-level
@@ -21337,7 +21896,7 @@
@node Ben's separate stderr notes, , Subprocesses, Subprocesses
-@subsection Ben's separate stderr notes (probably obsolete)
+@section Ben's separate stderr notes (probably obsolete)
This node contains some notes that Ben kept on his separate subprocess
workspace. These notes probably describe changes and features that have
diff -r f6af091ac6548f5e840cb3c31107474eda04f1cb -r a2912073be852d27a0589444677b96ad7027f2e3 man/lispref/numbers.texi
--- a/man/lispref/numbers.texi
+++ b/man/lispref/numbers.texi
@@ -320,28 +320,29 @@
numbers is limited only by the amount of virtual memory (and time) you
can throw at them.
- As of 09 April 2004, support for the GNU Multiple Precision
-arithmetic library (GMP) is nearly complete, and support for the BSD
-Multiple Precision arithmetic library (MP) is being debugged. To enable
-bignum support using GMP (respectively MP), invoke configure with your
-usual options, and add @samp{--use-number-lib=gmp} (respectively
-@samp{--use-number-lib=mp}). The default is to disable bignum support,
-but if you are using a script to automate the build process, it may be
-convenient to explicitly disable support by @emph{appending}
-@samp{--use-number-lib=no} to your invocation of configure. GMP has an
-MP compatibility mode, but it is not recommended, as there remain poorly
-understood bugs (even more so than for other vendors' versions of MP).
+ XEmacs supports the GNU Multiple Precision arithmetic library (GMP),
+the Multiple Precision Integers and Rationals library (MPIR), and the
+BSD Multiple Precision arithmetic library (MP). To enable bignum
+support using GMP, MPIR, or MP, invoke configure with your usual options
+and add @samp{--use-number-lib=gmp}, @samp{--use-number-lib=mpir}, or
+@samp{--use-number-lib=mp}, respectively. The default is to disable
+bignum support, but if you are using a script to automate the build
+process, it may be convenient to explicitly disable support by
+@emph{appending} @samp{--use-number-lib=no} to your invocation of
+configure. GMP has an MP compatibility mode, but it is not recommended,
+as there remain poorly understood bugs (even more so than for other
+vendors' versions of MP).
- With GMP, exact arithmetic with integers and ratios of arbitrary
-precision and approximate (``floating point'') arithmetic of arbitrary
-precision are implemented efficiently in the library. (Note that
-numerical implementations are quite delicate and sensitive to
+ With GMP and MPIR, exact arithmetic with integers and ratios of
+arbitrary precision and approximate (``floating point'') arithmetic of
+arbitrary precision are implemented efficiently in the library. (Note
+that numerical implementations are quite delicate and sensitive to
optimization. If the library was poorly optimized for your hardware, as
is often the case with Linux distributions for 80x86, you may achieve
gains of @emph{several orders of magnitude} by rebuilding the MP
-library. See @uref{http://www.swox.com/gmp/gmp-speed.html}.) The MP
-implementation provides arbitrary precision integers. Ratios and arbitrary
-precision floats are not available with MP.
+library. See @uref{http://gmplib.org/gmpbench.html}.) The MP
+implementation provides arbitrary precision integers. Ratios and
+arbitrary precision floats are not available with MP.
If your code needs to run correctly whether or not the feature is
provided, you may test for the features @code{bignum}, @code{ratio}, and
@@ -363,14 +364,6 @@
are bigfloat, and bigfloats are only coerced to other numerical types by
explicit calls to the function @code{coerce}.
- Bignum support is incomplete. If you would like to help with bignum
-support, especially on BSD MP, please subscribe to the
-@uref{http://www.xemacs.org/Lists/#xemacs-beta, XEmacs Beta mailing
-list}, and book up on @file{number-gmp.h} and @file{number-mp.h}. Jerry
-has promised to write internals documentation eventually, but if your
-skills run more to analysis and documentation than to writing new code,
-feel free to fill in the gap!
-
@menu
* Bignum Basics:: Representation and range of integers.
* Ratio Basics:: Representation and range of rational numbers.
@@ -385,9 +378,9 @@
In most cases, bignum support should be transparent to users and Lisp
programmers. A bignum-enabled XEmacs will automatically convert from
-fixnums to bignums and back in pure integer arithmetic, and for GNU MP,
-from floats to bigfloats. (Bigfloats must be explicitly coerced to
-other types, even if they are exactly representable by less precise
+fixnums to bignums and back in pure integer arithmetic, and for GMP and
+MPIR, from floats to bigfloats. (Bigfloats must be explicitly coerced
+to other types, even if they are exactly representable by less precise
types.) The Lisp reader and printer have been enhanced to handle
bignums, as have the mathematical functions. Rationals (fixnums,
bignums, and ratios) are printed using the @samp{%d}, @samp{%o},
@@ -397,7 +390,7 @@
@node Ratio Basics
@subsection Ratio Basics
-Ratios, when available have the read syntax and print representation
+Ratios, when available, have the read syntax and print representation
@samp{3/5}. Like other rationals (fixnums and bignums), they are
printed using the @samp{%d}, @samp{%o}, @samp{%x}, and @samp{%u} format
conversions.
@@ -413,10 +406,36 @@
setting @code{default-float-precision} to a non-zero value. Precision
is given in bits, with a maximum precision of
@code{bigfloat-maximum-precision}.
-@c #### is this true?
-Bigfloats are created automatically when a number with yes
+@example
+(let* ((float1 (string-to-number "9999999999999999.99999999999999999999"))
+ (default-float-precision 256)
+ (float2 (string-to-number "9999999999999999.99999999999999999999")))
+ (+ (if (bigfloatp float1) 1 0)
+ (if (bigfloatp float2) 2 0)))
+ @result{} 2
+@end example
+@example
+(let* ((float1 (float 999999999999999999999999999999999999999999999999999999))
+ (default-float-precision 256)
+ (float2 (float 999999999999999999999999999999999999999999999999999999)))
+ (princ float1)
+ (terpri)
+ (princ float2)
+ (terpri))
+ @result{} 9.999999999999999e+53
+9.99999999999999999999999999999999999999999999999999999E53
+t
+@end example
+
+Explicit type coercion is also available, although then the precision of
+the bigfloat is no greater than the source type.
+
+@example
+(coerce 999999999999999 'bigfloat)
+ @result{} 9.99999999999999E14
+@end example
@node Canonicalization and Contagion
@subsection Canonicalization and Contagion
diff -r f6af091ac6548f5e840cb3c31107474eda04f1cb -r a2912073be852d27a0589444677b96ad7027f2e3 man/xemacs-faq.texi
--- a/man/xemacs-faq.texi
+++ b/man/xemacs-faq.texi
@@ -7950,19 +7950,19 @@
Thanks to @email{james@(a)xemacs.org, Jerry James}, XEmacs 21.5.18 and
later can use the capabilities of multiple-precision libraries that may
-be available for your platform. The GNU Multiple Precision (GMP) and
-BSD Multiple Precision (MP) libraries are partially supported. GMP
-gives you @dfn{bignums} (arbitrary precision integers), @dfn{ratios}
-(arbitrary precision fractions), and @dfn{bigfloats} (arbitrary
-precision floating point numbers). GNU MP is better-supported by XEmacs
-at the time of writing (2004-04-06). BSD MP support does not include
-ratios or bigfloats, and it throws errors that aren't understood.
+be available for your platform. The GNU Multiple Precision (GMP),
+Multiple Precision Integers and Rationals (MPIR), and BSD Multiple
+Precision (MP) libraries are supported. GMP and MPIR give you
+@dfn{bignums} (arbitrary precision integers), @dfn{ratios} (arbitrary
+precision fractions), and @dfn{bigfloats} (arbitrary precision floating
+point numbers). GMP and MPIR are better-supported by XEmacs. BSD MP
+support does not include ratios or bigfloats.
In most cases, bignum support should be transparent to users and Lisp
programmers. A bignum-enabled XEmacs will automatically convert from
-fixnums to bignums and back in pure integer arithmetic, and for GNU MP,
-from floats to bigfloats. (Bigfloats must be explicitly coerced to
-other types, even if they are exactly representable by less precise
+fixnums to bignums and back in pure integer arithmetic, and for GMP and
+MPIR, from floats to bigfloats. (Bigfloats must be explicitly coerced
+to other types, even if they are exactly representable by less precise
types.) The Lisp reader and printer have been enhanced to handle
bignums, as have the mathematical functions. Rationals (fixnums,
bignums, and ratios) are printed using the @samp{%d}, @samp{%o},
@@ -8002,17 +8002,9 @@
arbitrarily decide to hand you an unpleasant surprise rather than a
bignum @ref{Q7.2.2, XEmacs segfaults when I use very big numbers!}.
-To configure with GNU MP, add @samp{--use-number-lib=gmp}
-(@samp{--enable-bignum=gmp} in 21.5 or later) to your invocation of
-@file{configure}. For BSD MP, use @samp{--use-number-lib=mp}
-(@samp{--enable-bignum=mp} for 21.5).
-
-If you would like to help with bignum support, especially on BSD MP,
-please subscribe to the @uref{http://www.xemacs.org/Lists/#xemacs-beta,
-XEmacs Beta mailing list}, and book up on @file{number-gmp.h} and
-(a)file{number-mp.h}. Jerry has promised to write internals documentation
-eventually, but if your skills run more to analysis and documentation
-than to writing new code, feel free to fill in the gap!
+To configure with GMP, add @samp{--enable-bignum=gmp} to your invocation
+of @file{configure}. For MPIR, use @samp{--enable-bignum=mpir}. For
+BSD MP, use @samp{--enable-bignum=mp}.
@node Q7.2.2, Q7.2.3, Q7.2.1, Advanced
@@ -8036,10 +8028,10 @@
@node Q7.2.3, Q7.2.4, Q7.2.2, Advanced
@unnumberedsubsec Q7.2.3: Bignums are really slow!
-Many Linux distributions compile all their packages for the i386, and
-this is costly. An optimized version can give you two or three orders
-of magnitude better performance for a Pentium III or IV. (Yes, really.
-See @uref{http://www.swox.com/gmp/gmp-speed.html}.)
+Many Unix and Linux distributions compile all packages for a generic
+version of the supported CPU, and this is costly. An optimized version
+can improve responiveness dramatically; see
+@uref{http://gmplib.org/gmpbench.html}.)
@node Q7.2.4, , Q7.2.3, Advanced
diff -r f6af091ac6548f5e840cb3c31107474eda04f1cb -r a2912073be852d27a0589444677b96ad7027f2e3 src/ChangeLog
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,15 @@
+2013-06-17 Jerry James <james(a)xemacs.org>
+
+ * Makefile.in.in: Support bignums with MPIR.
+ * config.h.in (WITH_MPIR): New macro.
+ * number.c: Add MPIR support.
+ * number.h: Ditto.
+ * number-gmp.h: Ditto.
+ (ratio_set_long_ulong): Canonicalize the ratio.
+ (ratio_set_ulong_ulong): Ditto.
+ * number-gmp.c (init_number_gmp): Add void param to silence GCC.
+ * number-mp.c (init_number_mp): Ditto.
+
2013-06-17 Jerry James <james(a)xemacs.org>
* alloc.c (make_bignum_un): New function.
diff -r f6af091ac6548f5e840cb3c31107474eda04f1cb -r a2912073be852d27a0589444677b96ad7027f2e3 src/Makefile.in.in
--- a/src/Makefile.in.in
+++ b/src/Makefile.in.in
@@ -207,7 +207,7 @@
mule_wnn_objs=mule-wnnfns.o
#endif
-#ifdef WITH_GMP
+#if defined(WITH_GMP) || defined(WITH_MPIR)
number_objs=number-gmp.o number.o
#endif
#ifdef WITH_MP
diff -r f6af091ac6548f5e840cb3c31107474eda04f1cb -r a2912073be852d27a0589444677b96ad7027f2e3 src/config.h.in
--- a/src/config.h.in
+++ b/src/config.h.in
@@ -747,6 +747,7 @@
/* Enhanced numeric support */
#undef WITH_NUMBER_TYPES
#undef WITH_GMP
+#undef WITH_MPIR
#undef WITH_MP
#undef MP_PREFIX
#undef HAVE_MP_MOVE
diff -r f6af091ac6548f5e840cb3c31107474eda04f1cb -r a2912073be852d27a0589444677b96ad7027f2e3 src/number-gmp.c
--- a/src/number-gmp.c
+++ b/src/number-gmp.c
@@ -1,5 +1,5 @@
-/* Numeric types for XEmacs using the GNU MP library.
- Copyright (C) 2004 Jerry James.
+/* Numeric types for XEmacs using the GMP or MPIR library.
+ Copyright (C) 2004,2013 Jerry James.
This file is part of XEmacs.
@@ -141,7 +141,7 @@
}
void
-init_number_gmp ()
+init_number_gmp (void)
{
mp_set_memory_functions ((void *(*) (size_t)) xmalloc, gmp_realloc,
gmp_free);
diff -r f6af091ac6548f5e840cb3c31107474eda04f1cb -r a2912073be852d27a0589444677b96ad7027f2e3 src/number-gmp.h
--- a/src/number-gmp.h
+++ b/src/number-gmp.h
@@ -1,5 +1,5 @@
-/* Definitions of numeric types for XEmacs using the GNU MP library.
- Copyright (C) 2004 Jerry James.
+/* Definitions of numeric types for XEmacs using the GMP or MPIR library.
+ Copyright (C) 2004,2013 Jerry James.
This file is part of XEmacs.
@@ -38,7 +38,12 @@
Occurs on line 1596 of gmp.h in version 4.1.4. */
#pragma warning ( disable : 4146 )
#endif
+#ifdef WITH_GMP
#include <gmp.h>
+#endif
+#ifdef WITH_MPIR
+#include <mpir.h>
+#endif
#ifdef _MSC_VER
#pragma warning ( default : 4146 )
#endif
@@ -165,9 +170,14 @@
#define ratio_set_double(r,f) mpq_set_d (r, f)
#define ratio_set_bignum(r,b) mpq_set_z (r, b)
#define ratio_set_bigfloat(r,f) mpq_set_f (r, f)
-#define ratio_set_long_ulong(r,num,den) mpq_set_si (r, num, den)
-#define ratio_set_ulong_ulong(r,num,den) mpq_set_ui (r, num, den)
-/* FIXME: Why does this canonicalize, but the previous 2 don't? */
+#define ratio_set_long_ulong(r,num,den) do { \
+ mpq_set_si (r, num, den); \
+ mpq_canonicalize (r); \
+ } while (0)
+#define ratio_set_ulong_ulong(r,num,den) do { \
+ mpq_set_ui (r, num, den); \
+ mpq_canonicalize (r); \
+ } while (0)
#define ratio_set_bignum_bignum(r,num,den) do { \
mpz_set (mpq_numref (r), num); \
mpz_set (mpq_denref (r), den); \
diff -r f6af091ac6548f5e840cb3c31107474eda04f1cb -r a2912073be852d27a0589444677b96ad7027f2e3 src/number-mp.c
--- a/src/number-mp.c
+++ b/src/number-mp.c
@@ -623,7 +623,7 @@
#endif
void
-init_number_mp ()
+init_number_mp (void)
{
#ifdef HAVE_MP_SET_MEMORY_FUNCTIONS
mp_set_memory_functions ((void *(*) (size_t)) xmalloc, mp_realloc, mp_free);
diff -r f6af091ac6548f5e840cb3c31107474eda04f1cb -r a2912073be852d27a0589444677b96ad7027f2e3 src/number.c
--- a/src/number.c
+++ b/src/number.c
@@ -870,7 +870,7 @@
{
number_initialized = 1;
-#ifdef WITH_GMP
+#if defined(WITH_GMP) || defined(WITH_MPIR)
init_number_gmp ();
#endif
#ifdef WITH_MP
diff -r f6af091ac6548f5e840cb3c31107474eda04f1cb -r a2912073be852d27a0589444677b96ad7027f2e3 src/number.h
--- a/src/number.h
+++ b/src/number.h
@@ -56,7 +56,7 @@
*/
/* Load the library definitions */
-#ifdef WITH_GMP
+#if defined(WITH_GMP) || defined(WITH_MPIR)
#include "number-gmp.h"
#endif
#ifdef WITH_MP
Repository URL: https://bitbucket.org/xemacs/xemacs/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
_______________________________________________
XEmacs-Patches mailing list
XEmacs-Patches(a)xemacs.org
http://lists.xemacs.org/mailman/listinfo/xemacs-patches
[COMMIT] Use new language features in #'call-process-internal now they're available.
11 years, 4 months
Aidan Kehoe
APPROVE COMMIT
NOTE: This patch has been committed.
# HG changeset patch
# User Aidan Kehoe <kehoea(a)parhasard.net>
# Date 1371497867 -3600
# Node ID f6af091ac6548f5e840cb3c31107474eda04f1cb
# Parent 165315eae1ab4d64ecc4a2d7e919fa4f13844421
Use new language features in #'call-process-internal now they're available.
lisp/ChangeLog addition:
2013-06-17 Aidan Kehoe <kehoea(a)parhasard.net>
* process.el (process-synchronize-point): Moved to a label.
* process.el (call-process-internal):
Now we have better language features, use them rather than
creating a closure ourselves or exposing a utility function when
there is no need for that with a well-implemented labels function.
diff -r 165315eae1ab -r f6af091ac654 lisp/ChangeLog
--- a/lisp/ChangeLog Mon Jun 17 19:54:02 2013 +0100
+++ b/lisp/ChangeLog Mon Jun 17 20:37:47 2013 +0100
@@ -1,3 +1,11 @@
+2013-06-17 Aidan Kehoe <kehoea(a)parhasard.net>
+
+ * process.el (process-synchronize-point): Moved to a label.
+ * process.el (call-process-internal):
+ Now we have better language features, use them rather than
+ creating a closure ourselves or exposing a utility function when
+ there is no need for that with a well-implemented labels function.
+
2013-06-17 Aidan Kehoe <kehoea(a)parhasard.net>
* cl-macs.el:
diff -r 165315eae1ab -r f6af091ac654 lisp/process.el
--- a/lisp/process.el Mon Jun 17 19:54:02 2013 +0100
+++ b/lisp/process.el Mon Jun 17 20:37:47 2013 +0100
@@ -109,29 +109,6 @@
shell-command-switch
(mapconcat 'identity (cons command args) " ")))
-(defun process-synchronize-point (proc)
- "Set the point(s) in buffer and stderr-buffer according to the process mark."
- ;; We need this because the documentation says to insert *BEFORE* point,
- ;; but we end up inserting after because only the process mark moves
- ;; forward, not point. We synchronize after every place output might
- ;; happen, in sentinels, and in an unwind-protect, to make *SURE* that
- ;; point is correct. (We could do this more easily and perhaps more
- ;; safely using a process filter, but that would create a LOT of garbage
- ;; since all the data would get sent in strings.) We make this a separate
- ;; function, not an flet, due to dynamic binding problems -- the flet may
- ;; not still be in scope when the sentinel is called.
- (let ((pb (process-buffer proc))
- (pm (process-mark proc)))
- (if (and pb (buffer-live-p pb) (marker-buffer pm))
- (goto-char pm pb))
- (if (process-has-separate-stderr-p proc)
- (let ((pseb (process-stderr-buffer proc))
- (psem (process-stderr-mark proc)))
- (if (and pseb (not (eq pb pseb))
- (buffer-live-p pseb)
- (marker-buffer psem))
- (goto-char psem pseb))))))
-
(defun call-process-internal (program &optional infile buffer display
&rest args)
"Internal function to call PROGRAM synchronously in separate process.
@@ -179,7 +156,33 @@
;; note that we need to be *very* careful in this code to handle C-g
;; at any point.
(unwind-protect
- (progn
+ (labels
+ ((process-synchronize-point (proc)
+ ;; Set the point(s) in buffer and stderr-buffer according to
+ ;; the process mark.
+ ;;
+ ;; We need this because the documentation says to insert
+ ;; *BEFORE* point, but we end up inserting after because only
+ ;; the process mark moves forward, not point. We synchronize
+ ;; after every place output might happen, in sentinels, and
+ ;; in an unwind-protect, to make *SURE* that point is
+ ;; correct. (We could do this more easily and perhaps more
+ ;; safely using a process filter, but that would create a LOT
+ ;; of garbage since all the data would get sent in strings.)
+ ;; We make this a label, not an flet, due to dynamic binding
+ ;; problems -- the flet may not still be in scope when the
+ ;; sentinel is called.
+ (let ((pb (process-buffer proc))
+ (pm (process-mark proc)))
+ (if (and pb (buffer-live-p pb) (marker-buffer pm))
+ (goto-char pm pb))
+ (if (process-has-separate-stderr-p proc)
+ (let ((pseb (process-stderr-buffer proc))
+ (psem (process-stderr-mark proc)))
+ (if (and pseb (not (eq pb pseb))
+ (buffer-live-p pseb)
+ (marker-buffer psem))
+ (goto-char psem pseb)))))))
;; first handle INFILE.
(cond ((stringp infile)
(setq infile (expand-file-name infile))
@@ -263,25 +266,20 @@
;; we finish.
;;
;; #### not clear if we should be doing this.
- ;;
- ;; NOTE NOTE NOTE: Due to the total bogosity of
- ;; dynamic scoping, and the lack of closures, we
- ;; have to be careful how we write the first
- ;; sentinel below since it may be executed after
- ;; this function has returned -- thus we fake a
- ;; closure. (This doesn't apply to the second one,
- ;; which only gets executed within the
- ;; unwind-protect.)
- `(lambda (proc status)
- (set-process-sentinel proc nil)
- (process-synchronize-point proc)
- (with-current-buffer ,errbuf
- (write-region-internal
- 1 (1+ (buffer-size))
- ,stderr
- nil 'major-rms-kludge-city nil
- coding-system-for-write))
- (kill-buffer ,errbuf)))
+ (apply-partially
+ #'(lambda (errbuf stderr proc status)
+ (set-process-sentinel proc nil)
+ (process-synchronize-point proc)
+ (with-current-buffer errbuf
+ (write-region-internal
+ 1 (1+ (buffer-size))
+ stderr
+ nil 'major-rms-kludge-city nil
+ coding-system-for-write))
+ (kill-buffer errbuf))
+ ;; Close around these two variables, the lambda may be
+ ;; called outside this enclosing unwind-protect.
+ errbuf stderr))
(no-wait nil)
(t
;; normal sentinel: maybe write out stderr and return
--
‘Liston operated so fast that he once accidentally amputated an assistant’s
fingers along with a patient’s leg, […] The patient and the assistant both
died of sepsis, and a spectator reportedly died of shock, resulting in the
only known procedure with a 300% mortality.’ (Atul Gawande, NEJM, 2012)
_______________________________________________
XEmacs-Patches mailing list
XEmacs-Patches(a)xemacs.org
http://lists.xemacs.org/mailman/listinfo/xemacs-patches
[COMMIT] Make #'apply-partially more intelligent still when byte-compiled.
11 years, 4 months
Aidan Kehoe
APPROVE COMMIT
NOTE: This patch has been committed
# HG changeset patch
# User Aidan Kehoe <kehoea(a)parhasard.net>
# Date 1371495242 -3600
# Node ID 165315eae1ab4d64ecc4a2d7e919fa4f13844421
# Parent 3192994c49caeb8083d28711b176a8ffe32e6e31
Make #'apply-partially more intelligent still when byte-compiled.
lisp/ChangeLog addition:
2013-06-17 Aidan Kehoe <kehoea(a)parhasard.net>
* cl-macs.el:
* cl-macs.el (apply-partially):
Be more intelligent about constructing (or not) compiled functions
at runtime or compile time when making these closures.
tests/ChangeLog addition:
2013-06-17 Aidan Kehoe <kehoea(a)parhasard.net>
* automated/lisp-tests.el:
Test #'apply-partially more extensively, given changes in
cl-macs.el.
diff -r 3192994c49ca -r 165315eae1ab lisp/ChangeLog
--- a/lisp/ChangeLog Mon Jun 17 10:23:00 2013 -0600
+++ b/lisp/ChangeLog Mon Jun 17 19:54:02 2013 +0100
@@ -1,3 +1,10 @@
+2013-06-17 Aidan Kehoe <kehoea(a)parhasard.net>
+
+ * cl-macs.el:
+ * cl-macs.el (apply-partially):
+ Be more intelligent about constructing (or not) compiled functions
+ at runtime or compile time when making these closures.
+
2013-03-02 Michael Sperber <mike(a)xemacs.org>
* bytecomp.el (byte-compile-if): Port this patch from GNU Emacs:
diff -r 3192994c49ca -r 165315eae1ab lisp/cl-macs.el
--- a/lisp/cl-macs.el Mon Jun 17 10:23:00 2013 -0600
+++ b/lisp/cl-macs.el Mon Jun 17 19:54:02 2013 +0100
@@ -3517,28 +3517,87 @@
(define-compiler-macro apply-partially (&whole form &rest args)
"Generate a #'make-byte-code call for #'apply-partially, if appropriate."
- (if (< (length args) 1)
- form
- (if (cl-const-exprs-p args)
- `#'(lambda (&rest args) (apply ,@args args))
- (let* ((placeholders (mapcar 'quote-maybe (mapcar 'gensym args)))
- (compiled (byte-compile-sexp
- `#'(lambda (&rest args) (apply ,@placeholders args)))))
- (assert (equal (intersection
- (mapcar 'quote-maybe (compiled-function-constants
- compiled))
- placeholders :test 'equal :stable t)
- placeholders)
- t "This macro requires that the relative order is the same\
-in the constants vector and in the arguments")
+ (when (< (length args) 1)
+ (return-from apply-partially form))
+ (let* ((values (cdr args)) (count (length values))
+ (placeholders (mapcar #'quote-maybe (mapcar #'gensym values)))
+ (sublis (pairlis placeholders values))
+ restp lambda arglist bindings compiled)
+ (when (and (eq 'function (car-safe (nth 0 args)))
+ (eq 'lambda (car-safe (nth 1 (nth 0 args)))))
+ (setq lambda (nth 1 (nth 0 args))
+ arglist (nth 1 lambda))
+ (when (> count (function-max-args lambda))
+ (byte-compile-warn
+ "attempt to apply-partially %S with too many arguments" lambda)
+ (return-from apply-partially form))
+ (while (and arglist placeholders)
+ (cond ((eq (car arglist) '&optional)
+ (if restp
+ (error 'syntax-error
+ "&optional found after &rest in %S" lambda))
+ (if (null (cdr arglist))
+ (error 'syntax-error "nothing after &optional in %S"
+ lambda)))
+ ((eq (car arglist) '&rest)
+ (if (null (cdr arglist))
+ (error 'syntax-error "nothing after &rest in %S" lambda))
+ (if (cdr (cdr arglist))
+ (error 'syntax-error "multiple vars after &rest in %S"
+ lambda))
+ (setq restp t))
+ (restp
+ (setq bindings (cons (list (car arglist)
+ (and placeholders
+ (cons 'list placeholders)))
+ bindings)
+ placeholders nil))
+ (t
+ (setq bindings (cons (list (car arglist) (car placeholders))
+ bindings)
+ placeholders (cdr placeholders))))
+ (setq arglist (cdr arglist)))
+ (when (cl-const-exprs-p values)
+ ;; Values are constant, no need to construct the compiled function
+ ;; at runtime.
+ (return-from apply-partially
+ (byte-compile-lambda
+ `(lambda ,arglist (let ,(sublis sublis (nreverse bindings)
+:test #'equal)
+ ,@(cddr lambda))))))
+ (setq compiled (byte-compile-lambda
+ `(lambda ,arglist (let ,(nreverse bindings)
+ ,@(cddr lambda)))))
+ (return-from apply-partially
`(make-byte-code
',(compiled-function-arglist compiled)
,(compiled-function-instructions compiled)
- (vector ,@(sublis (pairlis placeholders args)
+ (vector ,@(sublis sublis
(mapcar 'quote-maybe
(compiled-function-constants compiled))
:test 'equal))
- ,(compiled-function-stack-depth compiled))))))
+ ,(compiled-function-stack-depth compiled))))
+ (if (cl-const-exprs-p args)
+ `#'(lambda (&rest args) (apply ,@args args))
+ (let* ((placeholders (mapcar 'quote-maybe (mapcar 'gensym args)))
+ (compiled (byte-compile-sexp
+ `#'(lambda (&rest args)
+ (apply ,@placeholders args)))))
+ (assert (equal (intersection
+ (mapcar 'quote-maybe (compiled-function-constants
+ compiled))
+ placeholders :test 'equal :stable t)
+ placeholders)
+ t "This macro requires that the relative order is the same\
+in the constants vector and in the arguments")
+ `(make-byte-code
+ ',(compiled-function-arglist compiled)
+ ,(compiled-function-instructions compiled)
+ (vector ,@(sublis (pairlis placeholders args)
+ (mapcar 'quote-maybe
+ (compiled-function-constants compiled))
+:test 'equal))
+ ,(compiled-function-stack-depth compiled))))))
(define-compiler-macro delete-dups (list)
`(delete-duplicates (the list ,list) :test #'equal :from-end t))
diff -r 3192994c49ca -r 165315eae1ab tests/ChangeLog
--- a/tests/ChangeLog Mon Jun 17 10:23:00 2013 -0600
+++ b/tests/ChangeLog Mon Jun 17 19:54:02 2013 +0100
@@ -1,3 +1,9 @@
+2013-06-17 Aidan Kehoe <kehoea(a)parhasard.net>
+
+ * automated/lisp-tests.el:
+ Test #'apply-partially more extensively, given changes in
+ cl-macs.el.
+
2013-06-17 Jerry James <james(a)xemacs.org>
* automated/lisp-tests.el: Adjust expected failure message due to
diff -r 3192994c49ca -r 165315eae1ab tests/automated/lisp-tests.el
--- a/tests/automated/lisp-tests.el Mon Jun 17 10:23:00 2013 -0600
+++ b/tests/automated/lisp-tests.el Mon Jun 17 19:54:02 2013 +0100
@@ -2950,12 +2950,34 @@
(times-four (apply-partially '* four))
(plus-twelve (apply-partially '+ 6 (* 3 2)))
(construct-list (apply-partially 'list (incf four) (incf four)
- (incf four))))
+ (incf four)))
+ (list-and-multiply
+ (apply-partially #'(lambda (a b c d &optional e)
+ (cons (apply #'+ a b c d (if e (list e)))
+ (list* a b c d e)))
+ ;; Constant arguments -> function can be
+ ;; constructed at compile time
+ 1 2 3))
+ (list-and-four
+ (apply-partially #'(lambda (a b c d &optional e)
+ (cons (apply #'+ a b c d (if e (list e)))
+ (list* a b c d e)))
+ ;; Not constant arguments -> function constructed
+ ;; at runtime.
+ 1 2 four)))
(Assert (eql (funcall times-four 6) 24))
(Assert (eql (funcall times-four 4 4) 64))
(Assert (eql (funcall plus-twelve (funcall times-four 4) 4 4) 36))
(Check-Error wrong-number-of-arguments (apply-partially))
- (Assert (equal (funcall construct-list) '(5 6 7))))
+ (Assert (equal (funcall construct-list) '(5 6 7)))
+ (Assert (equal (funcall list-and-multiply 5 6) '(17 1 2 3 5 . 6)))
+ (Assert (equal (funcall list-and-multiply 7) '(13 1 2 3 7)))
+ (Check-Error wrong-number-of-arguments
+ (funcall list-and-multiply 7 8 9 10))
+ (Assert (equal (funcall list-and-four 5 6) '(21 1 2 7 5 . 6)))
+ (Assert (equal (funcall list-and-four 7) '(17 1 2 7 7)))
+ (Check-Error wrong-number-of-arguments
+ (funcall list-and-four 7 8 9 10)))
;; Test labels and inlining.
(labels
--
‘Liston operated so fast that he once accidentally amputated an assistant’s
fingers along with a patient’s leg, […] The patient and the assistant both
died of sepsis, and a spectator reportedly died of shock, resulting in the
only known procedure with a 300% mortality.’ (Atul Gawande, NEJM, 2012)
_______________________________________________
XEmacs-Patches mailing list
XEmacs-Patches(a)xemacs.org
http://lists.xemacs.org/mailman/listinfo/xemacs-patches
commit/XEmacs: 2 new changesets
11 years, 4 months
Bitbucket
2 new commits in XEmacs:
https://bitbucket.org/xemacs/xemacs/commits/165315eae1ab/
Changeset: 165315eae1ab
User: kehoea
Date: 2013-06-17 20:54:02
Summary: Make #'apply-partially more intelligent still when byte-compiled.
lisp/ChangeLog addition:
2013-06-17 Aidan Kehoe <kehoea(a)parhasard.net>
* cl-macs.el:
* cl-macs.el (apply-partially):
Be more intelligent about constructing (or not) compiled functions
at runtime or compile time when making these closures.
tests/ChangeLog addition:
2013-06-17 Aidan Kehoe <kehoea(a)parhasard.net>
* automated/lisp-tests.el:
Test #'apply-partially more extensively, given changes in
cl-macs.el.
Affected #: 4 files
diff -r 3192994c49caeb8083d28711b176a8ffe32e6e31 -r 165315eae1ab4d64ecc4a2d7e919fa4f13844421 lisp/ChangeLog
--- a/lisp/ChangeLog
+++ b/lisp/ChangeLog
@@ -1,3 +1,10 @@
+2013-06-17 Aidan Kehoe <kehoea(a)parhasard.net>
+
+ * cl-macs.el:
+ * cl-macs.el (apply-partially):
+ Be more intelligent about constructing (or not) compiled functions
+ at runtime or compile time when making these closures.
+
2013-03-02 Michael Sperber <mike(a)xemacs.org>
* bytecomp.el (byte-compile-if): Port this patch from GNU Emacs:
diff -r 3192994c49caeb8083d28711b176a8ffe32e6e31 -r 165315eae1ab4d64ecc4a2d7e919fa4f13844421 lisp/cl-macs.el
--- a/lisp/cl-macs.el
+++ b/lisp/cl-macs.el
@@ -3517,28 +3517,87 @@
(define-compiler-macro apply-partially (&whole form &rest args)
"Generate a #'make-byte-code call for #'apply-partially, if appropriate."
- (if (< (length args) 1)
- form
- (if (cl-const-exprs-p args)
- `#'(lambda (&rest args) (apply ,@args args))
- (let* ((placeholders (mapcar 'quote-maybe (mapcar 'gensym args)))
- (compiled (byte-compile-sexp
- `#'(lambda (&rest args) (apply ,@placeholders args)))))
- (assert (equal (intersection
- (mapcar 'quote-maybe (compiled-function-constants
- compiled))
- placeholders :test 'equal :stable t)
- placeholders)
- t "This macro requires that the relative order is the same\
-in the constants vector and in the arguments")
+ (when (< (length args) 1)
+ (return-from apply-partially form))
+ (let* ((values (cdr args)) (count (length values))
+ (placeholders (mapcar #'quote-maybe (mapcar #'gensym values)))
+ (sublis (pairlis placeholders values))
+ restp lambda arglist bindings compiled)
+ (when (and (eq 'function (car-safe (nth 0 args)))
+ (eq 'lambda (car-safe (nth 1 (nth 0 args)))))
+ (setq lambda (nth 1 (nth 0 args))
+ arglist (nth 1 lambda))
+ (when (> count (function-max-args lambda))
+ (byte-compile-warn
+ "attempt to apply-partially %S with too many arguments" lambda)
+ (return-from apply-partially form))
+ (while (and arglist placeholders)
+ (cond ((eq (car arglist) '&optional)
+ (if restp
+ (error 'syntax-error
+ "&optional found after &rest in %S" lambda))
+ (if (null (cdr arglist))
+ (error 'syntax-error "nothing after &optional in %S"
+ lambda)))
+ ((eq (car arglist) '&rest)
+ (if (null (cdr arglist))
+ (error 'syntax-error "nothing after &rest in %S" lambda))
+ (if (cdr (cdr arglist))
+ (error 'syntax-error "multiple vars after &rest in %S"
+ lambda))
+ (setq restp t))
+ (restp
+ (setq bindings (cons (list (car arglist)
+ (and placeholders
+ (cons 'list placeholders)))
+ bindings)
+ placeholders nil))
+ (t
+ (setq bindings (cons (list (car arglist) (car placeholders))
+ bindings)
+ placeholders (cdr placeholders))))
+ (setq arglist (cdr arglist)))
+ (when (cl-const-exprs-p values)
+ ;; Values are constant, no need to construct the compiled function
+ ;; at runtime.
+ (return-from apply-partially
+ (byte-compile-lambda
+ `(lambda ,arglist (let ,(sublis sublis (nreverse bindings)
+:test #'equal)
+ ,@(cddr lambda))))))
+ (setq compiled (byte-compile-lambda
+ `(lambda ,arglist (let ,(nreverse bindings)
+ ,@(cddr lambda)))))
+ (return-from apply-partially
`(make-byte-code
',(compiled-function-arglist compiled)
,(compiled-function-instructions compiled)
- (vector ,@(sublis (pairlis placeholders args)
+ (vector ,@(sublis sublis
(mapcar 'quote-maybe
(compiled-function-constants compiled))
:test 'equal))
- ,(compiled-function-stack-depth compiled))))))
+ ,(compiled-function-stack-depth compiled))))
+ (if (cl-const-exprs-p args)
+ `#'(lambda (&rest args) (apply ,@args args))
+ (let* ((placeholders (mapcar 'quote-maybe (mapcar 'gensym args)))
+ (compiled (byte-compile-sexp
+ `#'(lambda (&rest args)
+ (apply ,@placeholders args)))))
+ (assert (equal (intersection
+ (mapcar 'quote-maybe (compiled-function-constants
+ compiled))
+ placeholders :test 'equal :stable t)
+ placeholders)
+ t "This macro requires that the relative order is the same\
+in the constants vector and in the arguments")
+ `(make-byte-code
+ ',(compiled-function-arglist compiled)
+ ,(compiled-function-instructions compiled)
+ (vector ,@(sublis (pairlis placeholders args)
+ (mapcar 'quote-maybe
+ (compiled-function-constants compiled))
+:test 'equal))
+ ,(compiled-function-stack-depth compiled))))))
(define-compiler-macro delete-dups (list)
`(delete-duplicates (the list ,list) :test #'equal :from-end t))
diff -r 3192994c49caeb8083d28711b176a8ffe32e6e31 -r 165315eae1ab4d64ecc4a2d7e919fa4f13844421 tests/ChangeLog
--- a/tests/ChangeLog
+++ b/tests/ChangeLog
@@ -1,3 +1,9 @@
+2013-06-17 Aidan Kehoe <kehoea(a)parhasard.net>
+
+ * automated/lisp-tests.el:
+ Test #'apply-partially more extensively, given changes in
+ cl-macs.el.
+
2013-06-17 Jerry James <james(a)xemacs.org>
* automated/lisp-tests.el: Adjust expected failure message due to
diff -r 3192994c49caeb8083d28711b176a8ffe32e6e31 -r 165315eae1ab4d64ecc4a2d7e919fa4f13844421 tests/automated/lisp-tests.el
--- a/tests/automated/lisp-tests.el
+++ b/tests/automated/lisp-tests.el
@@ -2950,12 +2950,34 @@
(times-four (apply-partially '* four))
(plus-twelve (apply-partially '+ 6 (* 3 2)))
(construct-list (apply-partially 'list (incf four) (incf four)
- (incf four))))
+ (incf four)))
+ (list-and-multiply
+ (apply-partially #'(lambda (a b c d &optional e)
+ (cons (apply #'+ a b c d (if e (list e)))
+ (list* a b c d e)))
+ ;; Constant arguments -> function can be
+ ;; constructed at compile time
+ 1 2 3))
+ (list-and-four
+ (apply-partially #'(lambda (a b c d &optional e)
+ (cons (apply #'+ a b c d (if e (list e)))
+ (list* a b c d e)))
+ ;; Not constant arguments -> function constructed
+ ;; at runtime.
+ 1 2 four)))
(Assert (eql (funcall times-four 6) 24))
(Assert (eql (funcall times-four 4 4) 64))
(Assert (eql (funcall plus-twelve (funcall times-four 4) 4 4) 36))
(Check-Error wrong-number-of-arguments (apply-partially))
- (Assert (equal (funcall construct-list) '(5 6 7))))
+ (Assert (equal (funcall construct-list) '(5 6 7)))
+ (Assert (equal (funcall list-and-multiply 5 6) '(17 1 2 3 5 . 6)))
+ (Assert (equal (funcall list-and-multiply 7) '(13 1 2 3 7)))
+ (Check-Error wrong-number-of-arguments
+ (funcall list-and-multiply 7 8 9 10))
+ (Assert (equal (funcall list-and-four 5 6) '(21 1 2 7 5 . 6)))
+ (Assert (equal (funcall list-and-four 7) '(17 1 2 7 7)))
+ (Check-Error wrong-number-of-arguments
+ (funcall list-and-four 7 8 9 10)))
;; Test labels and inlining.
(labels
https://bitbucket.org/xemacs/xemacs/commits/f6af091ac654/
Changeset: f6af091ac654
User: kehoea
Date: 2013-06-17 21:37:47
Summary: Use new language features in #'call-process-internal now they're available.
lisp/ChangeLog addition:
2013-06-17 Aidan Kehoe <kehoea(a)parhasard.net>
* process.el (process-synchronize-point): Moved to a label.
* process.el (call-process-internal):
Now we have better language features, use them rather than
creating a closure ourselves or exposing a utility function when
there is no need for that with a well-implemented labels function.
Affected #: 2 files
diff -r 165315eae1ab4d64ecc4a2d7e919fa4f13844421 -r f6af091ac6548f5e840cb3c31107474eda04f1cb lisp/ChangeLog
--- a/lisp/ChangeLog
+++ b/lisp/ChangeLog
@@ -1,3 +1,11 @@
+2013-06-17 Aidan Kehoe <kehoea(a)parhasard.net>
+
+ * process.el (process-synchronize-point): Moved to a label.
+ * process.el (call-process-internal):
+ Now we have better language features, use them rather than
+ creating a closure ourselves or exposing a utility function when
+ there is no need for that with a well-implemented labels function.
+
2013-06-17 Aidan Kehoe <kehoea(a)parhasard.net>
* cl-macs.el:
diff -r 165315eae1ab4d64ecc4a2d7e919fa4f13844421 -r f6af091ac6548f5e840cb3c31107474eda04f1cb lisp/process.el
--- a/lisp/process.el
+++ b/lisp/process.el
@@ -109,29 +109,6 @@
shell-command-switch
(mapconcat 'identity (cons command args) " ")))
-(defun process-synchronize-point (proc)
- "Set the point(s) in buffer and stderr-buffer according to the process mark."
- ;; We need this because the documentation says to insert *BEFORE* point,
- ;; but we end up inserting after because only the process mark moves
- ;; forward, not point. We synchronize after every place output might
- ;; happen, in sentinels, and in an unwind-protect, to make *SURE* that
- ;; point is correct. (We could do this more easily and perhaps more
- ;; safely using a process filter, but that would create a LOT of garbage
- ;; since all the data would get sent in strings.) We make this a separate
- ;; function, not an flet, due to dynamic binding problems -- the flet may
- ;; not still be in scope when the sentinel is called.
- (let ((pb (process-buffer proc))
- (pm (process-mark proc)))
- (if (and pb (buffer-live-p pb) (marker-buffer pm))
- (goto-char pm pb))
- (if (process-has-separate-stderr-p proc)
- (let ((pseb (process-stderr-buffer proc))
- (psem (process-stderr-mark proc)))
- (if (and pseb (not (eq pb pseb))
- (buffer-live-p pseb)
- (marker-buffer psem))
- (goto-char psem pseb))))))
-
(defun call-process-internal (program &optional infile buffer display
&rest args)
"Internal function to call PROGRAM synchronously in separate process.
@@ -179,7 +156,33 @@
;; note that we need to be *very* careful in this code to handle C-g
;; at any point.
(unwind-protect
- (progn
+ (labels
+ ((process-synchronize-point (proc)
+ ;; Set the point(s) in buffer and stderr-buffer according to
+ ;; the process mark.
+ ;;
+ ;; We need this because the documentation says to insert
+ ;; *BEFORE* point, but we end up inserting after because only
+ ;; the process mark moves forward, not point. We synchronize
+ ;; after every place output might happen, in sentinels, and
+ ;; in an unwind-protect, to make *SURE* that point is
+ ;; correct. (We could do this more easily and perhaps more
+ ;; safely using a process filter, but that would create a LOT
+ ;; of garbage since all the data would get sent in strings.)
+ ;; We make this a label, not an flet, due to dynamic binding
+ ;; problems -- the flet may not still be in scope when the
+ ;; sentinel is called.
+ (let ((pb (process-buffer proc))
+ (pm (process-mark proc)))
+ (if (and pb (buffer-live-p pb) (marker-buffer pm))
+ (goto-char pm pb))
+ (if (process-has-separate-stderr-p proc)
+ (let ((pseb (process-stderr-buffer proc))
+ (psem (process-stderr-mark proc)))
+ (if (and pseb (not (eq pb pseb))
+ (buffer-live-p pseb)
+ (marker-buffer psem))
+ (goto-char psem pseb)))))))
;; first handle INFILE.
(cond ((stringp infile)
(setq infile (expand-file-name infile))
@@ -263,25 +266,20 @@
;; we finish.
;;
;; #### not clear if we should be doing this.
- ;;
- ;; NOTE NOTE NOTE: Due to the total bogosity of
- ;; dynamic scoping, and the lack of closures, we
- ;; have to be careful how we write the first
- ;; sentinel below since it may be executed after
- ;; this function has returned -- thus we fake a
- ;; closure. (This doesn't apply to the second one,
- ;; which only gets executed within the
- ;; unwind-protect.)
- `(lambda (proc status)
- (set-process-sentinel proc nil)
- (process-synchronize-point proc)
- (with-current-buffer ,errbuf
- (write-region-internal
- 1 (1+ (buffer-size))
- ,stderr
- nil 'major-rms-kludge-city nil
- coding-system-for-write))
- (kill-buffer ,errbuf)))
+ (apply-partially
+ #'(lambda (errbuf stderr proc status)
+ (set-process-sentinel proc nil)
+ (process-synchronize-point proc)
+ (with-current-buffer errbuf
+ (write-region-internal
+ 1 (1+ (buffer-size))
+ stderr
+ nil 'major-rms-kludge-city nil
+ coding-system-for-write))
+ (kill-buffer errbuf))
+ ;; Close around these two variables, the lambda may be
+ ;; called outside this enclosing unwind-protect.
+ errbuf stderr))
(no-wait nil)
(t
;; normal sentinel: maybe write out stderr and return
Repository URL: https://bitbucket.org/xemacs/xemacs/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
_______________________________________________
XEmacs-Patches mailing list
XEmacs-Patches(a)xemacs.org
http://lists.xemacs.org/mailman/listinfo/xemacs-patches
commit/XEmacs: Jerry James: Convert C (un)signed long long values to bignums properly.
11 years, 4 months
Bitbucket
1 new commit in XEmacs:
https://bitbucket.org/xemacs/xemacs/commits/3192994c49ca/
Changeset: 3192994c49ca
User: Jerry James
Date: 2013-06-17 18:23:00
Summary: Convert C (un)signed long long values to bignums properly.
This patch also does the following:
- Uses make_fixnum instead of make_integer when the argument is guaranteed to
be in the fixnum range.
- Introduces make_unsigned_integer so that we handle unsigned values with the
high bit set correctly.
- Introduces conversions between bignums and (un)signed long long values.
- Uses mp_set_memory_functions with the BSD MP code, if it exists.
- Eliminates some unnecessary consing in the Lisp + and * implementations.
- Fixes a problem with check_valid_xbm_inline(). This function is called
during intialization. It calls Ftimes. When using pdump, this is a
problem, because (a) the bignum code is not initialized until *after*
dumping, so we don't try to dump any bignums, and (b) multiplication of
integers is done inside bignums so we handle fixnum overflow correctly. I
decided that an XBM file with dimensions that don't fit into fixnums is
probably not something we want to try to handle anyway, and did the
arithmetic with C values instead of Lisp values. Doing that broke one test,
which started getting a different error message from the one it expected, so
I adjusted the test to match the new reality.
- Fixes a few miscellaneous bugs in the BSD MP code.
See <CAHCOHQk0u0=eD1fUMHTNWi2Yh=1WgiYyCXdMbsGzHBNhdqYz4w(a)mail.gmail.com> in
xemacs-patches, as well as followup messages.
Affected #: 27 files
diff -r ff13c44ce0d92d2872eb38404c9c076628c3301d -r 3192994c49caeb8083d28711b176a8ffe32e6e31 ChangeLog
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
+2013-06-17 Jerry James <james(a)xemacs.org>
+
+ * configure.ac: Add check for mp_set_memory_functions.
+
2013-03-12 Jerry James <james(a)xemacs.org>
* config.guess: Update to latest upstream version.
diff -r ff13c44ce0d92d2872eb38404c9c076628c3301d -r 3192994c49caeb8083d28711b176a8ffe32e6e31 configure
--- a/configure
+++ b/configure
@@ -20897,6 +20897,19 @@
else
{ echo "Error:" "Required MP numeric support cannot be provided." >&2; exit 1; }
fi
+ ac_fn_c_check_func "$LINENO" "mp_set_memory_functions" "ac_cv_func_mp_set_memory_functions"
+if test "x$ac_cv_func_mp_set_memory_functions" = xyes; then :
+ $as_echo "#define HAVE_MP_SET_MEMORY_FUNCTIONS 1" >>confdefs.h
+
+else
+ ac_fn_c_check_func "$LINENO" "__gmp_set_memory_functions" "ac_cv_func___gmp_set_memory_functions"
+if test "x$ac_cv_func___gmp_set_memory_functions" = xyes; then :
+ $as_echo "#define HAVE_MP_SET_MEMORY_FUNCTIONS 1" >>confdefs.h
+
+fi
+
+fi
+
$as_echo "#define WITH_NUMBER_TYPES 1" >>confdefs.h
$as_echo "#define WITH_MP 1" >>confdefs.h
diff -r ff13c44ce0d92d2872eb38404c9c076628c3301d -r 3192994c49caeb8083d28711b176a8ffe32e6e31 configure.ac
--- a/configure.ac
+++ b/configure.ac
@@ -5287,6 +5287,10 @@
else
XE_DIE("Required MP numeric support cannot be provided.")
fi
+ AC_CHECK_FUNC(mp_set_memory_functions,
+ [AC_DEFINE(HAVE_MP_SET_MEMORY_FUNCTIONS)],
+ [AC_CHECK_FUNC(__gmp_set_memory_functions,
+ [AC_DEFINE(HAVE_MP_SET_MEMORY_FUNCTIONS)])])
AC_DEFINE(WITH_NUMBER_TYPES)
AC_DEFINE(WITH_MP)
fi
diff -r ff13c44ce0d92d2872eb38404c9c076628c3301d -r 3192994c49caeb8083d28711b176a8ffe32e6e31 src/ChangeLog
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,72 @@
+2013-06-17 Jerry James <james(a)xemacs.org>
+
+ * alloc.c (make_bignum_un): New function.
+ (make_bignum_ll): New function.
+ (make_bignum_ull): New function.
+ * config.h.in (HAVE_MP_SET_MEMORY_FUNCTIONS): Add.
+ * data.c (Fplus): avoid unnecessary consing.
+ (Ftimes): ditto.
+ * glyphs.c (check_valid_xbm_inline): Since this function is called
+ prior to dumping, when bignums are forbidden, do all arithmetic
+ with C integers.
+ * lisp.h (MOST_POSITIVE_FIXNUM_UNSIGNED): New constant.
+ (MOST_POSITIVE_FIXNUM): Redefine in terms of the above.
+ (UNSIGNED_NUMBER_FITS_IN_A_FIXNUM): New macro.
+ * number-gmp.c (bignum_to_llong): New function.
+ (bignum_to_ullong): New function.
+ (bignum_set_llong): New function.
+ (bigfloat_to_string): Adjust whitespace.
+ (gmp_realloc): Ditto.
+ (gmp_free): Ditto.
+ * number-gmp.h (bignum_fits_llong): New macro.
+ (bignum_fits_ullong): New macro.
+ (bignum_set_ullong): New macro.
+ * number-mp.c (bignum_long_sign_bit): Remove, didn't work.
+ (bignum_min_llong): New variable.
+ (bignum_max_llong): New variable.
+ (bignum_max_ullong): New variable.
+ (bignum_to_llong): New function.
+ (bignum_to_ullong): New function.
+ (bignum_set_long): Reimplement using MP_XTOM.
+ (bignum_set_ulong): Ditto.
+ (bignum_set_llong): New function.
+ (bignum_set_ullong): New function.
+ (bignum_clrbit): Fix a comment.
+ (bignum_random_seed): Move to number-mp.h, since it is a no-op.
+ (bignum_random): Implement.
+ (mp_realloc): New function.
+ (mp_free): New function.
+ (init_number_mp): Use them. Fix a comment. Eliminate
+ initialization of bignum_long_sign_bit. Initialize
+ bignum_min_llong, bignum_max_llong, and bignum_set_ullong.
+ * number-mp.h (MP_XTOM): New macro.
+ (bignum_fits_llong_p): New macro.
+ (bignum_fits_ullong_p): New macro.
+ (bignum_random_seed): New macro.
+ * number.h: Implement bignums as long long integers.
+ (make_bignum_ll): New macro.
+ (make_integer): Accept a long long value.
+ (make_unsigned_integer): New macro.
+ (NATNUMP): Adjust whitespace.
+ (non_fixnum_number_p): Ditto.
+
+ * alloc.c (Fmake_list): Use make_unsigned_integer or make_fixnum
+ instead of make_integer where it is appropriate to do so.
+ * chartab.c (char_table_default_for_type): Ditto.
+ * dired.c (Ffile_attributes): Ditto.
+ * elhash.c (hash_table_size_validate): Ditto.
+ * eval.c (Fmacroexpand): Ditto.
+ * event-stream.c (Faccept_process_output): Ditto.
+ (Frecent_keys): Ditto.
+ * events.c (Fmake_event): Ditto.
+ (Fevent_timestamp_lessp): Ditto.
+ * font-mgr.c (Ffc_pattern_get): Ditto.
+ * indent.c (Fmove_to_column): Ditto.
+ * process.c (Fset_process_window_size): Ditto.
+ * profile.c (Fstart_profiling): Ditto.
+ * unicode.c (Fset_unicode_conversion): Ditto.
+ (Funicode_to_char): Ditto.
+
2013-04-23 Vin Shelton <acs(a)xemacs.org>
* sysdep.c (qxe_getgrgid): Hack in WIN32_NATIVE group support.
diff -r ff13c44ce0d92d2872eb38404c9c076628c3301d -r 3192994c49caeb8083d28711b176a8ffe32e6e31 src/alloc.c
--- a/src/alloc.c
+++ b/src/alloc.c
@@ -1583,7 +1583,7 @@
Lisp_Object val = Qnil;
Elemcount size;
- check_integer_range (length, Qzero, make_integer (MOST_POSITIVE_FIXNUM));
+ check_integer_range (length, Qzero, make_fixnum (MOST_POSITIVE_FIXNUM));
size = XFIXNUM (length);
@@ -1644,6 +1644,45 @@
/* WARNING: This function returns a bignum even if its argument fits into a
fixnum. See Fcanonicalize_number(). */
Lisp_Object
+make_bignum_un (unsigned long bignum_value)
+{
+ Lisp_Bignum *b;
+
+ ALLOC_FROB_BLOCK_LISP_OBJECT (bignum, Lisp_Bignum, b, &lrecord_bignum);
+ bignum_init (bignum_data (b));
+ bignum_set_ulong (bignum_data (b), bignum_value);
+ return wrap_bignum (b);
+}
+
+/* WARNING: This function returns a bignum even if its argument fits into a
+ fixnum. See Fcanonicalize_number(). */
+Lisp_Object
+make_bignum_ll (long long bignum_value)
+{
+ Lisp_Bignum *b;
+
+ ALLOC_FROB_BLOCK_LISP_OBJECT (bignum, Lisp_Bignum, b, &lrecord_bignum);
+ bignum_init (bignum_data (b));
+ bignum_set_llong (bignum_data (b), bignum_value);
+ return wrap_bignum (b);
+}
+
+/* WARNING: This function returns a bignum even if its argument fits into a
+ fixnum. See Fcanonicalize_number(). */
+Lisp_Object
+make_bignum_ull (unsigned long long bignum_value)
+{
+ Lisp_Bignum *b;
+
+ ALLOC_FROB_BLOCK_LISP_OBJECT (bignum, Lisp_Bignum, b, &lrecord_bignum);
+ bignum_init (bignum_data (b));
+ bignum_set_ullong (bignum_data (b), bignum_value);
+ return wrap_bignum (b);
+}
+
+/* WARNING: This function returns a bignum even if its argument fits into a
+ fixnum. See Fcanonicalize_number(). */
+Lisp_Object
make_bignum_bg (bignum bg)
{
Lisp_Bignum *b;
diff -r ff13c44ce0d92d2872eb38404c9c076628c3301d -r 3192994c49caeb8083d28711b176a8ffe32e6e31 src/chartab.c
--- a/src/chartab.c
+++ b/src/chartab.c
@@ -436,7 +436,7 @@
break;
case CHAR_TABLE_TYPE_SYNTAX:
- return make_integer (Sinherit);
+ return make_fixnum (Sinherit);
break;
}
ABORT();
diff -r ff13c44ce0d92d2872eb38404c9c076628c3301d -r 3192994c49caeb8083d28711b176a8ffe32e6e31 src/config.h.in
--- a/src/config.h.in
+++ b/src/config.h.in
@@ -750,6 +750,7 @@
#undef WITH_MP
#undef MP_PREFIX
#undef HAVE_MP_MOVE
+#undef HAVE_MP_SET_MEMORY_FUNCTIONS
#undef SIZEOF_SHORT
#undef SIZEOF_INT
diff -r ff13c44ce0d92d2872eb38404c9c076628c3301d -r 3192994c49caeb8083d28711b176a8ffe32e6e31 src/data.c
--- a/src/data.c
+++ b/src/data.c
@@ -1447,16 +1447,14 @@
break;
#ifdef HAVE_BIGNUM
case BIGNUM_T:
- bignum_add (scratch_bignum, XBIGNUM_DATA (accum),
+ bignum_add (XBIGNUM_DATA (accum), XBIGNUM_DATA (accum),
XBIGNUM_DATA (addend));
- accum = make_bignum_bg (scratch_bignum);
break;
#endif
#ifdef HAVE_RATIO
case RATIO_T:
- ratio_add (scratch_ratio, XRATIO_DATA (accum),
+ ratio_add (XRATIO_DATA (accum), XRATIO_DATA (accum),
XRATIO_DATA (addend));
- accum = make_ratio_rt (scratch_ratio);
break;
#endif
case FLOAT_T:
@@ -1464,12 +1462,11 @@
break;
#ifdef HAVE_BIGFLOAT
case BIGFLOAT_T:
- bigfloat_set_prec (scratch_bigfloat,
+ bigfloat_set_prec (XBIGFLOAT_DATA (accum),
max (XBIGFLOAT_GET_PREC (addend),
XBIGFLOAT_GET_PREC (accum)));
- bigfloat_add (scratch_bigfloat, XBIGFLOAT_DATA (accum),
+ bigfloat_add (XBIGFLOAT_DATA (accum), XBIGFLOAT_DATA (accum),
XBIGFLOAT_DATA (addend));
- accum = make_bigfloat_bf (scratch_bigfloat);
break;
#endif
}
@@ -1643,16 +1640,14 @@
{
#ifdef HAVE_BIGNUM
case BIGNUM_T:
- bignum_mul (scratch_bignum, XBIGNUM_DATA (accum),
+ bignum_mul (XBIGNUM_DATA (accum), XBIGNUM_DATA (accum),
XBIGNUM_DATA (multiplier));
- accum = make_bignum_bg (scratch_bignum);
break;
#endif
#ifdef HAVE_RATIO
case RATIO_T:
- ratio_mul (scratch_ratio, XRATIO_DATA (accum),
+ ratio_mul (XRATIO_DATA (accum), XRATIO_DATA (accum),
XRATIO_DATA (multiplier));
- accum = make_ratio_rt (scratch_ratio);
break;
#endif
case FLOAT_T:
@@ -1660,12 +1655,11 @@
break;
#ifdef HAVE_BIGFLOAT
case BIGFLOAT_T:
- bigfloat_set_prec (scratch_bigfloat,
+ bigfloat_set_prec (XBIGFLOAT_DATA (accum),
max (XBIGFLOAT_GET_PREC (multiplier),
XBIGFLOAT_GET_PREC (accum)));
- bigfloat_mul (scratch_bigfloat, XBIGFLOAT_DATA (accum),
+ bigfloat_mul (XBIGFLOAT_DATA (accum), XBIGFLOAT_DATA (accum),
XBIGFLOAT_DATA (multiplier));
- accum = make_bigfloat_bf (scratch_bigfloat);
break;
#endif
}
diff -r ff13c44ce0d92d2872eb38404c9c076628c3301d -r 3192994c49caeb8083d28711b176a8ffe32e6e31 src/dired.c
--- a/src/dired.c
+++ b/src/dired.c
@@ -915,8 +915,8 @@
}
#ifndef HAVE_BIGNUM
- size = make_integer (NUMBER_FITS_IN_A_FIXNUM (s.st_size) ?
- (EMACS_INT)s.st_size : -1);
+ size = make_fixnum (NUMBER_FITS_IN_A_FIXNUM (s.st_size) ?
+ (EMACS_INT)s.st_size : -1);
#else
size = make_integer (s.st_size);
#endif
@@ -939,8 +939,8 @@
if (NILP(id_format) || EQ (id_format, Qinteger))
{
- uidInfo = make_integer (s.st_uid);
- gidInfo = make_integer (s.st_gid);
+ uidInfo = make_unsigned_integer (s.st_uid);
+ gidInfo = make_unsigned_integer (s.st_gid);
}
else
{
@@ -957,7 +957,7 @@
RETURN_UNGCPRO (listn (12,
mode,
- make_integer (s.st_nlink),
+ make_unsigned_integer (s.st_nlink),
uidInfo,
gidInfo,
make_time (s.st_atime),
@@ -966,8 +966,8 @@
size,
modestring,
gid,
- make_integer (s.st_ino),
- make_integer (s.st_dev)));
+ make_unsigned_integer (s.st_ino),
+ make_unsigned_integer (s.st_dev)));
}
diff -r ff13c44ce0d92d2872eb38404c9c076628c3301d -r 3192994c49caeb8083d28711b176a8ffe32e6e31 src/elhash.c
--- a/src/elhash.c
+++ b/src/elhash.c
@@ -820,7 +820,7 @@
/* hash_table_size() can't handle excessively large sizes. */
maybe_signal_error_1 (Qargs_out_of_range,
list3 (value, Qzero,
- make_integer (MOST_POSITIVE_FIXNUM)),
+ make_fixnum (MOST_POSITIVE_FIXNUM)),
Qhash_table, errb);
return 0;
}
diff -r ff13c44ce0d92d2872eb38404c9c076628c3301d -r 3192994c49caeb8083d28711b176a8ffe32e6e31 src/eval.c
--- a/src/eval.c
+++ b/src/eval.c
@@ -1576,7 +1576,7 @@
in case it expands into another macro call. */
if (SYMBOLP (form))
{
- Lisp_Object hashed = make_integer ((EMACS_INT) (LISP_HASH (form)));
+ Lisp_Object hashed = make_unsigned_integer (LISP_HASH (form));
Lisp_Object assocked;
if (BIGNUMP (hashed))
@@ -7276,7 +7276,7 @@
REGISTER int i;
Lisp_Object tem;
- check_integer_range (nframes, Qzero, make_integer (MOST_POSITIVE_FIXNUM));
+ check_integer_range (nframes, Qzero, make_fixnum (MOST_POSITIVE_FIXNUM));
/* Find the frame requested. */
for (i = XFIXNUM (nframes); backlist && (i-- > 0);)
diff -r ff13c44ce0d92d2872eb38404c9c076628c3301d -r 3192994c49caeb8083d28711b176a8ffe32e6e31 src/event-stream.c
--- a/src/event-stream.c
+++ b/src/event-stream.c
@@ -2626,7 +2626,7 @@
if (!NILP (timeout_msecs))
{
check_integer_range (timeout_msecs, Qzero,
- make_integer (MOST_POSITIVE_FIXNUM));
+ make_fixnum (MOST_POSITIVE_FIXNUM));
msecs += XFIXNUM (timeout_msecs);
}
if (msecs)
@@ -3716,7 +3716,7 @@
else
{
check_integer_range (number, Qzero,
- make_integer (ARRAY_DIMENSION_LIMIT));
+ make_fixnum (ARRAY_DIMENSION_LIMIT));
nwanted = XFIXNUM (number);
}
diff -r ff13c44ce0d92d2872eb38404c9c076628c3301d -r 3192994c49caeb8083d28711b176a8ffe32e6e31 src/events.c
--- a/src/events.c
+++ b/src/events.c
@@ -735,13 +735,13 @@
else if (EQ (keyword, Qtimestamp))
{
#ifdef HAVE_BIGNUM
- check_integer_range (value, Qzero, make_integer (UINT_MAX));
+ check_integer_range (value, Qzero, make_unsigned_integer (UINT_MAX));
if (BIGNUMP (value))
{
SET_EVENT_TIMESTAMP (e, bignum_to_uint (XBIGNUM_DATA (value)));
}
#else
- check_integer_range (value, Qzero, make_integer (MOST_POSITIVE_FIXNUM));
+ check_integer_range (value, Qzero, make_fixnum (MOST_POSITIVE_FIXNUM));
#endif
if (FIXNUMP (value))
{
@@ -1777,8 +1777,8 @@
{
EMACS_INT t1, t2;
- check_integer_range (time1, Qzero, make_integer (MOST_POSITIVE_FIXNUM));
- check_integer_range (time2, Qzero, make_integer (MOST_POSITIVE_FIXNUM));
+ check_integer_range (time1, Qzero, make_fixnum (MOST_POSITIVE_FIXNUM));
+ check_integer_range (time2, Qzero, make_fixnum (MOST_POSITIVE_FIXNUM));
t1 = XFIXNUM (time1);
t2 = XFIXNUM (time2);
diff -r ff13c44ce0d92d2872eb38404c9c076628c3301d -r 3192994c49caeb8083d28711b176a8ffe32e6e31 src/font-mgr.c
--- a/src/font-mgr.c
+++ b/src/font-mgr.c
@@ -440,7 +440,7 @@
check_integer_range (id, Qzero, make_integer (INT_MAX));
int_id = BIGNUMP (id) ? bignum_to_int (XBIGNUM_DATA (id)) : XFIXNUM (id);
#else
- check_integer_range (id, Qzero, make_integer (MOST_POSITIVE_FIXNUM));
+ check_integer_range (id, Qzero, make_fixnum (MOST_POSITIVE_FIXNUM));
int_id = XFIXNUM (id);
#endif
}
diff -r ff13c44ce0d92d2872eb38404c9c076628c3301d -r 3192994c49caeb8083d28711b176a8ffe32e6e31 src/glyphs.c
--- a/src/glyphs.c
+++ b/src/glyphs.c
@@ -2638,6 +2638,7 @@
check_valid_xbm_inline (Lisp_Object data)
{
Lisp_Object width, height, bits, args[2];
+ unsigned long i_width, i_height;
if (!CONSP (data) ||
!CONSP (XCDR (data)) ||
@@ -2651,22 +2652,15 @@
CHECK_STRING (bits);
- if (!NATNUMP (width))
+ if (!FIXNUMP (width) || XREALFIXNUM (width) < 0)
invalid_argument ("Width must be a natural number", width);
- if (!NATNUMP (height))
+ if (!FIXNUMP (height) || XREALFIXNUM (height) < 0)
invalid_argument ("Height must be a natural number", height);
- args[0] = width;
- args[1] = height;
-
- args[0] = Ftimes (countof (args), args);
- args[1] = make_integer (8);
-
- args[0] = Fquo (countof (args), args);
- args[1] = make_integer (string_char_length (bits));
-
- if (!NILP (Fgtr (countof (args), args)))
+ i_width = (unsigned long) XREALFIXNUM (width);
+ i_height = (unsigned long) XREALFIXNUM (height);
+ if (i_width * i_height / 8UL > string_char_length (bits))
invalid_argument ("data is too short for width and height",
vector3 (width, height, bits));
}
diff -r ff13c44ce0d92d2872eb38404c9c076628c3301d -r 3192994c49caeb8083d28711b176a8ffe32e6e31 src/indent.c
--- a/src/indent.c
+++ b/src/indent.c
@@ -411,7 +411,7 @@
buffer = wrap_buffer (buf);
if (tab_width <= 0 || tab_width > 1000) tab_width = 8;
- check_integer_range (column, Qzero, make_integer (MOST_POSITIVE_FIXNUM));
+ check_integer_range (column, Qzero, make_fixnum (MOST_POSITIVE_FIXNUM));
goal = XFIXNUM (column);
retry:
diff -r ff13c44ce0d92d2872eb38404c9c076628c3301d -r 3192994c49caeb8083d28711b176a8ffe32e6e31 src/lisp.h
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -1677,11 +1677,14 @@
#define FIXNUM_VALBITS (BITS_PER_EMACS_INT - FIXNUM_GCBITS)
#define VALBITS (BITS_PER_EMACS_INT - GCBITS)
-#define MOST_POSITIVE_FIXNUM ((EMACS_INT) ((1UL << (FIXNUM_VALBITS - 1)) -1UL))
+#define MOST_POSITIVE_FIXNUM_UNSIGNED ((1UL << (FIXNUM_VALBITS - 1)) -1UL)
+#define MOST_POSITIVE_FIXNUM ((EMACS_INT) MOST_POSITIVE_FIXNUM_UNSIGNED)
#define MOST_NEGATIVE_FIXNUM (-(MOST_POSITIVE_FIXNUM) - 1)
/* WARNING: evaluates its arg twice. */
#define NUMBER_FITS_IN_A_FIXNUM(num) \
((num) <= MOST_POSITIVE_FIXNUM && (num) >= MOST_NEGATIVE_FIXNUM)
+#define UNSIGNED_NUMBER_FITS_IN_A_FIXNUM(num) \
+ ((num) <= MOST_POSITIVE_FIXNUM_UNSIGNED)
#ifdef USE_UNION_TYPE
# include "lisp-union.h"
diff -r ff13c44ce0d92d2872eb38404c9c076628c3301d -r 3192994c49caeb8083d28711b176a8ffe32e6e31 src/number-gmp.c
--- a/src/number-gmp.c
+++ b/src/number-gmp.c
@@ -27,8 +27,42 @@
static mp_exp_t float_print_min, float_print_max;
gmp_randstate_t random_state;
+long long
+bignum_to_llong (const bignum b)
+{
+ long long l;
+
+ mpz_export (&l, NULL, 1, sizeof (l), 0, 0U, b);
+ return (mpz_sgn (b) < 0) ? -l : l;
+}
+
+unsigned long long
+bignum_to_ullong (const bignum b)
+{
+ unsigned long long l;
+
+ mpz_export (&l, NULL, 1, sizeof (l), 0, 0U, b);
+ return l;
+}
+
+void
+bignum_set_llong (bignum b, long long l)
+{
+ if (l < 0LL)
+ {
+ /* This even works for LLONG_MIN. Try it! */
+ l = -l;
+ mpz_import (b, 1U, 1, sizeof (l), 0, 0U, &l);
+ mpz_neg (b, b);
+ }
+ else
+ {
+ mpz_import (b, 1U, 1, sizeof (l), 0, 0U, &l);
+ }
+}
+
CIbyte *
-bigfloat_to_string(mpf_t f, int base)
+bigfloat_to_string (mpf_t f, int base)
{
mp_exp_t expt;
CIbyte *str = mpf_get_str (NULL, &expt, base, 0, f);
@@ -94,12 +128,14 @@
/* We need the next two functions since GNU MP insists on giving us an extra
parameter. */
-static void *gmp_realloc (void *ptr, size_t UNUSED (old_size), size_t new_size)
+static void *
+gmp_realloc (void *ptr, size_t UNUSED (old_size), size_t new_size)
{
return xrealloc (ptr, new_size);
}
-static void gmp_free (void *ptr, size_t UNUSED (size))
+static void
+gmp_free (void *ptr, size_t UNUSED (size))
{
xfree (ptr);
}
diff -r ff13c44ce0d92d2872eb38404c9c076628c3301d -r 3192994c49caeb8083d28711b176a8ffe32e6e31 src/number-gmp.h
--- a/src/number-gmp.h
+++ b/src/number-gmp.h
@@ -69,6 +69,11 @@
#define bignum_fits_uint_p(b) mpz_fits_uint_p (b)
#define bignum_fits_long_p(b) mpz_fits_slong_p (b)
#define bignum_fits_ulong_p(b) mpz_fits_ulong_p (b)
+#define bignum_fits_llong_p(b) \
+ (mpz_sizeinbase (b, 2) <= (sizeof(long long) << 3) - 1U)
+#define bignum_fits_ullong_p(b) \
+ (mpz_sgn (b) >= 0 && \
+ mpz_sizeinbase (b, 2) <= (sizeof(unsigned long long) << 3))
/***** Bignum: conversions *****/
#define bignum_to_string(b,base) mpz_get_str (NULL, base, b)
@@ -76,6 +81,8 @@
#define bignum_to_uint(b) ((unsigned int) mpz_get_ui (b))
#define bignum_to_long(b) mpz_get_si (b)
#define bignum_to_ulong(b) mpz_get_ui (b)
+extern long long bignum_to_llong(const bignum b);
+extern unsigned long long bignum_to_ullong(const bignum b);
#define bignum_to_double(b) mpz_get_d (b)
/***** Bignum: converting assignments *****/
@@ -83,6 +90,8 @@
#define bignum_set_string(b,s,base) mpz_set_str (b, s, base)
#define bignum_set_long(b,l) mpz_set_si (b, l)
#define bignum_set_ulong(b,l) mpz_set_ui (b, l)
+extern void bignum_set_llong(bignum b, long long l);
+#define bignum_set_ullong(b,l) mpz_import (b,1U,1,sizeof (l),0,0U,&l)
#define bignum_set_double(b,f) mpz_set_d (b, f)
#define bignum_set_ratio(b,r) mpz_set_q (b, r)
#define bignum_set_bigfloat(b,f) mpz_set_f (b, f)
diff -r ff13c44ce0d92d2872eb38404c9c076628c3301d -r 3192994c49caeb8083d28711b176a8ffe32e6e31 src/number-mp.c
--- a/src/number-mp.c
+++ b/src/number-mp.c
@@ -21,12 +21,14 @@
#include <config.h>
#include <limits.h>
#include <math.h>
+#include <stdlib.h>
#include "lisp.h"
-static MINT *bignum_bytesize, *bignum_long_sign_bit, *bignum_one, *bignum_two;
+static MINT *bignum_bytesize, *bignum_one, *bignum_two;
MINT *bignum_zero, *intern_bignum;
MINT *bignum_min_int, *bignum_max_int, *bignum_max_uint;
MINT *bignum_min_long, *bignum_max_long, *bignum_max_ulong;
+MINT *bignum_min_llong, *bignum_max_llong, *bignum_max_ullong;
short div_rem;
char *
@@ -164,6 +166,32 @@
return retval;
}
+long long
+bignum_to_llong (bignum b)
+{
+ short rem, sign;
+ unsigned long long retval = 0LL;
+ REGISTER unsigned int i;
+ MINT *quo;
+
+ sign = bignum_sign (b);
+ BIGNUM_TO_TYPE (long long, unsigned long long);
+ return ((long long) retval) * sign;
+}
+
+unsigned long long
+bignum_to_ullong (bignum b)
+{
+ short rem, sign;
+ unsigned long long retval = 0UL;
+ REGISTER unsigned int i;
+ MINT *quo;
+
+ sign = bignum_sign (b);
+ BIGNUM_TO_TYPE (unsigned long long, unsigned long long);
+ return retval;
+}
+
double
bignum_to_double (bignum b)
{
@@ -249,6 +277,7 @@
MP_MADD (b, temp, b);
MP_MFREE (temp);
}
+ MP_MFREE (mbase);
if (neg)
MP_MSUB (bignum_zero, b, b);
@@ -257,31 +286,61 @@
}
void
-bignum_set_long (MINT *b, long l)
+bignum_set_long (bignum b, long l)
{
- /* Negative l is hard, not least because -LONG_MIN == LONG_MIN. We pretend
- that l is unsigned, then subtract off the amount equal to the sign bit. */
- bignum_set_ulong (b, (unsigned long) l);
- if (l < 0L)
- MP_MSUB (b, bignum_long_sign_bit, b);
+ char hex[SIZEOF_LONG * 2U + 2U];
+ MINT *temp;
+ int neg = l < 0L;
+
+ snprintf (hex, SIZEOF_LONG * 2U + 2U, "%lx",
+ neg ? (unsigned long) -l : (unsigned long) l);
+ temp = MP_XTOM (hex);
+ if (neg)
+ MP_MSUB (bignum_zero, temp, b);
+ else
+ MP_MOVE (temp, b);
+ MP_MFREE (temp);
}
void
bignum_set_ulong (bignum b, unsigned long l)
{
- REGISTER unsigned int i;
- MINT *multiplier = MP_ITOM (1);
+ char hex[SIZEOF_LONG * 2U + 2U];
+ MINT *temp;
- MP_MOVE (bignum_zero, b);
- for (i = 0UL; l > 0UL; l >>= 8, i++)
- {
- MINT *temp = MP_ITOM ((short) (l & 255));
- MP_MULT (multiplier, temp, temp);
- MP_MADD (b, temp, b);
- MP_MULT (multiplier, bignum_bytesize, multiplier);
- MP_MFREE (temp);
- }
- MP_MFREE (multiplier);
+ snprintf (hex, SIZEOF_LONG * 2U + 2U, "%lx", l);
+ temp = MP_XTOM (hex);
+ MP_MOVE (temp, b);
+ MP_MFREE (temp);
+}
+
+void
+bignum_set_llong (bignum b, long long l)
+{
+ char hex[SIZEOF_LONG_LONG * 2U + 2U];
+ MINT *temp;
+ int neg = l < 0LL;
+
+ snprintf (hex, SIZEOF_LONG_LONG * 2U + 2U, "%llx",
+ neg ? (unsigned long long) -l : (unsigned long long) l);
+ temp = MP_XTOM (hex);
+ if (neg)
+ MP_MSUB (bignum_zero, temp, b);
+ else
+ MP_MOVE (temp, b);
+ MP_MFREE (temp);
+}
+
+void
+bignum_set_ullong (bignum b, unsigned long long l)
+{
+ char hex[SIZEOF_LONG_LONG * 2U + 2U];
+ MINT *temp;
+
+ snprintf (hex, SIZEOF_LONG_LONG * 2U + 2U, "%llx", l);
+ temp = MP_XTOM (hex);
+ MP_MOVE (temp, b);
+ MP_MFREE (temp);
}
void
@@ -485,7 +544,7 @@
{
MINT *num = MP_ITOM (0);
- /* See if the bit is already set, and subtract it off if not */
+ /* See if the bit is set, and subtract it off if so */
MP_MOVE (b, intern_bignum);
bignum_pow (num, bignum_two, bit);
bignum_ior (intern_bignum, intern_bignum, num);
@@ -516,21 +575,59 @@
MP_MDIV (b, intern_bignum, result, intern_bignum);
}
-void bignum_random_seed(unsigned long seed)
+void
+bignum_random (bignum result, bignum limit)
{
- /* FIXME: Implement me */
+ MINT *denominator = MP_ITOM (0), *divisor = MP_ITOM (0);
+ bignum_set_long (denominator, RAND_MAX);
+ MP_MADD (denominator, bignum_one, denominator);
+ MP_MADD (limit, bignum_one, divisor);
+ MP_MDIV (denominator, divisor, denominator, intern_bignum);
+ MP_MFREE (divisor);
+
+ do
+ {
+ MINT *limitcmp = MP_ITOM (1);
+
+ /* Accumulate at least as many random bits as in LIMIT */
+ MP_MOVE (bignum_zero, result);
+ do
+ {
+ bignum_lshift (limitcmp, limitcmp, FIXNUM_VALBITS);
+ bignum_lshift (result, result, FIXNUM_VALBITS);
+ bignum_set_long (intern_bignum, get_random ());
+ MP_MADD (intern_bignum, result, result);
+ }
+ while (MP_MCMP (limitcmp, limit) <= 0);
+ MP_MDIV (result, denominator, result, intern_bignum);
+ MP_MFREE (limitcmp);
+ }
+ while (MP_MCMP (limit, result) <= 0);
+
+ MP_MFREE (denominator);
}
-void bignum_random(bignum result, bignum limit)
+#ifdef HAVE_MP_SET_MEMORY_FUNCTIONS
+/* We need the next two functions due to the extra parameter. */
+static void *
+mp_realloc (void *ptr, size_t UNUSED (old_size), size_t new_size)
{
- /* FIXME: Implement me */
- MP_MOVE (bignum_zero, result);
+ return xrealloc (ptr, new_size);
}
+static void
+mp_free (void *ptr, size_t UNUSED (size))
+{
+ xfree (ptr);
+}
+#endif
+
void
init_number_mp ()
{
- REGISTER unsigned int i;
+#ifdef HAVE_MP_SET_MEMORY_FUNCTIONS
+ mp_set_memory_functions ((void *(*) (size_t)) xmalloc, mp_realloc, mp_free);
+#endif
bignum_zero = MP_ITOM (0);
bignum_one = MP_ITOM (1);
@@ -540,14 +637,9 @@
number-mp.h. Its value is immaterial. */
intern_bignum = MP_ITOM (0);
- /* bignum_bytesize holds the number of bits in a byte. */
+ /* The multiplier used to shift a number left by one byte's worth of bits */
bignum_bytesize = MP_ITOM (256);
- /* bignum_long_sign_bit holds an adjustment for negative longs. */
- bignum_long_sign_bit = MP_ITOM (256);
- for (i = 1UL; i < sizeof (long); i++)
- MP_MULT (bignum_bytesize, bignum_long_sign_bit, bignum_long_sign_bit);
-
/* The MP interface only supports turning short ints into MINTs, so we have
to set these the hard way. */
@@ -568,4 +660,13 @@
bignum_max_ulong = MP_ITOM (0);
bignum_set_ulong (bignum_max_ulong, ULONG_MAX);
+
+ bignum_min_llong = MP_ITOM (0);
+ bignum_set_llong (bignum_min_llong, LLONG_MIN);
+
+ bignum_max_llong = MP_ITOM (0);
+ bignum_set_llong (bignum_max_llong, LLONG_MAX);
+
+ bignum_max_ullong = MP_ITOM (0);
+ bignum_set_ullong (bignum_max_ullong, ULLONG_MAX);
}
diff -r ff13c44ce0d92d2872eb38404c9c076628c3301d -r 3192994c49caeb8083d28711b176a8ffe32e6e31 src/number-mp.h
--- a/src/number-mp.h
+++ b/src/number-mp.h
@@ -40,6 +40,7 @@
#ifdef MP_PREFIX
#define MP_GCD mp_gcd
#define MP_ITOM mp_itom
+#define MP_XTOM mp_xtom
#define MP_MADD mp_madd
#define MP_MCMP mp_mcmp
#define MP_MDIV mp_mdiv
@@ -55,6 +56,7 @@
#else
#define MP_GCD gcd
#define MP_ITOM itom
+#define MP_XTOM xtom
#define MP_MADD madd
#define MP_MCMP mcmp
#define MP_MDIV mdiv
@@ -81,6 +83,7 @@
extern MINT *bignum_zero, *intern_bignum;
extern MINT *bignum_min_int, *bignum_max_int, *bignum_max_uint;
extern MINT *bignum_min_long, *bignum_max_long, *bignum_max_ulong;
+extern MINT *bignum_min_llong, *bignum_max_llong, *bignum_max_ullong;
extern short div_rem;
/***** Bignum: basic functions *****/
@@ -102,6 +105,10 @@
MP_MCMP (b, bignum_max_long) <= 0)
#define bignum_fits_ulong_p(b) (MP_MCMP (b, bignum_zero) >= 0 && \
MP_MCMP (b, bignum_max_ulong) <= 0)
+#define bignum_fits_llong_p(b) (MP_MCMP (b, bignum_min_llong) >= 0 && \
+ MP_MCMP (b, bignum_max_llong) <= 0)
+#define bignum_fits_ullong_p(b) (MP_MCMP (b, bignum_zero) >= 0 && \
+ MP_MCMP (b, bignum_max_ullong) <= 0)
/***** Bignum: conversions *****/
extern char *bignum_to_string(bignum, int);
@@ -109,6 +116,8 @@
extern unsigned int bignum_to_uint(bignum);
extern long bignum_to_long(bignum);
extern unsigned long bignum_to_ulong(bignum);
+extern long long bignum_to_llong(bignum);
+extern unsigned long long bignum_to_ullong(bignum);
extern double bignum_to_double(bignum);
/***** Bignum: converting assignments *****/
@@ -116,6 +125,8 @@
extern int bignum_set_string(bignum, const char *, int);
extern void bignum_set_long(bignum, long);
extern void bignum_set_ulong(bignum, unsigned long);
+extern void bignum_set_llong(bignum, long long);
+extern void bignum_set_ullong(bignum, unsigned long long);
extern void bignum_set_double(bignum, double);
/***** Bignum: comparisons *****/
@@ -155,7 +166,7 @@
extern void bignum_rshift(bignum, bignum, unsigned long);
/***** Bignum: random numbers *****/
-extern void bignum_random_seed(unsigned long);
+#define bignum_random_seed(s)
extern void bignum_random(bignum, bignum);
#endif /* INCLUDED_number_mp_h_ */
diff -r ff13c44ce0d92d2872eb38404c9c076628c3301d -r 3192994c49caeb8083d28711b176a8ffe32e6e31 src/number.h
--- a/src/number.h
+++ b/src/number.h
@@ -105,10 +105,14 @@
# define bignum_fits_emacs_int_p(b) bignum_fits_int_p(b)
# define bignum_to_emacs_int(b) bignum_to_int(b)
#else
-# error Bignums currently do not work with long long Emacs integers.
+# define bignum_fits_emacs_int_p(b) bignum_fits_llong_p(b)
+# define bignum_to_emacs_int(b) bignum_to_llong(b)
#endif
extern Lisp_Object make_bignum (long);
+extern Lisp_Object make_bignum_un (unsigned long);
+extern Lisp_Object make_bignum_ll (long long);
+extern Lisp_Object make_bignum_ull (unsigned long long);
extern Lisp_Object make_bignum_bg (bignum);
extern bignum scratch_bignum, scratch_bignum2;
@@ -119,6 +123,7 @@
#define CONCHECK_BIGNUM(x) dead_wrong_type_argument (Qbignump, x)
typedef void bignum;
#define make_bignum(l) This XEmacs does not support bignums
+#define make_bignum_ll(l) This XEmacs does not support bignums
#define make_bignum_bg(b) This XEmacs does not support bignums
#endif /* HAVE_BIGNUM */
@@ -140,10 +145,15 @@
} while (0)
#ifdef HAVE_BIGNUM
-#define make_integer(x) \
- (NUMBER_FITS_IN_A_FIXNUM (x) ? make_fixnum (x) : make_bignum (x))
+#define make_integer(x) \
+ (NUMBER_FITS_IN_A_FIXNUM (x) ? make_fixnum (x) \
+: (sizeof (x) > SIZEOF_LONG ? make_bignum_ll (x) : make_bignum (x)))
+#define make_unsigned_integer(x) \
+ (UNSIGNED_NUMBER_FITS_IN_A_FIXNUM (x) ? make_fixnum (x) \
+: (sizeof (x) > SIZEOF_LONG ? make_bignum_ull (x) : make_bignum_un (x)))
#else
#define make_integer(x) make_fixnum (x)
+#define make_unsigned_integer(x) make_fixnum ((EMACS_INT) x)
#endif
extern Fixnum Vmost_negative_fixnum, Vmost_positive_fixnum;
@@ -170,7 +180,7 @@
#ifdef HAVE_BIGNUM
#define NATNUMP(x) ((FIXNUMP (x) && XFIXNUM (x) >= 0) || \
- (BIGNUMP (x) && bignum_sign (XBIGNUM_DATA (x)) >= 0))
+ (BIGNUMP (x) && bignum_sign (XBIGNUM_DATA (x)) >= 0))
#else
#define NATNUMP(x) (FIXNUMP (x) && XFIXNUM (x) >= 0)
#endif
@@ -376,19 +386,19 @@
if (LRECORDP (object))
{
switch (XRECORD_LHEADER (object)->type)
- {
- case lrecord_type_float:
+ {
+ case lrecord_type_float:
#ifdef HAVE_BIGNUM
- case lrecord_type_bignum:
+ case lrecord_type_bignum:
#endif
#ifdef HAVE_RATIO
- case lrecord_type_ratio:
+ case lrecord_type_ratio:
#endif
#ifdef HAVE_BIGFLOAT
- case lrecord_type_bigfloat:
+ case lrecord_type_bigfloat:
#endif
- return 1;
- }
+ return 1;
+ }
}
return 0;
}
diff -r ff13c44ce0d92d2872eb38404c9c076628c3301d -r 3192994c49caeb8083d28711b176a8ffe32e6e31 src/process.c
--- a/src/process.c
+++ b/src/process.c
@@ -975,8 +975,8 @@
(process, height, width))
{
CHECK_PROCESS (process);
- check_integer_range (height, Qzero, make_integer (MOST_POSITIVE_FIXNUM));
- check_integer_range (width, Qzero, make_integer (MOST_POSITIVE_FIXNUM));
+ check_integer_range (height, Qzero, make_fixnum (MOST_POSITIVE_FIXNUM));
+ check_integer_range (width, Qzero, make_fixnum (MOST_POSITIVE_FIXNUM));
return
MAYBE_INT_PROCMETH (set_window_size,
(XPROCESS (process), XFIXNUM (height), XFIXNUM (width))) <= 0
diff -r ff13c44ce0d92d2872eb38404c9c076628c3301d -r 3192994c49caeb8083d28711b176a8ffe32e6e31 src/profile.c
--- a/src/profile.c
+++ b/src/profile.c
@@ -370,7 +370,7 @@
XFIXNUM (microsecs);
#else
check_integer_range (microsecs, make_fixnum (1000),
- make_integer (MOST_POSITIVE_FIXNUM));
+ make_fixnum (MOST_POSITIVE_FIXNUM));
msecs = XFIXNUM (microsecs);
#endif
}
diff -r ff13c44ce0d92d2872eb38404c9c076628c3301d -r 3192994c49caeb8083d28711b176a8ffe32e6e31 src/unicode.c
--- a/src/unicode.c
+++ b/src/unicode.c
@@ -1370,7 +1370,7 @@
CHECK_CHAR (character);
- check_integer_range (code, Qzero, make_integer (MOST_POSITIVE_FIXNUM));
+ check_integer_range (code, Qzero, make_fixnum (MOST_POSITIVE_FIXNUM));
unicode = XFIXNUM (code);
ichar = XCHAR (character);
@@ -1446,7 +1446,7 @@
int lbs[NUM_LEADING_BYTES];
int c;
- check_integer_range (code, Qzero, make_integer (MOST_POSITIVE_FIXNUM));
+ check_integer_range (code, Qzero, make_fixnum (MOST_POSITIVE_FIXNUM));
c = XFIXNUM (code);
{
EXTERNAL_LIST_LOOP_2 (elt, charsets)
@@ -1472,7 +1472,7 @@
return make_char (ret);
}
#else
- check_integer_range (code, Qzero, make_integer (MOST_POSITIVE_FIXNUM));
+ check_integer_range (code, Qzero, make_fixnum (MOST_POSITIVE_FIXNUM));
return Fint_to_char (code);
#endif /* MULE */
}
diff -r ff13c44ce0d92d2872eb38404c9c076628c3301d -r 3192994c49caeb8083d28711b176a8ffe32e6e31 tests/ChangeLog
--- a/tests/ChangeLog
+++ b/tests/ChangeLog
@@ -1,3 +1,8 @@
+2013-06-17 Jerry James <james(a)xemacs.org>
+
+ * automated/lisp-tests.el: Adjust expected failure message due to
+ changes in check_valid_xbm_inline().
+
2013-04-20 Mats Lidell <matsl(a)xemacs.org>
* automated/dired-tests.el: New. Tests for file-attributes.
diff -r ff13c44ce0d92d2872eb38404c9c076628c3301d -r 3192994c49caeb8083d28711b176a8ffe32e6e31 tests/automated/lisp-tests.el
--- a/tests/automated/lisp-tests.el
+++ b/tests/automated/lisp-tests.el
@@ -2641,7 +2641,7 @@
(when (featurep 'xbm)
(Check-Error-Message
invalid-argument
- "^data is too short for width and height"
+ "^Height must be a natural number"
(set-face-background-pixmap
'left-margin
`[xbm :data (20 ,(* 2 most-positive-fixnum) "random-text")])))
Repository URL: https://bitbucket.org/xemacs/xemacs/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
_______________________________________________
XEmacs-Patches mailing list
XEmacs-Patches(a)xemacs.org
http://lists.xemacs.org/mailman/listinfo/xemacs-patches
[PATCH 21.5] Bignums, long long ints, and BSD MP improvements
11 years, 4 months
Jerry James
PATCH 21.5
I did not intend to take this long, or produce such a large patch, but it kind
of got away from me. This patch started life as an effort to fix the problem
that C integers larger than a machine word are not converted to bignums
properly. Then as I stumbled across various bugs and problems, it grew into a
larger cleanup of some of the bignum code. Here is what this patch now does:
- Uses make_fixnum instead of make_integer when the argument is guaranteed to
be in the fixnum range.
- Introduces make_unsigned_integer so that we handle unsigned values with the
high bit set correctly.
- Introduces conversions between bignums and (un)signed long long values.
- Uses mp_set_memory_functions with the BSD MP code, if it exists.
- Eliminates all use of move()/mp_move(). For one thing, we had a check in
configure to see if the function is even available. Presumably there are,
or were, MP implementations without this function. But then we did nothing
if the function didn't exist and just used it anyway. For another thing,
the move() compatibility function in GMP 5.0.5 (which is what I have on my
Fedora 18 workstation) is broken. Sometimes it works as expected, sometimes
I get zero in the target bignum, even though the source bignum had a nonzero
value. I took the drastic step of wiping out all uses of this function just
so I could do some testing. (Note that the BSD compatibility functions were
dropped from GMP 5.1, so once I upgrade to Fedora 19, I won't be able to
test this code any more.)
- Eliminates some unnecessary consing in the Lisp + and * implementations.
- Fixes a problem with check_valid_xbm_inline(). This function is called
during intialization. It calls Ftimes. When using pdump, this is a
problem, because (a) the bignum code is not initialized until *after*
dumping, so we don't try to dump any bignums, and (b) multiplication of
integers is done inside bignums so we handle fixnum overflow correctly. I
decided that an XBM file with dimensions that don't fit into fixnums is
probably not something we want to try to handle anyway, and did the
arithmetic with C values instead of Lisp values. Doing that broke one test,
which started getting a different error message from the one it expected, so
I adjusted the test to match the new reality.
- Fixes a few miscellaneous bugs in the BSD MP code.
The patch is attached to avoid whitespace mangling courtesy of gmail.
--
Jerry James
http://www.jamezone.org/
_______________________________________________
XEmacs-Patches mailing list
XEmacs-Patches(a)xemacs.org
http://lists.xemacs.org/mailman/listinfo/xemacs-patches
commit/xemacs-packages: 3 new changesets
11 years, 4 months
Bitbucket
3 new commits in xemacs-packages:
https://bitbucket.org/xemacs/xemacs-packages/commits/606bb6c5b74f/
Changeset: 606bb6c5b74f
User: Norbert Koch
Date: 2013-06-17 10:17:51
Summary: update edit-utils
Affected #: 1 file
diff -r 34716b847f616f01a308557f16ff9ace71d05e0f -r 606bb6c5b74f64e1685d2db3d861b4893537217f .hgsubstate
--- a/.hgsubstate
+++ b/.hgsubstate
@@ -33,7 +33,7 @@
5200706cfcb56eeefed3d21d8f63f32dd491ca85 xemacs-packages/ede
7f290f0c522c3031e9101047df3949d87789de35 xemacs-packages/edebug
68569d2f5904bfc32cc5f9beececfb6e56b6f152 xemacs-packages/ediff
-33bcc14b0f8f3a756426b8e090efe931ad6a2283 xemacs-packages/edit-utils
+c0655c55d04ecd402b1e5fc2e8d0895faa755423 xemacs-packages/edit-utils
94f1da97c08e96f1bf1fd5a255934956e6a37a05 xemacs-packages/edt
73360c2969ec1e3ae896760611d0a4d4be823cf0 xemacs-packages/efs
2f441d6442dac751f54b36f78fbfdab0848f6bbc xemacs-packages/eicq
https://bitbucket.org/xemacs/xemacs-packages/commits/6625fa490548/
Changeset: 6625fa490548
User: Norbert Koch
Date: 2013-06-17 10:18:27
Summary: XEmacs Package Release
Affected #: 1 file
diff -r 606bb6c5b74f64e1685d2db3d861b4893537217f -r 6625fa490548673a243b10dedb620c42e6c52c92 ChangeLog
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
+2013-06-17 Norbert Koch <viteno(a)xemacs.org>
+
+ * Packages released: edit-utils.
+
2013-06-03 Norbert Koch <viteno(a)xemacs.org>
* Packages released: cc-mode, xemacs-base.
https://bitbucket.org/xemacs/xemacs-packages/commits/d2186184fa2f/
Changeset: d2186184fa2f
User: Norbert Koch
Date: 2013-06-17 10:29:39
Summary: Pre-release edit-utils 2.51
Affected #: 1 file
diff -r 6625fa490548673a243b10dedb620c42e6c52c92 -r d2186184fa2ffbb4e833337207058e6cc55551e6 .hgsubstate
--- a/.hgsubstate
+++ b/.hgsubstate
@@ -33,7 +33,7 @@
5200706cfcb56eeefed3d21d8f63f32dd491ca85 xemacs-packages/ede
7f290f0c522c3031e9101047df3949d87789de35 xemacs-packages/edebug
68569d2f5904bfc32cc5f9beececfb6e56b6f152 xemacs-packages/ediff
-c0655c55d04ecd402b1e5fc2e8d0895faa755423 xemacs-packages/edit-utils
+987a8f165ca55d13410e6a0546928278d7bbf66c xemacs-packages/edit-utils
94f1da97c08e96f1bf1fd5a255934956e6a37a05 xemacs-packages/edt
73360c2969ec1e3ae896760611d0a4d4be823cf0 xemacs-packages/efs
2f441d6442dac751f54b36f78fbfdab0848f6bbc xemacs-packages/eicq
Repository URL: https://bitbucket.org/xemacs/xemacs-packages/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
_______________________________________________
XEmacs-Patches mailing list
XEmacs-Patches(a)xemacs.org
http://lists.xemacs.org/mailman/listinfo/xemacs-patches
commit/edit-utils: 2 new changesets
11 years, 4 months
Bitbucket
2 new commits in edit-utils:
https://bitbucket.org/xemacs/edit-utils/commits/d2323673ec99/
Changeset: d2323673ec99
User: Norbert Koch
Date: 2013-06-17 10:18:26
Summary: XEmacs Package Release 2.51
Affected #: 2 files
diff -r c0655c55d04ecd402b1e5fc2e8d0895faa755423 -r d2323673ec99bc79928dd4ad15d45f60e0e288c7 ChangeLog
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
+2013-06-17 Norbert Koch <viteno(a)xemacs.org>
+
+ * Makefile (VERSION): XEmacs package 2.51 released.
+
2013-06-15 Mats Lidell <matsl(a)xemacs.org>
* find-lisp.el: New file. Find in lisp from GNU.
diff -r c0655c55d04ecd402b1e5fc2e8d0895faa755423 -r d2323673ec99bc79928dd4ad15d45f60e0e288c7 Makefile
--- a/Makefile
+++ b/Makefile
@@ -19,7 +19,7 @@
# This XEmacs package contains independent single file lisp packages
-VERSION = 2.50
+VERSION = 2.51
AUTHOR_VERSION =
MAINTAINER = XEmacs Development Team <xemacs-beta(a)xemacs.org>
PACKAGE = edit-utils
https://bitbucket.org/xemacs/edit-utils/commits/987a8f165ca5/
Changeset: 987a8f165ca5
User: Norbert Koch
Date: 2013-06-17 10:18:26
Summary: Added tag edit-utils-2_51 for changeset d2323673ec99
Affected #: 1 file
diff -r d2323673ec99bc79928dd4ad15d45f60e0e288c7 -r 987a8f165ca55d13410e6a0546928278d7bbf66c .hgtags
--- a/.hgtags
+++ b/.hgtags
@@ -156,3 +156,4 @@
7fcd64a33e7a5fded1fc9123adf9a1bdc6ed1bcd edit-utils-2_48
0465ba201528499f75e1f5e880c1f716eb024384 edit-utils-2_49
16e2ea4308300af77a25d51d9b77bd65c9099ffb edit-utils-2_50
+d2323673ec99bc79928dd4ad15d45f60e0e288c7 edit-utils-2_51
Repository URL: https://bitbucket.org/xemacs/edit-utils/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
_______________________________________________
XEmacs-Patches mailing list
XEmacs-Patches(a)xemacs.org
http://lists.xemacs.org/mailman/listinfo/xemacs-patches