aboutsummaryrefslogtreecommitdiffstats
path: root/src/floatfns.c
diff options
context:
space:
mode:
authorPaul Eggert2018-09-13 14:28:56 -0700
committerPaul Eggert2018-09-13 14:29:58 -0700
commitc44bc4d370b38ac3e9da15579fd372d1410d4b4c (patch)
tree5f294fabb278e1e294f35852086637e6df859ed8 /src/floatfns.c
parent755fa346eba212b4650c8541023bb78e1658d77b (diff)
downloademacs-c44bc4d370b38ac3e9da15579fd372d1410d4b4c.tar.gz
emacs-c44bc4d370b38ac3e9da15579fd372d1410d4b4c.zip
Fix (floor 54043195528445955 3.0) bug
* src/floatfns.c (rounding_driver): Fix rounding error that can occur when both args have values exactly representable as integers but at least one arg is a float. * test/src/floatfns-tests.el (big-round): New test.
Diffstat (limited to 'src/floatfns.c')
-rw-r--r--src/floatfns.c20
1 files changed, 19 insertions, 1 deletions
diff --git a/src/floatfns.c b/src/floatfns.c
index 6f5aee2db9d..900392575c0 100644
--- a/src/floatfns.c
+++ b/src/floatfns.c
@@ -332,6 +332,18 @@ This is the same as the exponent of a float. */)
332 return make_fixnum (value); 332 return make_fixnum (value);
333} 333}
334 334
335/* True if A is exactly representable as an integer. */
336
337static bool
338integer_value (Lisp_Object a)
339{
340 if (FLOATP (a))
341 {
342 double d = XFLOAT_DATA (a);
343 return d == floor (d) && isfinite (d);
344 }
345 return true;
346}
335 347
336/* the rounding functions */ 348/* the rounding functions */
337 349
@@ -353,10 +365,16 @@ rounding_driver (Lisp_Object arg, Lisp_Object divisor,
353 else 365 else
354 { 366 {
355 CHECK_NUMBER (divisor); 367 CHECK_NUMBER (divisor);
356 if (!FLOATP (arg) && !FLOATP (divisor)) 368 if (integer_value (arg) && integer_value (divisor))
357 { 369 {
358 /* Divide as integers. Converting to double might lose 370 /* Divide as integers. Converting to double might lose
359 info, even for fixnums; also see the FIXME below. */ 371 info, even for fixnums; also see the FIXME below. */
372
373 if (FLOATP (arg))
374 arg = double_to_integer (XFLOAT_DATA (arg));
375 if (FLOATP (divisor))
376 divisor = double_to_integer (XFLOAT_DATA (divisor));
377
360 if (FIXNUMP (divisor)) 378 if (FIXNUMP (divisor))
361 { 379 {
362 if (XFIXNUM (divisor) == 0) 380 if (XFIXNUM (divisor) == 0)