diff options
| author | Paul Eggert | 2011-05-04 23:31:14 -0700 |
|---|---|---|
| committer | Paul Eggert | 2011-05-04 23:31:14 -0700 |
| commit | c717b32678affe3864f0d5024a9de514c950214d (patch) | |
| tree | 5e682fb44780734c00be9a203499b7a8651e560c /src | |
| parent | 852a74a59b12d505eba86a0aed46bfe8af7b9acf (diff) | |
| download | emacs-c717b32678affe3864f0d5024a9de514c950214d.tar.gz emacs-c717b32678affe3864f0d5024a9de514c950214d.zip | |
Revert to wraparound integer arithmetic, instead of going to float.
Diffstat (limited to 'src')
| -rw-r--r-- | src/ChangeLog | 10 | ||||
| -rw-r--r-- | src/bytecode.c | 6 | ||||
| -rw-r--r-- | src/data.c | 126 | ||||
| -rw-r--r-- | src/floatfns.c | 46 |
4 files changed, 66 insertions, 122 deletions
diff --git a/src/ChangeLog b/src/ChangeLog index ee2db310562..2b4f498a0b9 100644 --- a/src/ChangeLog +++ b/src/ChangeLog | |||
| @@ -11,16 +11,6 @@ | |||
| 11 | 11 | ||
| 12 | * term.c: Don't include <stdarg.h>, as <lisp.h> does that. | 12 | * term.c: Don't include <stdarg.h>, as <lisp.h> does that. |
| 13 | 13 | ||
| 14 | Arithmetic overflows now return float rather than wrapping around. | ||
| 15 | (Bug#8611). | ||
| 16 | * data.c: Include <intprops.h>. | ||
| 17 | (arith_driver): Use floating point if the accumulator would otherwise | ||
| 18 | go out of EMACS_INT range. | ||
| 19 | (arith_driver, Fadd1, Fsub1): Use floating point if the result is | ||
| 20 | out of Emacs fixnum range. | ||
| 21 | * bytecode.c (exec_byte_code): Likewise, for Bsub1, Badd1, Bnegate. | ||
| 22 | * floatfns.c (Fexpt): Likewise. | ||
| 23 | |||
| 24 | * callproc.c (Fcall_process): Use 'volatile' to avoid vfork clobbering. | 14 | * callproc.c (Fcall_process): Use 'volatile' to avoid vfork clobbering. |
| 25 | 15 | ||
| 26 | * process.c (Fformat_network_address): Fix typo: args2 -> *args2. | 16 | * process.c (Fformat_network_address): Fix typo: args2 -> *args2. |
diff --git a/src/bytecode.c b/src/bytecode.c index ce79b011bbb..c3cd3d43072 100644 --- a/src/bytecode.c +++ b/src/bytecode.c | |||
| @@ -1186,7 +1186,7 @@ exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth, | |||
| 1186 | { | 1186 | { |
| 1187 | Lisp_Object v1; | 1187 | Lisp_Object v1; |
| 1188 | v1 = TOP; | 1188 | v1 = TOP; |
| 1189 | if (INTEGERP (v1) && MOST_NEGATIVE_FIXNUM < XINT (v1)) | 1189 | if (INTEGERP (v1)) |
| 1190 | { | 1190 | { |
| 1191 | XSETINT (v1, XINT (v1) - 1); | 1191 | XSETINT (v1, XINT (v1) - 1); |
| 1192 | TOP = v1; | 1192 | TOP = v1; |
| @@ -1204,7 +1204,7 @@ exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth, | |||
| 1204 | { | 1204 | { |
| 1205 | Lisp_Object v1; | 1205 | Lisp_Object v1; |
| 1206 | v1 = TOP; | 1206 | v1 = TOP; |
| 1207 | if (INTEGERP (v1) && XINT (v1) < MOST_POSITIVE_FIXNUM) | 1207 | if (INTEGERP (v1)) |
| 1208 | { | 1208 | { |
| 1209 | XSETINT (v1, XINT (v1) + 1); | 1209 | XSETINT (v1, XINT (v1) + 1); |
| 1210 | TOP = v1; | 1210 | TOP = v1; |
| @@ -1290,7 +1290,7 @@ exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth, | |||
| 1290 | { | 1290 | { |
| 1291 | Lisp_Object v1; | 1291 | Lisp_Object v1; |
| 1292 | v1 = TOP; | 1292 | v1 = TOP; |
| 1293 | if (INTEGERP (v1) && - MOST_POSITIVE_FIXNUM <= XINT (v1)) | 1293 | if (INTEGERP (v1)) |
| 1294 | { | 1294 | { |
| 1295 | XSETINT (v1, - XINT (v1)); | 1295 | XSETINT (v1, - XINT (v1)); |
| 1296 | TOP = v1; | 1296 | TOP = v1; |
diff --git a/src/data.c b/src/data.c index beff570d552..577ae777d89 100644 --- a/src/data.c +++ b/src/data.c | |||
| @@ -22,9 +22,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ | |||
| 22 | #include <signal.h> | 22 | #include <signal.h> |
| 23 | #include <stdio.h> | 23 | #include <stdio.h> |
| 24 | #include <setjmp.h> | 24 | #include <setjmp.h> |
| 25 | |||
| 26 | #include <intprops.h> | ||
| 27 | |||
| 28 | #include "lisp.h" | 25 | #include "lisp.h" |
| 29 | #include "puresize.h" | 26 | #include "puresize.h" |
| 30 | #include "character.h" | 27 | #include "character.h" |
| @@ -2429,8 +2426,10 @@ static Lisp_Object float_arith_driver (double, size_t, enum arithop, | |||
| 2429 | static Lisp_Object | 2426 | static Lisp_Object |
| 2430 | arith_driver (enum arithop code, size_t nargs, register Lisp_Object *args) | 2427 | arith_driver (enum arithop code, size_t nargs, register Lisp_Object *args) |
| 2431 | { | 2428 | { |
| 2429 | register Lisp_Object val; | ||
| 2432 | register size_t argnum; | 2430 | register size_t argnum; |
| 2433 | register EMACS_INT accum = 0; | 2431 | register EMACS_INT accum = 0; |
| 2432 | register EMACS_INT next; | ||
| 2434 | 2433 | ||
| 2435 | switch (SWITCH_ENUM_CAST (code)) | 2434 | switch (SWITCH_ENUM_CAST (code)) |
| 2436 | { | 2435 | { |
| @@ -2452,89 +2451,58 @@ arith_driver (enum arithop code, size_t nargs, register Lisp_Object *args) | |||
| 2452 | 2451 | ||
| 2453 | for (argnum = 0; argnum < nargs; argnum++) | 2452 | for (argnum = 0; argnum < nargs; argnum++) |
| 2454 | { | 2453 | { |
| 2455 | EMACS_INT a = accum; | ||
| 2456 | int use_float = 0; | ||
| 2457 | |||
| 2458 | /* Using args[argnum] as argument to CHECK_NUMBER_... */ | 2454 | /* Using args[argnum] as argument to CHECK_NUMBER_... */ |
| 2459 | Lisp_Object val = args[argnum]; | 2455 | val = args[argnum]; |
| 2460 | CHECK_NUMBER_OR_FLOAT_COERCE_MARKER (val); | 2456 | CHECK_NUMBER_OR_FLOAT_COERCE_MARKER (val); |
| 2461 | args[argnum] = val; | ||
| 2462 | 2457 | ||
| 2463 | if (FLOATP (val)) | 2458 | if (FLOATP (val)) |
| 2464 | use_float = 1; | 2459 | return float_arith_driver ((double) accum, argnum, code, |
| 2465 | else | 2460 | nargs, args); |
| 2461 | args[argnum] = val; | ||
| 2462 | next = XINT (args[argnum]); | ||
| 2463 | switch (SWITCH_ENUM_CAST (code)) | ||
| 2466 | { | 2464 | { |
| 2467 | EMACS_INT next = XINT (val); | 2465 | case Aadd: |
| 2468 | switch (SWITCH_ENUM_CAST (code)) | 2466 | accum += next; |
| 2467 | break; | ||
| 2468 | case Asub: | ||
| 2469 | accum = argnum ? accum - next : nargs == 1 ? - next : next; | ||
| 2470 | break; | ||
| 2471 | case Amult: | ||
| 2472 | accum *= next; | ||
| 2473 | break; | ||
| 2474 | case Adiv: | ||
| 2475 | if (!argnum) | ||
| 2476 | accum = next; | ||
| 2477 | else | ||
| 2469 | { | 2478 | { |
| 2470 | case Aadd: | 2479 | if (next == 0) |
| 2471 | if (next < 0 | 2480 | xsignal0 (Qarith_error); |
| 2472 | ? a < TYPE_MINIMUM (EMACS_INT) - next | 2481 | accum /= next; |
| 2473 | : TYPE_MAXIMUM (EMACS_INT) - next < a) | ||
| 2474 | use_float = 1; | ||
| 2475 | else | ||
| 2476 | a += next; | ||
| 2477 | break; | ||
| 2478 | case Asub: | ||
| 2479 | if (argnum == 0 && nargs != 1) | ||
| 2480 | a = next; | ||
| 2481 | else if (next < 0 | ||
| 2482 | ? TYPE_MAXIMUM (EMACS_INT) + next < a | ||
| 2483 | : a < TYPE_MINIMUM (EMACS_INT) + next) | ||
| 2484 | use_float = 1; | ||
| 2485 | else | ||
| 2486 | a -= next; | ||
| 2487 | break; | ||
| 2488 | case Amult: | ||
| 2489 | if (next < 0 | ||
| 2490 | ? (a < 0 | ||
| 2491 | ? a < TYPE_MAXIMUM (EMACS_INT) / next | ||
| 2492 | : next != -1 && TYPE_MINIMUM (EMACS_INT) / next < a) | ||
| 2493 | : (next != 0 | ||
| 2494 | && (a < 0 | ||
| 2495 | ? a < TYPE_MINIMUM (EMACS_INT) / next | ||
| 2496 | : TYPE_MAXIMUM (EMACS_INT) / next < a))) | ||
| 2497 | use_float = 1; | ||
| 2498 | else | ||
| 2499 | a *= next; | ||
| 2500 | break; | ||
| 2501 | case Adiv: | ||
| 2502 | if (!argnum) | ||
| 2503 | a = next; | ||
| 2504 | else | ||
| 2505 | { | ||
| 2506 | if (next == 0) | ||
| 2507 | xsignal0 (Qarith_error); | ||
| 2508 | a /= next; | ||
| 2509 | } | ||
| 2510 | break; | ||
| 2511 | case Alogand: | ||
| 2512 | a &= next; | ||
| 2513 | break; | ||
| 2514 | case Alogior: | ||
| 2515 | a |= next; | ||
| 2516 | break; | ||
| 2517 | case Alogxor: | ||
| 2518 | a ^= next; | ||
| 2519 | break; | ||
| 2520 | case Amax: | ||
| 2521 | if (!argnum || a < next) | ||
| 2522 | a = next; | ||
| 2523 | break; | ||
| 2524 | case Amin: | ||
| 2525 | if (!argnum || next < a) | ||
| 2526 | a = next; | ||
| 2527 | break; | ||
| 2528 | } | 2482 | } |
| 2483 | break; | ||
| 2484 | case Alogand: | ||
| 2485 | accum &= next; | ||
| 2486 | break; | ||
| 2487 | case Alogior: | ||
| 2488 | accum |= next; | ||
| 2489 | break; | ||
| 2490 | case Alogxor: | ||
| 2491 | accum ^= next; | ||
| 2492 | break; | ||
| 2493 | case Amax: | ||
| 2494 | if (!argnum || next > accum) | ||
| 2495 | accum = next; | ||
| 2496 | break; | ||
| 2497 | case Amin: | ||
| 2498 | if (!argnum || next < accum) | ||
| 2499 | accum = next; | ||
| 2500 | break; | ||
| 2529 | } | 2501 | } |
| 2530 | |||
| 2531 | if (use_float) | ||
| 2532 | return float_arith_driver (accum, argnum, code, nargs, args); | ||
| 2533 | |||
| 2534 | accum = a; | ||
| 2535 | } | 2502 | } |
| 2536 | 2503 | ||
| 2537 | return make_fixnum_or_float (accum); | 2504 | XSETINT (val, accum); |
| 2505 | return val; | ||
| 2538 | } | 2506 | } |
| 2539 | 2507 | ||
| 2540 | #undef isnan | 2508 | #undef isnan |
| @@ -2809,8 +2777,7 @@ Markers are converted to integers. */) | |||
| 2809 | 2777 | ||
| 2810 | if (FLOATP (number)) | 2778 | if (FLOATP (number)) |
| 2811 | return (make_float (1.0 + XFLOAT_DATA (number))); | 2779 | return (make_float (1.0 + XFLOAT_DATA (number))); |
| 2812 | if (XINT (number) + 1 == MOST_POSITIVE_FIXNUM + 1) | 2780 | |
| 2813 | return make_float (XINT (number) + 1); | ||
| 2814 | XSETINT (number, XINT (number) + 1); | 2781 | XSETINT (number, XINT (number) + 1); |
| 2815 | return number; | 2782 | return number; |
| 2816 | } | 2783 | } |
| @@ -2824,8 +2791,7 @@ Markers are converted to integers. */) | |||
| 2824 | 2791 | ||
| 2825 | if (FLOATP (number)) | 2792 | if (FLOATP (number)) |
| 2826 | return (make_float (-1.0 + XFLOAT_DATA (number))); | 2793 | return (make_float (-1.0 + XFLOAT_DATA (number))); |
| 2827 | if (XINT (number) - 1 == MOST_NEGATIVE_FIXNUM - 1) | 2794 | |
| 2828 | return make_float (XINT (number) - 1); | ||
| 2829 | XSETINT (number, XINT (number) - 1); | 2795 | XSETINT (number, XINT (number) - 1); |
| 2830 | return number; | 2796 | return number; |
| 2831 | } | 2797 | } |
diff --git a/src/floatfns.c b/src/floatfns.c index 5c286772864..1232fc0afa1 100644 --- a/src/floatfns.c +++ b/src/floatfns.c | |||
| @@ -491,39 +491,27 @@ DEFUN ("expt", Fexpt, Sexpt, 2, 2, 0, | |||
| 491 | y = XINT (arg2); | 491 | y = XINT (arg2); |
| 492 | acc = 1; | 492 | acc = 1; |
| 493 | 493 | ||
| 494 | if ((x == 0 && y != 0) || x == 1 || (x == -1 && (y & 1))) | 494 | if (y < 0) |
| 495 | return arg1; | ||
| 496 | if (x == -1) | ||
| 497 | y = 0; | ||
| 498 | |||
| 499 | while (1) | ||
| 500 | { | 495 | { |
| 501 | if (y & 1) | 496 | if (x == 1) |
| 502 | { | 497 | acc = 1; |
| 503 | if (x < 0 | 498 | else if (x == -1) |
| 504 | ? (acc < 0 | 499 | acc = (y & 1) ? -1 : 1; |
| 505 | ? acc < MOST_POSITIVE_FIXNUM / x | 500 | else |
| 506 | : MOST_NEGATIVE_FIXNUM / x < acc) | 501 | acc = 0; |
| 507 | : (acc < 0 | 502 | } |
| 508 | ? acc < MOST_NEGATIVE_FIXNUM / x | 503 | else |
| 509 | : MOST_POSITIVE_FIXNUM / x < acc)) | 504 | { |
| 510 | break; | 505 | while (y > 0) |
| 511 | acc *= x; | ||
| 512 | } | ||
| 513 | |||
| 514 | y >>= 1; | ||
| 515 | if (y == 0) | ||
| 516 | { | 506 | { |
| 517 | XSETINT (val, acc); | 507 | if (y & 1) |
| 518 | return val; | 508 | acc *= x; |
| 509 | x *= x; | ||
| 510 | y = (unsigned)y >> 1; | ||
| 519 | } | 511 | } |
| 520 | |||
| 521 | if (x < 0 | ||
| 522 | ? x < MOST_POSITIVE_FIXNUM / x | ||
| 523 | : MOST_POSITIVE_FIXNUM / x < x) | ||
| 524 | break; | ||
| 525 | x *= x; | ||
| 526 | } | 512 | } |
| 513 | XSETINT (val, acc); | ||
| 514 | return val; | ||
| 527 | } | 515 | } |
| 528 | f1 = FLOATP (arg1) ? XFLOAT_DATA (arg1) : XINT (arg1); | 516 | f1 = FLOATP (arg1) ? XFLOAT_DATA (arg1) : XINT (arg1); |
| 529 | f2 = FLOATP (arg2) ? XFLOAT_DATA (arg2) : XINT (arg2); | 517 | f2 = FLOATP (arg2) ? XFLOAT_DATA (arg2) : XINT (arg2); |