emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Emacs-diffs] master 7f4558e 1/3: Always allow at least double-precision


From: Paul Eggert
Subject: [Emacs-diffs] master 7f4558e 1/3: Always allow at least double-precision bignums
Date: Tue, 4 Jun 2019 11:34:21 -0400 (EDT)

branch: master
commit 7f4558e3d9edbdee6901e5fbcd4a4072f49ec5b9
Author: Paul Eggert <address@hidden>
Commit: Paul Eggert <address@hidden>

    Always allow at least double-precision bignums
    
    Without this fix, Emacs can get into a tight loop reporting
    a range error when calculating timestamps.
    * doc/lispref/numbers.texi (Integer Basics):
    * src/alloc.c (syms_of_alloc): Document this.
    * src/bignum.c (make_bignum_bits): Always allow bignums
    of at least twice the width of (u)intmax_t.
---
 doc/lispref/numbers.texi | 14 +++++++-------
 src/alloc.c              |  6 +++---
 src/bignum.c             |  7 +++++--
 3 files changed, 15 insertions(+), 12 deletions(-)

diff --git a/doc/lispref/numbers.texi b/doc/lispref/numbers.texi
index fbdd83f..cae8bab 100644
--- a/doc/lispref/numbers.texi
+++ b/doc/lispref/numbers.texi
@@ -191,19 +191,19 @@ on 64-bit platforms.
 @cindex integer range
 @cindex number of bignum bits, limit on
 @defvar integer-width
-The value of this variable is a nonnegative integer that is an upper
-bound on the number of bits in a bignum.  Integers outside the fixnum
-range are limited to absolute values less than
+The value of this variable is a nonnegative integer that controls
+whether Emacs signals a range error when a large integer would be
+calculated.  Integers with absolute values less than
 @ifnottex
 address@hidden,
 @end ifnottex
 @tex
 @math{2^{n}},
 @end tex
-where @var{n} is this variable's value.  Attempts to create bignums outside
-this range signal a range error.  Setting this variable
-to zero disables creation of bignums; setting it to a large number can
-cause Emacs to consume large quantities of memory if a computation
+where @var{n} is this variable's value, do not signal a range error.
+Attempts to create larger integers typically signal a range error,
+although there might be no signal if a larger integer can be created cheaply.
+Setting this variable to a large number can be costly if a computation
 creates huge integers.
 @end defvar
 
diff --git a/src/alloc.c b/src/alloc.c
index 5c5b56d..64aaa8a 100644
--- a/src/alloc.c
+++ b/src/alloc.c
@@ -7369,9 +7369,9 @@ The time is in seconds as a floating point value.  */);
               doc: /* Accumulated number of garbage collections done.  */);
 
   DEFVAR_INT ("integer-width", integer_width,
-             doc: /* Maximum number of bits in bignums.
-Integers outside the fixnum range are limited to absolute values less
-than 2**N, where N is this variable's value.  N should be nonnegative.  */);
+             doc: /* Maximum number N of bits in safely-calculated integers.
+Integers with absolute values less than 2**N do not signal a range error.
+N should be nonnegative.  */);
 
   defsubr (&Scons);
   defsubr (&Slist);
diff --git a/src/bignum.c b/src/bignum.c
index 009d731..3883d3a 100644
--- a/src/bignum.c
+++ b/src/bignum.c
@@ -82,8 +82,11 @@ static Lisp_Object
 make_bignum_bits (size_t bits)
 {
   /* The documentation says integer-width should be nonnegative, so
-     a single comparison suffices even though 'bits' is unsigned.  */
-  if (integer_width < bits)
+     comparing it to BITS works even though BITS is unsigned.  Treat
+     integer-width as if it were at least twice the machine integer width,
+     so that timefns.c can safely use bignums for double-precision
+     timestamps.  */
+  if (integer_width < bits && 2 * max (INTMAX_WIDTH, UINTMAX_WIDTH) < bits)
     overflow_error ();
 
   struct Lisp_Bignum *b = ALLOCATE_PLAIN_PSEUDOVECTOR (struct Lisp_Bignum,



reply via email to

[Prev in Thread] Current Thread [Next in Thread]