Revert to wraparound integer arithmetic, instead of going to float.
This commit is contained in:
parent
852a74a59b
commit
c717b32678
9 changed files with 79 additions and 150 deletions
|
@ -1,9 +1,6 @@
|
|||
2011-05-03 Paul Eggert <eggert@cs.ucla.edu>
|
||||
|
||||
* numbers.texi (Integer Basics): Large integers are treated as floats.
|
||||
(Arithmetic Operations, Math Functions): Large integers go to
|
||||
floats instead of wrapping around.
|
||||
* objects.texi (Integer Type): Likewise. (Bug#8611)
|
||||
|
||||
2011-04-30 Lars Magne Ingebrigtsen <larsi@gnus.org>
|
||||
|
||||
|
|
|
@ -507,9 +507,9 @@ commonly used.
|
|||
All of these functions except @code{%} return a floating point value
|
||||
if any argument is floating.
|
||||
|
||||
If integer arithmetic overflows, the resulting value is converted
|
||||
to floating point. Thus @code{(1+ 536870911)} may evaluate to
|
||||
536870912.0, depending on your hardware.
|
||||
It is important to note that in Emacs Lisp, arithmetic functions
|
||||
do not check for overflow. Thus @code{(1+ 268435455)} may evaluate to
|
||||
@minus{}268435456, depending on your hardware.
|
||||
|
||||
@defun 1+ number-or-marker
|
||||
This function returns @var{number-or-marker} plus 1.
|
||||
|
@ -826,7 +826,7 @@ On the other hand, shifting one place to the right looks like this:
|
|||
As the example illustrates, shifting one place to the right divides the
|
||||
value of a positive integer by two, rounding downward.
|
||||
|
||||
The function @code{lsh} does
|
||||
The function @code{lsh}, like all Emacs Lisp arithmetic functions, does
|
||||
not check for overflow, so shifting left can discard significant bits
|
||||
and change the sign of the number. For example, left shifting
|
||||
536,870,911 produces @minus{}2 on a 30-bit machine:
|
||||
|
@ -1169,8 +1169,8 @@ approximately.
|
|||
|
||||
@defun expt x y
|
||||
This function returns @var{x} raised to power @var{y}. If both
|
||||
arguments are integers and @var{y} is nonnegative, the result is an
|
||||
integer if it is in Emacs integer range.
|
||||
arguments are integers and @var{y} is positive, the result is an
|
||||
integer; in this case, overflow causes truncation, so watch out.
|
||||
@end defun
|
||||
|
||||
@defun sqrt arg
|
||||
|
|
|
@ -179,10 +179,10 @@ to
|
|||
@tex
|
||||
@math{2^{29}-1})
|
||||
@end tex
|
||||
on most machines. (Some machines may provide a wider range.)
|
||||
If integer arithmetic overflows, the resulting value is converted
|
||||
+to floating point. Thus @code{(1+ 536870911)} may evaluate to
|
||||
+536870912.0, depending on your hardware.
|
||||
on most machines. (Some machines may provide a wider range.) It is
|
||||
important to note that the Emacs Lisp arithmetic functions do not check
|
||||
for overflow. Thus @code{(1+ 536870911)} is @minus{}536870912 on most
|
||||
machines.
|
||||
|
||||
The read syntax for integers is a sequence of (base ten) digits with an
|
||||
optional sign at the beginning and an optional period at the end. The
|
||||
|
@ -195,8 +195,7 @@ leading @samp{+} or a final @samp{.}.
|
|||
1 ; @r{The integer 1.}
|
||||
1. ; @r{Also the integer 1.}
|
||||
+1 ; @r{Also the integer 1.}
|
||||
1073741825 ; @r{The floating point number 1073741825.0,}
|
||||
; @r{on a 30-bit implementation.}
|
||||
1073741825 ; @r{Also the integer 1 on a 30-bit implementation.}
|
||||
@end group
|
||||
@end example
|
||||
|
||||
|
|
|
@ -1,8 +1,3 @@
|
|||
2011-05-03 Paul Eggert <eggert@cs.ucla.edu>
|
||||
|
||||
* NEWS: Integer overflow now yields floating-point instead of
|
||||
wrapping around. (Bug#8611)
|
||||
|
||||
2011-05-03 Leo Liu <sdl.web@gmail.com>
|
||||
|
||||
* NEWS: Mention the new command isearch-yank-pop.
|
||||
|
|
6
etc/NEWS
6
etc/NEWS
|
@ -728,12 +728,6 @@ soap-inspect.el is an interactive inspector for SOAP WSDL structures.
|
|||
|
||||
* Incompatible Lisp Changes in Emacs 24.1
|
||||
|
||||
+++
|
||||
** Integer arithmetic overflow now yields the nearest floating-piont
|
||||
value rather than wrapping around. For example, on a 32-bit machine,
|
||||
(1+ 536870911) yields 536870912.0, instead of the -536870912 it
|
||||
yielded in Emacs 23.3, or the 0 it yielded in Emacs 23.1.
|
||||
|
||||
---
|
||||
** `char-direction-table' and the associated function `char-direction'
|
||||
were deleted. They were buggy and inferior to the new support of
|
||||
|
|
|
@ -11,16 +11,6 @@
|
|||
|
||||
* term.c: Don't include <stdarg.h>, as <lisp.h> does that.
|
||||
|
||||
Arithmetic overflows now return float rather than wrapping around.
|
||||
(Bug#8611).
|
||||
* data.c: Include <intprops.h>.
|
||||
(arith_driver): Use floating point if the accumulator would otherwise
|
||||
go out of EMACS_INT range.
|
||||
(arith_driver, Fadd1, Fsub1): Use floating point if the result is
|
||||
out of Emacs fixnum range.
|
||||
* bytecode.c (exec_byte_code): Likewise, for Bsub1, Badd1, Bnegate.
|
||||
* floatfns.c (Fexpt): Likewise.
|
||||
|
||||
* callproc.c (Fcall_process): Use 'volatile' to avoid vfork clobbering.
|
||||
|
||||
* process.c (Fformat_network_address): Fix typo: args2 -> *args2.
|
||||
|
|
|
@ -1186,7 +1186,7 @@ exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth,
|
|||
{
|
||||
Lisp_Object v1;
|
||||
v1 = TOP;
|
||||
if (INTEGERP (v1) && MOST_NEGATIVE_FIXNUM < XINT (v1))
|
||||
if (INTEGERP (v1))
|
||||
{
|
||||
XSETINT (v1, XINT (v1) - 1);
|
||||
TOP = v1;
|
||||
|
@ -1204,7 +1204,7 @@ exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth,
|
|||
{
|
||||
Lisp_Object v1;
|
||||
v1 = TOP;
|
||||
if (INTEGERP (v1) && XINT (v1) < MOST_POSITIVE_FIXNUM)
|
||||
if (INTEGERP (v1))
|
||||
{
|
||||
XSETINT (v1, XINT (v1) + 1);
|
||||
TOP = v1;
|
||||
|
@ -1290,7 +1290,7 @@ exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth,
|
|||
{
|
||||
Lisp_Object v1;
|
||||
v1 = TOP;
|
||||
if (INTEGERP (v1) && - MOST_POSITIVE_FIXNUM <= XINT (v1))
|
||||
if (INTEGERP (v1))
|
||||
{
|
||||
XSETINT (v1, - XINT (v1));
|
||||
TOP = v1;
|
||||
|
|
126
src/data.c
126
src/data.c
|
@ -22,9 +22,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
|
|||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <setjmp.h>
|
||||
|
||||
#include <intprops.h>
|
||||
|
||||
#include "lisp.h"
|
||||
#include "puresize.h"
|
||||
#include "character.h"
|
||||
|
@ -2429,8 +2426,10 @@ static Lisp_Object float_arith_driver (double, size_t, enum arithop,
|
|||
static Lisp_Object
|
||||
arith_driver (enum arithop code, size_t nargs, register Lisp_Object *args)
|
||||
{
|
||||
register Lisp_Object val;
|
||||
register size_t argnum;
|
||||
register EMACS_INT accum = 0;
|
||||
register EMACS_INT next;
|
||||
|
||||
switch (SWITCH_ENUM_CAST (code))
|
||||
{
|
||||
|
@ -2452,89 +2451,58 @@ arith_driver (enum arithop code, size_t nargs, register Lisp_Object *args)
|
|||
|
||||
for (argnum = 0; argnum < nargs; argnum++)
|
||||
{
|
||||
EMACS_INT a = accum;
|
||||
int use_float = 0;
|
||||
|
||||
/* Using args[argnum] as argument to CHECK_NUMBER_... */
|
||||
Lisp_Object val = args[argnum];
|
||||
val = args[argnum];
|
||||
CHECK_NUMBER_OR_FLOAT_COERCE_MARKER (val);
|
||||
args[argnum] = val;
|
||||
|
||||
if (FLOATP (val))
|
||||
use_float = 1;
|
||||
else
|
||||
return float_arith_driver ((double) accum, argnum, code,
|
||||
nargs, args);
|
||||
args[argnum] = val;
|
||||
next = XINT (args[argnum]);
|
||||
switch (SWITCH_ENUM_CAST (code))
|
||||
{
|
||||
EMACS_INT next = XINT (val);
|
||||
switch (SWITCH_ENUM_CAST (code))
|
||||
case Aadd:
|
||||
accum += next;
|
||||
break;
|
||||
case Asub:
|
||||
accum = argnum ? accum - next : nargs == 1 ? - next : next;
|
||||
break;
|
||||
case Amult:
|
||||
accum *= next;
|
||||
break;
|
||||
case Adiv:
|
||||
if (!argnum)
|
||||
accum = next;
|
||||
else
|
||||
{
|
||||
case Aadd:
|
||||
if (next < 0
|
||||
? a < TYPE_MINIMUM (EMACS_INT) - next
|
||||
: TYPE_MAXIMUM (EMACS_INT) - next < a)
|
||||
use_float = 1;
|
||||
else
|
||||
a += next;
|
||||
break;
|
||||
case Asub:
|
||||
if (argnum == 0 && nargs != 1)
|
||||
a = next;
|
||||
else if (next < 0
|
||||
? TYPE_MAXIMUM (EMACS_INT) + next < a
|
||||
: a < TYPE_MINIMUM (EMACS_INT) + next)
|
||||
use_float = 1;
|
||||
else
|
||||
a -= next;
|
||||
break;
|
||||
case Amult:
|
||||
if (next < 0
|
||||
? (a < 0
|
||||
? a < TYPE_MAXIMUM (EMACS_INT) / next
|
||||
: next != -1 && TYPE_MINIMUM (EMACS_INT) / next < a)
|
||||
: (next != 0
|
||||
&& (a < 0
|
||||
? a < TYPE_MINIMUM (EMACS_INT) / next
|
||||
: TYPE_MAXIMUM (EMACS_INT) / next < a)))
|
||||
use_float = 1;
|
||||
else
|
||||
a *= next;
|
||||
break;
|
||||
case Adiv:
|
||||
if (!argnum)
|
||||
a = next;
|
||||
else
|
||||
{
|
||||
if (next == 0)
|
||||
xsignal0 (Qarith_error);
|
||||
a /= next;
|
||||
}
|
||||
break;
|
||||
case Alogand:
|
||||
a &= next;
|
||||
break;
|
||||
case Alogior:
|
||||
a |= next;
|
||||
break;
|
||||
case Alogxor:
|
||||
a ^= next;
|
||||
break;
|
||||
case Amax:
|
||||
if (!argnum || a < next)
|
||||
a = next;
|
||||
break;
|
||||
case Amin:
|
||||
if (!argnum || next < a)
|
||||
a = next;
|
||||
break;
|
||||
if (next == 0)
|
||||
xsignal0 (Qarith_error);
|
||||
accum /= next;
|
||||
}
|
||||
break;
|
||||
case Alogand:
|
||||
accum &= next;
|
||||
break;
|
||||
case Alogior:
|
||||
accum |= next;
|
||||
break;
|
||||
case Alogxor:
|
||||
accum ^= next;
|
||||
break;
|
||||
case Amax:
|
||||
if (!argnum || next > accum)
|
||||
accum = next;
|
||||
break;
|
||||
case Amin:
|
||||
if (!argnum || next < accum)
|
||||
accum = next;
|
||||
break;
|
||||
}
|
||||
|
||||
if (use_float)
|
||||
return float_arith_driver (accum, argnum, code, nargs, args);
|
||||
|
||||
accum = a;
|
||||
}
|
||||
|
||||
return make_fixnum_or_float (accum);
|
||||
XSETINT (val, accum);
|
||||
return val;
|
||||
}
|
||||
|
||||
#undef isnan
|
||||
|
@ -2809,8 +2777,7 @@ Markers are converted to integers. */)
|
|||
|
||||
if (FLOATP (number))
|
||||
return (make_float (1.0 + XFLOAT_DATA (number)));
|
||||
if (XINT (number) + 1 == MOST_POSITIVE_FIXNUM + 1)
|
||||
return make_float (XINT (number) + 1);
|
||||
|
||||
XSETINT (number, XINT (number) + 1);
|
||||
return number;
|
||||
}
|
||||
|
@ -2824,8 +2791,7 @@ Markers are converted to integers. */)
|
|||
|
||||
if (FLOATP (number))
|
||||
return (make_float (-1.0 + XFLOAT_DATA (number)));
|
||||
if (XINT (number) - 1 == MOST_NEGATIVE_FIXNUM - 1)
|
||||
return make_float (XINT (number) - 1);
|
||||
|
||||
XSETINT (number, XINT (number) - 1);
|
||||
return number;
|
||||
}
|
||||
|
|
|
@ -491,39 +491,27 @@ DEFUN ("expt", Fexpt, Sexpt, 2, 2, 0,
|
|||
y = XINT (arg2);
|
||||
acc = 1;
|
||||
|
||||
if ((x == 0 && y != 0) || x == 1 || (x == -1 && (y & 1)))
|
||||
return arg1;
|
||||
if (x == -1)
|
||||
y = 0;
|
||||
|
||||
while (1)
|
||||
if (y < 0)
|
||||
{
|
||||
if (y & 1)
|
||||
{
|
||||
if (x < 0
|
||||
? (acc < 0
|
||||
? acc < MOST_POSITIVE_FIXNUM / x
|
||||
: MOST_NEGATIVE_FIXNUM / x < acc)
|
||||
: (acc < 0
|
||||
? acc < MOST_NEGATIVE_FIXNUM / x
|
||||
: MOST_POSITIVE_FIXNUM / x < acc))
|
||||
break;
|
||||
acc *= x;
|
||||
}
|
||||
|
||||
y >>= 1;
|
||||
if (y == 0)
|
||||
{
|
||||
XSETINT (val, acc);
|
||||
return val;
|
||||
}
|
||||
|
||||
if (x < 0
|
||||
? x < MOST_POSITIVE_FIXNUM / x
|
||||
: MOST_POSITIVE_FIXNUM / x < x)
|
||||
break;
|
||||
x *= x;
|
||||
if (x == 1)
|
||||
acc = 1;
|
||||
else if (x == -1)
|
||||
acc = (y & 1) ? -1 : 1;
|
||||
else
|
||||
acc = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
while (y > 0)
|
||||
{
|
||||
if (y & 1)
|
||||
acc *= x;
|
||||
x *= x;
|
||||
y = (unsigned)y >> 1;
|
||||
}
|
||||
}
|
||||
XSETINT (val, acc);
|
||||
return val;
|
||||
}
|
||||
f1 = FLOATP (arg1) ? XFLOAT_DATA (arg1) : XINT (arg1);
|
||||
f2 = FLOATP (arg2) ? XFLOAT_DATA (arg2) : XINT (arg2);
|
||||
|
|
Loading…
Add table
Reference in a new issue