summaryrefslogtreecommitdiff
path: root/src/floatfns.c
diff options
context:
space:
mode:
authorPaul Eggert <eggert@Penguin.CS.UCLA.EDU>2018-09-13 14:28:56 -0700
committerPaul Eggert <eggert@cs.ucla.edu>2018-09-13 14:29:58 -0700
commitc44bc4d370b38ac3e9da15579fd372d1410d4b4c (patch)
tree5f294fabb278e1e294f35852086637e6df859ed8 /src/floatfns.c
parent755fa346eba212b4650c8541023bb78e1658d77b (diff)
downloademacs-c44bc4d370b38ac3e9da15579fd372d1410d4b4c.tar.gz
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. */)
return make_fixnum (value);
}
+/* True if A is exactly representable as an integer. */
+
+static bool
+integer_value (Lisp_Object a)
+{
+ if (FLOATP (a))
+ {
+ double d = XFLOAT_DATA (a);
+ return d == floor (d) && isfinite (d);
+ }
+ return true;
+}
/* the rounding functions */
@@ -353,10 +365,16 @@ rounding_driver (Lisp_Object arg, Lisp_Object divisor,
else
{
CHECK_NUMBER (divisor);
- if (!FLOATP (arg) && !FLOATP (divisor))
+ if (integer_value (arg) && integer_value (divisor))
{
/* Divide as integers. Converting to double might lose
info, even for fixnums; also see the FIXME below. */
+
+ if (FLOATP (arg))
+ arg = double_to_integer (XFLOAT_DATA (arg));
+ if (FLOATP (divisor))
+ divisor = double_to_integer (XFLOAT_DATA (divisor));
+
if (FIXNUMP (divisor))
{
if (XFIXNUM (divisor) == 0)