aboutsummaryrefslogtreecommitdiffstats
path: root/src/floatfns.c
diff options
context:
space:
mode:
authorPaul Eggert2018-08-22 19:30:24 -0700
committerPaul Eggert2018-08-22 19:30:57 -0700
commitee641b87cf220250ba89f219fb47a4406a05deb7 (patch)
tree08ff44c5197ae39b2ec0906de4bb4dcafda4677f /src/floatfns.c
parentbe5fe6183e95f3afe3a62ec43504b99df90bc794 (diff)
downloademacs-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.c16
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
416static void 421static 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'. */
510static double
511identity (double x)
512{
513 return x;
514}
515
504DEFUN ("truncate", Ftruncate, Struncate, 1, 2, 0, 516DEFUN ("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.
506Rounds ARG toward zero. 518Rounds ARG toward zero.
507With optional DIVISOR, truncate ARG/DIVISOR. */) 519With 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