aboutsummaryrefslogtreecommitdiffstats
path: root/src/data.c
diff options
context:
space:
mode:
authorPaul Eggert2018-08-12 15:28:20 -0700
committerPaul Eggert2018-08-12 15:31:28 -0700
commita84cef90957f2379cc0df6bd908317fc441971ce (patch)
treeec13b83e5b54cb7c4757dad817ac7fadc0fc2c28 /src/data.c
parent2b1cac26855b99644b00a839f7ea25446d997572 (diff)
downloademacs-a84cef90957f2379cc0df6bd908317fc441971ce.tar.gz
emacs-a84cef90957f2379cc0df6bd908317fc441971ce.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.
Diffstat (limited to 'src/data.c')
-rw-r--r--src/data.c43
1 files changed, 29 insertions, 14 deletions
diff --git a/src/data.c b/src/data.c
index c8a9c6b3783..7b8dd45c948 100644
--- a/src/data.c
+++ b/src/data.c
@@ -2492,7 +2492,7 @@ arithcompare (Lisp_Object num1, Lisp_Object num2,
2492{ 2492{
2493 double f1, f2; 2493 double f1, f2;
2494 EMACS_INT i1, i2; 2494 EMACS_INT i1, i2;
2495 bool fneq; 2495 bool lt, eq, gt;
2496 bool test; 2496 bool test;
2497 2497
2498 CHECK_NUMBER_COERCE_MARKER (num1); 2498 CHECK_NUMBER_COERCE_MARKER (num1);
@@ -2502,10 +2502,13 @@ arithcompare (Lisp_Object num1, Lisp_Object num2,
2502 return bignumcompare (num1, num2, comparison); 2502 return bignumcompare (num1, num2, comparison);
2503 2503
2504 /* If either arg is floating point, set F1 and F2 to the 'double' 2504 /* If either arg is floating point, set F1 and F2 to the 'double'
2505 approximations of the two arguments, and set FNEQ if floating-point 2505 approximations of the two arguments, and set LT, EQ, and GT to
2506 comparison reports that F1 is not equal to F2, possibly because F1 2506 the <, ==, > floating-point comparisons of F1 and F2
2507 or F2 is a NaN. Regardless, set I1 and I2 to integers that break 2507 respectively, taking care to avoid problems if either is a NaN,
2508 ties if the floating-point comparison is either not done or reports 2508 and trying to avoid problems on platforms where variables (in
2509 violation of the C standard) can contain excess precision.
2510 Regardless, set I1 and I2 to integers that break ties if the
2511 floating-point comparison is either not done or reports
2509 equality. */ 2512 equality. */
2510 2513
2511 if (FLOATP (num1)) 2514 if (FLOATP (num1))
@@ -2528,7 +2531,9 @@ arithcompare (Lisp_Object num1, Lisp_Object num2,
2528 to I2 will break the tie correctly. */ 2531 to I2 will break the tie correctly. */
2529 i1 = f2 = i2 = XFIXNUM (num2); 2532 i1 = f2 = i2 = XFIXNUM (num2);
2530 } 2533 }
2531 fneq = f1 != f2; 2534 lt = f1 < f2;
2535 eq = f1 == f2;
2536 gt = f1 > f2;
2532 } 2537 }
2533 else 2538 else
2534 { 2539 {
@@ -2539,39 +2544,49 @@ arithcompare (Lisp_Object num1, Lisp_Object num2,
2539 converse of comparing float to integer (see above). */ 2544 converse of comparing float to integer (see above). */
2540 i2 = f1 = i1; 2545 i2 = f1 = i1;
2541 f2 = XFLOAT_DATA (num2); 2546 f2 = XFLOAT_DATA (num2);
2542 fneq = f1 != f2; 2547 lt = f1 < f2;
2548 eq = f1 == f2;
2549 gt = f1 > f2;
2543 } 2550 }
2544 else 2551 else
2545 { 2552 {
2546 i2 = XFIXNUM (num2); 2553 i2 = XFIXNUM (num2);
2547 fneq = false; 2554 eq = true;
2548 } 2555 }
2549 } 2556 }
2550 2557
2558 if (eq)
2559 {
2560 /* Break a floating-point tie by comparing the integers. */
2561 lt = i1 < i2;
2562 eq = i1 == i2;
2563 gt = i1 > i2;
2564 }
2565
2551 switch (comparison) 2566 switch (comparison)
2552 { 2567 {
2553 case ARITH_EQUAL: 2568 case ARITH_EQUAL:
2554 test = !fneq && i1 == i2; 2569 test = eq;
2555 break; 2570 break;
2556 2571
2557 case ARITH_NOTEQUAL: 2572 case ARITH_NOTEQUAL:
2558 test = fneq || i1 != i2; 2573 test = !eq;
2559 break; 2574 break;
2560 2575
2561 case ARITH_LESS: 2576 case ARITH_LESS:
2562 test = fneq ? f1 < f2 : i1 < i2; 2577 test = lt;
2563 break; 2578 break;
2564 2579
2565 case ARITH_LESS_OR_EQUAL: 2580 case ARITH_LESS_OR_EQUAL:
2566 test = fneq ? f1 <= f2 : i1 <= i2; 2581 test = lt | eq;
2567 break; 2582 break;
2568 2583
2569 case ARITH_GRTR: 2584 case ARITH_GRTR:
2570 test = fneq ? f1 > f2 : i1 > i2; 2585 test = gt;
2571 break; 2586 break;
2572 2587
2573 case ARITH_GRTR_OR_EQUAL: 2588 case ARITH_GRTR_OR_EQUAL:
2574 test = fneq ? f1 >= f2 : i1 >= i2; 2589 test = gt | eq;
2575 break; 2590 break;
2576 2591
2577 default: 2592 default: