diff options
| author | Paul Eggert | 2018-09-13 14:28:56 -0700 |
|---|---|---|
| committer | Paul Eggert | 2018-09-13 14:29:58 -0700 |
| commit | c44bc4d370b38ac3e9da15579fd372d1410d4b4c (patch) | |
| tree | 5f294fabb278e1e294f35852086637e6df859ed8 /src/floatfns.c | |
| parent | 755fa346eba212b4650c8541023bb78e1658d77b (diff) | |
| download | emacs-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.c | 20 |
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 | |||
| 337 | static bool | ||
| 338 | integer_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) |