diff options
| author | Paul Eggert | 2018-08-22 19:30:24 -0700 |
|---|---|---|
| committer | Paul Eggert | 2018-08-22 19:30:57 -0700 |
| commit | ee641b87cf220250ba89f219fb47a4406a05deb7 (patch) | |
| tree | 08ff44c5197ae39b2ec0906de4bb4dcafda4677f /src/floatfns.c | |
| parent | be5fe6183e95f3afe3a62ec43504b99df90bc794 (diff) | |
| download | emacs-ee641b87cf220250ba89f219fb47a4406a05deb7.tar.gz emacs-ee641b87cf220250ba89f219fb47a4406a05deb7.zip | |
Fix bugs when rounding to bignums
Also, since Emacs historically reported a range error when
rounding operations overflowed, do that consistently for all
bignum overflows.
* doc/lispref/errors.texi (Standard Errors):
* doc/lispref/numbers.texi (Integer Basics): Document range errors.
* src/alloc.c (range_error): Rename from integer_overflow.
All uses changed.
* src/floatfns.c (rounding_driver): When the result of a floating
point rounding operation does not fit into a fixnum, put it
into a bignum instead of always signaling an range error.
* test/src/floatfns-tests.el (divide-extreme-sign):
These tests now return the mathematically-correct answer
instead of signaling an error.
(bignum-round): Check that integers round to themselves.
Diffstat (limited to 'src/floatfns.c')
| -rw-r--r-- | src/floatfns.c | 16 |
1 files changed, 14 insertions, 2 deletions
diff --git a/src/floatfns.c b/src/floatfns.c index c09fe9d6a5b..e7884864eef 100644 --- a/src/floatfns.c +++ b/src/floatfns.c | |||
| @@ -410,7 +410,12 @@ rounding_driver (Lisp_Object arg, Lisp_Object divisor, | |||
| 410 | if (! FIXNUM_OVERFLOW_P (ir)) | 410 | if (! FIXNUM_OVERFLOW_P (ir)) |
| 411 | return make_fixnum (ir); | 411 | return make_fixnum (ir); |
| 412 | } | 412 | } |
| 413 | xsignal2 (Qrange_error, build_string (name), arg); | 413 | mpz_t drz; |
| 414 | mpz_init (drz); | ||
| 415 | mpz_set_d (drz, dr); | ||
| 416 | Lisp_Object rounded = make_number (drz); | ||
| 417 | mpz_clear (drz); | ||
| 418 | return rounded; | ||
| 414 | } | 419 | } |
| 415 | 420 | ||
| 416 | static void | 421 | static void |
| @@ -501,13 +506,20 @@ systems, but 2 on others. */) | |||
| 501 | return rounding_driver (arg, divisor, emacs_rint, rounddiv_q, "round"); | 506 | return rounding_driver (arg, divisor, emacs_rint, rounddiv_q, "round"); |
| 502 | } | 507 | } |
| 503 | 508 | ||
| 509 | /* Since rounding_driver truncates anyway, no need to call 'trunc'. */ | ||
| 510 | static double | ||
| 511 | identity (double x) | ||
| 512 | { | ||
| 513 | return x; | ||
| 514 | } | ||
| 515 | |||
| 504 | DEFUN ("truncate", Ftruncate, Struncate, 1, 2, 0, | 516 | DEFUN ("truncate", Ftruncate, Struncate, 1, 2, 0, |
| 505 | doc: /* Truncate a floating point number to an int. | 517 | doc: /* Truncate a floating point number to an int. |
| 506 | Rounds ARG toward zero. | 518 | Rounds ARG toward zero. |
| 507 | With optional DIVISOR, truncate ARG/DIVISOR. */) | 519 | With optional DIVISOR, truncate ARG/DIVISOR. */) |
| 508 | (Lisp_Object arg, Lisp_Object divisor) | 520 | (Lisp_Object arg, Lisp_Object divisor) |
| 509 | { | 521 | { |
| 510 | return rounding_driver (arg, divisor, trunc, mpz_tdiv_q, "truncate"); | 522 | return rounding_driver (arg, divisor, identity, mpz_tdiv_q, "truncate"); |
| 511 | } | 523 | } |
| 512 | 524 | ||
| 513 | 525 | ||