diff options
| author | Paul Eggert | 2018-08-12 15:28:20 -0700 |
|---|---|---|
| committer | Eli Zaretskii | 2018-08-13 20:16:56 +0300 |
| commit | f882de8b8095c3a42d1f6d22ed3f7aed57e9f5e0 (patch) | |
| tree | 8772cc7b163793b0d9132a1ce00e21dc7c24d341 /src/data.c | |
| parent | 34e75c144efe54dd6063fbb65d5a40176952422c (diff) | |
| download | emacs-f882de8b8095c3a42d1f6d22ed3f7aed57e9f5e0.tar.gz emacs-f882de8b8095c3a42d1f6d22ed3f7aed57e9f5e0.zip | |
Port better to x86 -fexcess-precision=fast
Problem reported by Eli Zaretskii in:
https://lists.gnu.org/r/emacs-devel/2018-08/msg00380.html
* src/data.c (arithcompare): Work around incompatibility
between gcc -fexcess-precision=fast and the C standard on x86,
by capturing the results of floating-point comparisons before
the excess precision spontaneously decays. Although this fix
might not work in general, it does work here and is probably
good enough for the platforms we care about.
(cherry picked from commit a84cef90957f2379cc0df6bd908317fc441971ce)
Diffstat (limited to 'src/data.c')
| -rw-r--r-- | src/data.c | 43 |
1 files changed, 29 insertions, 14 deletions
diff --git a/src/data.c b/src/data.c index 4bee194e296..4569f002420 100644 --- a/src/data.c +++ b/src/data.c | |||
| @@ -2411,17 +2411,20 @@ arithcompare (Lisp_Object num1, Lisp_Object num2, | |||
| 2411 | { | 2411 | { |
| 2412 | double f1, f2; | 2412 | double f1, f2; |
| 2413 | EMACS_INT i1, i2; | 2413 | EMACS_INT i1, i2; |
| 2414 | bool fneq; | 2414 | bool lt, eq, gt; |
| 2415 | bool test; | 2415 | bool test; |
| 2416 | 2416 | ||
| 2417 | CHECK_NUMBER_OR_FLOAT_COERCE_MARKER (num1); | 2417 | CHECK_NUMBER_OR_FLOAT_COERCE_MARKER (num1); |
| 2418 | CHECK_NUMBER_OR_FLOAT_COERCE_MARKER (num2); | 2418 | CHECK_NUMBER_OR_FLOAT_COERCE_MARKER (num2); |
| 2419 | 2419 | ||
| 2420 | /* If either arg is floating point, set F1 and F2 to the 'double' | 2420 | /* If either arg is floating point, set F1 and F2 to the 'double' |
| 2421 | approximations of the two arguments, and set FNEQ if floating-point | 2421 | approximations of the two arguments, and set LT, EQ, and GT to |
| 2422 | comparison reports that F1 is not equal to F2, possibly because F1 | 2422 | the <, ==, > floating-point comparisons of F1 and F2 |
| 2423 | or F2 is a NaN. Regardless, set I1 and I2 to integers that break | 2423 | respectively, taking care to avoid problems if either is a NaN, |
| 2424 | ties if the floating-point comparison is either not done or reports | 2424 | and trying to avoid problems on platforms where variables (in |
| 2425 | violation of the C standard) can contain excess precision. | ||
| 2426 | Regardless, set I1 and I2 to integers that break ties if the | ||
| 2427 | floating-point comparison is either not done or reports | ||
| 2425 | equality. */ | 2428 | equality. */ |
| 2426 | 2429 | ||
| 2427 | if (FLOATP (num1)) | 2430 | if (FLOATP (num1)) |
| @@ -2444,7 +2447,9 @@ arithcompare (Lisp_Object num1, Lisp_Object num2, | |||
| 2444 | to I2 will break the tie correctly. */ | 2447 | to I2 will break the tie correctly. */ |
| 2445 | i1 = f2 = i2 = XINT (num2); | 2448 | i1 = f2 = i2 = XINT (num2); |
| 2446 | } | 2449 | } |
| 2447 | fneq = f1 != f2; | 2450 | lt = f1 < f2; |
| 2451 | eq = f1 == f2; | ||
| 2452 | gt = f1 > f2; | ||
| 2448 | } | 2453 | } |
| 2449 | else | 2454 | else |
| 2450 | { | 2455 | { |
| @@ -2455,39 +2460,49 @@ arithcompare (Lisp_Object num1, Lisp_Object num2, | |||
| 2455 | converse of comparing float to integer (see above). */ | 2460 | converse of comparing float to integer (see above). */ |
| 2456 | i2 = f1 = i1; | 2461 | i2 = f1 = i1; |
| 2457 | f2 = XFLOAT_DATA (num2); | 2462 | f2 = XFLOAT_DATA (num2); |
| 2458 | fneq = f1 != f2; | 2463 | lt = f1 < f2; |
| 2464 | eq = f1 == f2; | ||
| 2465 | gt = f1 > f2; | ||
| 2459 | } | 2466 | } |
| 2460 | else | 2467 | else |
| 2461 | { | 2468 | { |
| 2462 | i2 = XINT (num2); | 2469 | i2 = XINT (num2); |
| 2463 | fneq = false; | 2470 | eq = true; |
| 2464 | } | 2471 | } |
| 2465 | } | 2472 | } |
| 2466 | 2473 | ||
| 2474 | if (eq) | ||
| 2475 | { | ||
| 2476 | /* Break a floating-point tie by comparing the integers. */ | ||
| 2477 | lt = i1 < i2; | ||
| 2478 | eq = i1 == i2; | ||
| 2479 | gt = i1 > i2; | ||
| 2480 | } | ||
| 2481 | |||
| 2467 | switch (comparison) | 2482 | switch (comparison) |
| 2468 | { | 2483 | { |
| 2469 | case ARITH_EQUAL: | 2484 | case ARITH_EQUAL: |
| 2470 | test = !fneq && i1 == i2; | 2485 | test = eq; |
| 2471 | break; | 2486 | break; |
| 2472 | 2487 | ||
| 2473 | case ARITH_NOTEQUAL: | 2488 | case ARITH_NOTEQUAL: |
| 2474 | test = fneq || i1 != i2; | 2489 | test = !eq; |
| 2475 | break; | 2490 | break; |
| 2476 | 2491 | ||
| 2477 | case ARITH_LESS: | 2492 | case ARITH_LESS: |
| 2478 | test = fneq ? f1 < f2 : i1 < i2; | 2493 | test = lt; |
| 2479 | break; | 2494 | break; |
| 2480 | 2495 | ||
| 2481 | case ARITH_LESS_OR_EQUAL: | 2496 | case ARITH_LESS_OR_EQUAL: |
| 2482 | test = fneq ? f1 <= f2 : i1 <= i2; | 2497 | test = lt | eq; |
| 2483 | break; | 2498 | break; |
| 2484 | 2499 | ||
| 2485 | case ARITH_GRTR: | 2500 | case ARITH_GRTR: |
| 2486 | test = fneq ? f1 > f2 : i1 > i2; | 2501 | test = gt; |
| 2487 | break; | 2502 | break; |
| 2488 | 2503 | ||
| 2489 | case ARITH_GRTR_OR_EQUAL: | 2504 | case ARITH_GRTR_OR_EQUAL: |
| 2490 | test = fneq ? f1 >= f2 : i1 >= i2; | 2505 | test = gt | eq; |
| 2491 | break; | 2506 | break; |
| 2492 | 2507 | ||
| 2493 | default: | 2508 | default: |