aboutsummaryrefslogtreecommitdiffstats
path: root/src/data.c
diff options
context:
space:
mode:
authorPaul Eggert2018-08-12 15:28:20 -0700
committerEli Zaretskii2018-08-13 20:16:56 +0300
commitf882de8b8095c3a42d1f6d22ed3f7aed57e9f5e0 (patch)
tree8772cc7b163793b0d9132a1ce00e21dc7c24d341 /src/data.c
parent34e75c144efe54dd6063fbb65d5a40176952422c (diff)
downloademacs-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.c43
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: