diff options
| author | Mattias EngdegÄrd | 2024-07-20 13:12:19 +0200 |
|---|---|---|
| committer | Mattias EngdegÄrd | 2024-07-27 12:04:09 +0200 |
| commit | 2fd38e5c496a2351a25e95df37a7900f6f80f22f (patch) | |
| tree | 8b4bb30916da084175a880e285ed8656e0641b70 /src | |
| parent | 156a3ba4f9ef9f7a401cfd3ca118152169f0ddcf (diff) | |
| download | emacs-2fd38e5c496a2351a25e95df37a7900f6f80f22f.tar.gz emacs-2fd38e5c496a2351a25e95df37a7900f6f80f22f.zip | |
Simplify and speed up numeric comparisons
This makes comparison functions (=, /=, <, <=, >, >=, min, max) quite
a bit faster (10-20 %). Bytecode ops on fixnums are not affected,
nor is `value<`.
* src/data.c (arithcompare): Simplify the code to reduce the number of
branches. Remove the comparison code argument; instead, return the
relation encoded as bits, which can be tested cheaply. All callers
adapted.
* src/lisp.h (enum Arith_Comparison): Remove.
(Cmp_Bit_*, cmp_bits_t): New.
Diffstat (limited to 'src')
| -rw-r--r-- | src/bytecode.c | 10 | ||||
| -rw-r--r-- | src/data.c | 160 | ||||
| -rw-r--r-- | src/fileio.c | 2 | ||||
| -rw-r--r-- | src/lisp.h | 23 |
4 files changed, 96 insertions, 99 deletions
diff --git a/src/bytecode.c b/src/bytecode.c index 75f9f1d0ac7..ce075c86afd 100644 --- a/src/bytecode.c +++ b/src/bytecode.c | |||
| @@ -1242,7 +1242,7 @@ exec_byte_code (Lisp_Object fun, ptrdiff_t args_template, | |||
| 1242 | if (FIXNUMP (v1) && FIXNUMP (v2)) | 1242 | if (FIXNUMP (v1) && FIXNUMP (v2)) |
| 1243 | TOP = BASE_EQ (v1, v2) ? Qt : Qnil; | 1243 | TOP = BASE_EQ (v1, v2) ? Qt : Qnil; |
| 1244 | else | 1244 | else |
| 1245 | TOP = arithcompare (v1, v2, ARITH_EQUAL); | 1245 | TOP = arithcompare (v1, v2) & Cmp_EQ ? Qt : Qnil; |
| 1246 | NEXT; | 1246 | NEXT; |
| 1247 | } | 1247 | } |
| 1248 | 1248 | ||
| @@ -1253,7 +1253,7 @@ exec_byte_code (Lisp_Object fun, ptrdiff_t args_template, | |||
| 1253 | if (FIXNUMP (v1) && FIXNUMP (v2)) | 1253 | if (FIXNUMP (v1) && FIXNUMP (v2)) |
| 1254 | TOP = XFIXNUM (v1) > XFIXNUM (v2) ? Qt : Qnil; | 1254 | TOP = XFIXNUM (v1) > XFIXNUM (v2) ? Qt : Qnil; |
| 1255 | else | 1255 | else |
| 1256 | TOP = arithcompare (v1, v2, ARITH_GRTR); | 1256 | TOP = arithcompare (v1, v2) & Cmp_GT ? Qt : Qnil; |
| 1257 | NEXT; | 1257 | NEXT; |
| 1258 | } | 1258 | } |
| 1259 | 1259 | ||
| @@ -1264,7 +1264,7 @@ exec_byte_code (Lisp_Object fun, ptrdiff_t args_template, | |||
| 1264 | if (FIXNUMP (v1) && FIXNUMP (v2)) | 1264 | if (FIXNUMP (v1) && FIXNUMP (v2)) |
| 1265 | TOP = XFIXNUM (v1) < XFIXNUM (v2) ? Qt : Qnil; | 1265 | TOP = XFIXNUM (v1) < XFIXNUM (v2) ? Qt : Qnil; |
| 1266 | else | 1266 | else |
| 1267 | TOP = arithcompare (v1, v2, ARITH_LESS); | 1267 | TOP = arithcompare (v1, v2) & Cmp_LT ? Qt : Qnil; |
| 1268 | NEXT; | 1268 | NEXT; |
| 1269 | } | 1269 | } |
| 1270 | 1270 | ||
| @@ -1275,7 +1275,7 @@ exec_byte_code (Lisp_Object fun, ptrdiff_t args_template, | |||
| 1275 | if (FIXNUMP (v1) && FIXNUMP (v2)) | 1275 | if (FIXNUMP (v1) && FIXNUMP (v2)) |
| 1276 | TOP = XFIXNUM (v1) <= XFIXNUM (v2) ? Qt : Qnil; | 1276 | TOP = XFIXNUM (v1) <= XFIXNUM (v2) ? Qt : Qnil; |
| 1277 | else | 1277 | else |
| 1278 | TOP = arithcompare (v1, v2, ARITH_LESS_OR_EQUAL); | 1278 | TOP = arithcompare (v1, v2) & (Cmp_LT | Cmp_EQ) ? Qt : Qnil; |
| 1279 | NEXT; | 1279 | NEXT; |
| 1280 | } | 1280 | } |
| 1281 | 1281 | ||
| @@ -1286,7 +1286,7 @@ exec_byte_code (Lisp_Object fun, ptrdiff_t args_template, | |||
| 1286 | if (FIXNUMP (v1) && FIXNUMP (v2)) | 1286 | if (FIXNUMP (v1) && FIXNUMP (v2)) |
| 1287 | TOP = XFIXNUM (v1) >= XFIXNUM (v2) ? Qt : Qnil; | 1287 | TOP = XFIXNUM (v1) >= XFIXNUM (v2) ? Qt : Qnil; |
| 1288 | else | 1288 | else |
| 1289 | TOP = arithcompare (v1, v2, ARITH_GRTR_OR_EQUAL); | 1289 | TOP = arithcompare (v1, v2) & (Cmp_GT | Cmp_EQ) ? Qt : Qnil; |
| 1290 | NEXT; | 1290 | NEXT; |
| 1291 | } | 1291 | } |
| 1292 | 1292 | ||
diff --git a/src/data.c b/src/data.c index 752856abf09..b4d08a3ff06 100644 --- a/src/data.c +++ b/src/data.c | |||
| @@ -2682,26 +2682,13 @@ check_number_coerce_marker (Lisp_Object x) | |||
| 2682 | return x; | 2682 | return x; |
| 2683 | } | 2683 | } |
| 2684 | 2684 | ||
| 2685 | Lisp_Object | 2685 | cmp_bits_t |
| 2686 | arithcompare (Lisp_Object num1, Lisp_Object num2, | 2686 | arithcompare (Lisp_Object num1, Lisp_Object num2) |
| 2687 | enum Arith_Comparison comparison) | ||
| 2688 | { | 2687 | { |
| 2689 | EMACS_INT i1 = 0, i2 = 0; | ||
| 2690 | bool lt, eq = true, gt; | ||
| 2691 | bool test; | ||
| 2692 | |||
| 2693 | num1 = check_number_coerce_marker (num1); | 2688 | num1 = check_number_coerce_marker (num1); |
| 2694 | num2 = check_number_coerce_marker (num2); | 2689 | num2 = check_number_coerce_marker (num2); |
| 2695 | 2690 | ||
| 2696 | /* If the comparison is mostly done by comparing two doubles, | 2691 | bool lt, eq, gt; |
| 2697 | set LT, EQ, and GT to the <, ==, > results of that comparison, | ||
| 2698 | respectively, taking care to avoid problems if either is a NaN, | ||
| 2699 | and trying to avoid problems on platforms where variables (in | ||
| 2700 | violation of the C standard) can contain excess precision. | ||
| 2701 | Regardless, set I1 and I2 to integers that break ties if the | ||
| 2702 | two-double comparison is either not done or reports | ||
| 2703 | equality. */ | ||
| 2704 | |||
| 2705 | if (FLOATP (num1)) | 2692 | if (FLOATP (num1)) |
| 2706 | { | 2693 | { |
| 2707 | double f1 = XFLOAT_DATA (num1); | 2694 | double f1 = XFLOAT_DATA (num1); |
| @@ -2723,16 +2710,30 @@ arithcompare (Lisp_Object num1, Lisp_Object num2, | |||
| 2723 | (exactly) so I1 - I2 = NUM1 - NUM2 (exactly), so comparing I1 | 2710 | (exactly) so I1 - I2 = NUM1 - NUM2 (exactly), so comparing I1 |
| 2724 | to I2 will break the tie correctly. */ | 2711 | to I2 will break the tie correctly. */ |
| 2725 | double f2 = XFIXNUM (num2); | 2712 | double f2 = XFIXNUM (num2); |
| 2726 | lt = f1 < f2; | 2713 | if (f1 == f2) |
| 2727 | eq = f1 == f2; | 2714 | { |
| 2728 | gt = f1 > f2; | 2715 | EMACS_INT i1 = f2; |
| 2729 | i1 = f2; | 2716 | EMACS_INT i2 = XFIXNUM (num2); |
| 2730 | i2 = XFIXNUM (num2); | 2717 | eq = i1 == i2; |
| 2718 | lt = i1 < i2; | ||
| 2719 | gt = i1 > i2; | ||
| 2720 | } | ||
| 2721 | else | ||
| 2722 | { | ||
| 2723 | eq = false; | ||
| 2724 | lt = f1 < f2; | ||
| 2725 | gt = f1 > f2; | ||
| 2726 | } | ||
| 2731 | } | 2727 | } |
| 2732 | else if (isnan (f1)) | 2728 | else if (isnan (f1)) |
| 2733 | lt = eq = gt = false; | 2729 | lt = eq = gt = false; |
| 2734 | else | 2730 | else |
| 2735 | i2 = mpz_cmp_d (*xbignum_val (num2), f1); | 2731 | { |
| 2732 | int cmp = mpz_cmp_d (*xbignum_val (num2), f1); | ||
| 2733 | eq = cmp == 0; | ||
| 2734 | lt = cmp > 0; | ||
| 2735 | gt = cmp < 0; | ||
| 2736 | } | ||
| 2736 | } | 2737 | } |
| 2737 | else if (FIXNUMP (num1)) | 2738 | else if (FIXNUMP (num1)) |
| 2738 | { | 2739 | { |
| @@ -2741,19 +2742,36 @@ arithcompare (Lisp_Object num1, Lisp_Object num2, | |||
| 2741 | /* Compare an integer NUM1 to a float NUM2. This is the | 2742 | /* Compare an integer NUM1 to a float NUM2. This is the |
| 2742 | converse of comparing float to integer (see above). */ | 2743 | converse of comparing float to integer (see above). */ |
| 2743 | double f1 = XFIXNUM (num1), f2 = XFLOAT_DATA (num2); | 2744 | double f1 = XFIXNUM (num1), f2 = XFLOAT_DATA (num2); |
| 2744 | lt = f1 < f2; | 2745 | if (f1 == f2) |
| 2745 | eq = f1 == f2; | 2746 | { |
| 2746 | gt = f1 > f2; | 2747 | EMACS_INT i1 = XFIXNUM (num1); |
| 2747 | i1 = XFIXNUM (num1); | 2748 | EMACS_INT i2 = f1; |
| 2748 | i2 = f1; | 2749 | eq = i1 == i2; |
| 2750 | lt = i1 < i2; | ||
| 2751 | gt = i1 > i2; | ||
| 2752 | } | ||
| 2753 | else | ||
| 2754 | { | ||
| 2755 | eq = false; | ||
| 2756 | lt = f1 < f2; | ||
| 2757 | gt = f1 > f2; | ||
| 2758 | } | ||
| 2749 | } | 2759 | } |
| 2750 | else if (FIXNUMP (num2)) | 2760 | else if (FIXNUMP (num2)) |
| 2751 | { | 2761 | { |
| 2752 | i1 = XFIXNUM (num1); | 2762 | EMACS_INT i1 = XFIXNUM (num1); |
| 2753 | i2 = XFIXNUM (num2); | 2763 | EMACS_INT i2 = XFIXNUM (num2); |
| 2764 | eq = i1 == i2; | ||
| 2765 | lt = i1 < i2; | ||
| 2766 | gt = i1 > i2; | ||
| 2754 | } | 2767 | } |
| 2755 | else | 2768 | else |
| 2756 | i2 = mpz_sgn (*xbignum_val (num2)); | 2769 | { |
| 2770 | int sgn = mpz_sgn (*xbignum_val (num2)); | ||
| 2771 | eq = sgn == 0; | ||
| 2772 | lt = sgn > 0; | ||
| 2773 | gt = sgn < 0; | ||
| 2774 | } | ||
| 2757 | } | 2775 | } |
| 2758 | else if (FLOATP (num2)) | 2776 | else if (FLOATP (num2)) |
| 2759 | { | 2777 | { |
| @@ -2761,61 +2779,36 @@ arithcompare (Lisp_Object num1, Lisp_Object num2, | |||
| 2761 | if (isnan (f2)) | 2779 | if (isnan (f2)) |
| 2762 | lt = eq = gt = false; | 2780 | lt = eq = gt = false; |
| 2763 | else | 2781 | else |
| 2764 | i1 = mpz_cmp_d (*xbignum_val (num1), f2); | 2782 | { |
| 2783 | int cmp = mpz_cmp_d (*xbignum_val (num1), f2); | ||
| 2784 | eq = cmp == 0; | ||
| 2785 | lt = cmp < 0; | ||
| 2786 | gt = cmp > 0; | ||
| 2787 | } | ||
| 2765 | } | 2788 | } |
| 2766 | else if (FIXNUMP (num2)) | 2789 | else if (FIXNUMP (num2)) |
| 2767 | i1 = mpz_sgn (*xbignum_val (num1)); | ||
| 2768 | else | ||
| 2769 | i1 = mpz_cmp (*xbignum_val (num1), *xbignum_val (num2)); | ||
| 2770 | |||
| 2771 | if (eq) | ||
| 2772 | { | 2790 | { |
| 2773 | /* The two-double comparison either reported equality, or was not done. | 2791 | int sgn = mpz_sgn (*xbignum_val (num1)); |
| 2774 | Break the tie by comparing the integers. */ | 2792 | eq = sgn == 0; |
| 2775 | lt = i1 < i2; | 2793 | lt = sgn < 0; |
| 2776 | eq = i1 == i2; | 2794 | gt = sgn > 0; |
| 2777 | gt = i1 > i2; | ||
| 2778 | } | 2795 | } |
| 2779 | 2796 | else | |
| 2780 | switch (comparison) | ||
| 2781 | { | 2797 | { |
| 2782 | case ARITH_EQUAL: | 2798 | int cmp = mpz_cmp (*xbignum_val (num1), *xbignum_val (num2)); |
| 2783 | test = eq; | 2799 | eq = cmp == 0; |
| 2784 | break; | 2800 | lt = cmp < 0; |
| 2785 | 2801 | gt = cmp > 0; | |
| 2786 | case ARITH_NOTEQUAL: | ||
| 2787 | test = !eq; | ||
| 2788 | break; | ||
| 2789 | |||
| 2790 | case ARITH_LESS: | ||
| 2791 | test = lt; | ||
| 2792 | break; | ||
| 2793 | |||
| 2794 | case ARITH_LESS_OR_EQUAL: | ||
| 2795 | test = lt | eq; | ||
| 2796 | break; | ||
| 2797 | |||
| 2798 | case ARITH_GRTR: | ||
| 2799 | test = gt; | ||
| 2800 | break; | ||
| 2801 | |||
| 2802 | case ARITH_GRTR_OR_EQUAL: | ||
| 2803 | test = gt | eq; | ||
| 2804 | break; | ||
| 2805 | |||
| 2806 | default: | ||
| 2807 | eassume (false); | ||
| 2808 | } | 2802 | } |
| 2809 | 2803 | ||
| 2810 | return test ? Qt : Qnil; | 2804 | return lt << Cmp_Bit_LT | gt << Cmp_Bit_GT | eq << Cmp_Bit_EQ; |
| 2811 | } | 2805 | } |
| 2812 | 2806 | ||
| 2813 | static Lisp_Object | 2807 | static Lisp_Object |
| 2814 | arithcompare_driver (ptrdiff_t nargs, Lisp_Object *args, | 2808 | arithcompare_driver (ptrdiff_t nargs, Lisp_Object *args, cmp_bits_t cmpmask) |
| 2815 | enum Arith_Comparison comparison) | ||
| 2816 | { | 2809 | { |
| 2817 | for (ptrdiff_t i = 1; i < nargs; i++) | 2810 | for (ptrdiff_t i = 1; i < nargs; i++) |
| 2818 | if (NILP (arithcompare (args[i - 1], args[i], comparison))) | 2811 | if (!(arithcompare (args[i - 1], args[i]) & cmpmask)) |
| 2819 | return Qnil; | 2812 | return Qnil; |
| 2820 | return Qt; | 2813 | return Qt; |
| 2821 | } | 2814 | } |
| @@ -2825,7 +2818,7 @@ DEFUN ("=", Feqlsign, Seqlsign, 1, MANY, 0, | |||
| 2825 | usage: (= NUMBER-OR-MARKER &rest NUMBERS-OR-MARKERS) */) | 2818 | usage: (= NUMBER-OR-MARKER &rest NUMBERS-OR-MARKERS) */) |
| 2826 | (ptrdiff_t nargs, Lisp_Object *args) | 2819 | (ptrdiff_t nargs, Lisp_Object *args) |
| 2827 | { | 2820 | { |
| 2828 | return arithcompare_driver (nargs, args, ARITH_EQUAL); | 2821 | return arithcompare_driver (nargs, args, Cmp_EQ); |
| 2829 | } | 2822 | } |
| 2830 | 2823 | ||
| 2831 | DEFUN ("<", Flss, Slss, 1, MANY, 0, | 2824 | DEFUN ("<", Flss, Slss, 1, MANY, 0, |
| @@ -2836,7 +2829,7 @@ usage: (< NUMBER-OR-MARKER &rest NUMBERS-OR-MARKERS) */) | |||
| 2836 | if (nargs == 2 && FIXNUMP (args[0]) && FIXNUMP (args[1])) | 2829 | if (nargs == 2 && FIXNUMP (args[0]) && FIXNUMP (args[1])) |
| 2837 | return XFIXNUM (args[0]) < XFIXNUM (args[1]) ? Qt : Qnil; | 2830 | return XFIXNUM (args[0]) < XFIXNUM (args[1]) ? Qt : Qnil; |
| 2838 | 2831 | ||
| 2839 | return arithcompare_driver (nargs, args, ARITH_LESS); | 2832 | return arithcompare_driver (nargs, args, Cmp_LT); |
| 2840 | } | 2833 | } |
| 2841 | 2834 | ||
| 2842 | DEFUN (">", Fgtr, Sgtr, 1, MANY, 0, | 2835 | DEFUN (">", Fgtr, Sgtr, 1, MANY, 0, |
| @@ -2847,7 +2840,7 @@ usage: (> NUMBER-OR-MARKER &rest NUMBERS-OR-MARKERS) */) | |||
| 2847 | if (nargs == 2 && FIXNUMP (args[0]) && FIXNUMP (args[1])) | 2840 | if (nargs == 2 && FIXNUMP (args[0]) && FIXNUMP (args[1])) |
| 2848 | return XFIXNUM (args[0]) > XFIXNUM (args[1]) ? Qt : Qnil; | 2841 | return XFIXNUM (args[0]) > XFIXNUM (args[1]) ? Qt : Qnil; |
| 2849 | 2842 | ||
| 2850 | return arithcompare_driver (nargs, args, ARITH_GRTR); | 2843 | return arithcompare_driver (nargs, args, Cmp_GT); |
| 2851 | } | 2844 | } |
| 2852 | 2845 | ||
| 2853 | DEFUN ("<=", Fleq, Sleq, 1, MANY, 0, | 2846 | DEFUN ("<=", Fleq, Sleq, 1, MANY, 0, |
| @@ -2858,7 +2851,7 @@ usage: (<= NUMBER-OR-MARKER &rest NUMBERS-OR-MARKERS) */) | |||
| 2858 | if (nargs == 2 && FIXNUMP (args[0]) && FIXNUMP (args[1])) | 2851 | if (nargs == 2 && FIXNUMP (args[0]) && FIXNUMP (args[1])) |
| 2859 | return XFIXNUM (args[0]) <= XFIXNUM (args[1]) ? Qt : Qnil; | 2852 | return XFIXNUM (args[0]) <= XFIXNUM (args[1]) ? Qt : Qnil; |
| 2860 | 2853 | ||
| 2861 | return arithcompare_driver (nargs, args, ARITH_LESS_OR_EQUAL); | 2854 | return arithcompare_driver (nargs, args, Cmp_LT | Cmp_EQ); |
| 2862 | } | 2855 | } |
| 2863 | 2856 | ||
| 2864 | DEFUN (">=", Fgeq, Sgeq, 1, MANY, 0, | 2857 | DEFUN (">=", Fgeq, Sgeq, 1, MANY, 0, |
| @@ -2869,14 +2862,14 @@ usage: (>= NUMBER-OR-MARKER &rest NUMBERS-OR-MARKERS) */) | |||
| 2869 | if (nargs == 2 && FIXNUMP (args[0]) && FIXNUMP (args[1])) | 2862 | if (nargs == 2 && FIXNUMP (args[0]) && FIXNUMP (args[1])) |
| 2870 | return XFIXNUM (args[0]) >= XFIXNUM (args[1]) ? Qt : Qnil; | 2863 | return XFIXNUM (args[0]) >= XFIXNUM (args[1]) ? Qt : Qnil; |
| 2871 | 2864 | ||
| 2872 | return arithcompare_driver (nargs, args, ARITH_GRTR_OR_EQUAL); | 2865 | return arithcompare_driver (nargs, args, Cmp_GT | Cmp_EQ); |
| 2873 | } | 2866 | } |
| 2874 | 2867 | ||
| 2875 | DEFUN ("/=", Fneq, Sneq, 2, 2, 0, | 2868 | DEFUN ("/=", Fneq, Sneq, 2, 2, 0, |
| 2876 | doc: /* Return t if first arg is not equal to second arg. Both must be numbers or markers. */) | 2869 | doc: /* Return t if first arg is not equal to second arg. Both must be numbers or markers. */) |
| 2877 | (register Lisp_Object num1, Lisp_Object num2) | 2870 | (register Lisp_Object num1, Lisp_Object num2) |
| 2878 | { | 2871 | { |
| 2879 | return arithcompare (num1, num2, ARITH_NOTEQUAL); | 2872 | return arithcompare (num1, num2) & Cmp_EQ ? Qnil : Qt; |
| 2880 | } | 2873 | } |
| 2881 | 2874 | ||
| 2882 | /* Convert the cons-of-integers, integer, or float value C to an | 2875 | /* Convert the cons-of-integers, integer, or float value C to an |
| @@ -3418,14 +3411,13 @@ Both X and Y must be numbers or markers. */) | |||
| 3418 | } | 3411 | } |
| 3419 | 3412 | ||
| 3420 | static Lisp_Object | 3413 | static Lisp_Object |
| 3421 | minmax_driver (ptrdiff_t nargs, Lisp_Object *args, | 3414 | minmax_driver (ptrdiff_t nargs, Lisp_Object *args, cmp_bits_t cmpmask) |
| 3422 | enum Arith_Comparison comparison) | ||
| 3423 | { | 3415 | { |
| 3424 | Lisp_Object accum = check_number_coerce_marker (args[0]); | 3416 | Lisp_Object accum = check_number_coerce_marker (args[0]); |
| 3425 | for (ptrdiff_t argnum = 1; argnum < nargs; argnum++) | 3417 | for (ptrdiff_t argnum = 1; argnum < nargs; argnum++) |
| 3426 | { | 3418 | { |
| 3427 | Lisp_Object val = check_number_coerce_marker (args[argnum]); | 3419 | Lisp_Object val = check_number_coerce_marker (args[argnum]); |
| 3428 | if (!NILP (arithcompare (val, accum, comparison))) | 3420 | if (arithcompare (val, accum) & cmpmask) |
| 3429 | accum = val; | 3421 | accum = val; |
| 3430 | else if (FLOATP (val) && isnan (XFLOAT_DATA (val))) | 3422 | else if (FLOATP (val) && isnan (XFLOAT_DATA (val))) |
| 3431 | return val; | 3423 | return val; |
| @@ -3439,7 +3431,7 @@ The value is always a number; markers are converted to numbers. | |||
| 3439 | usage: (max NUMBER-OR-MARKER &rest NUMBERS-OR-MARKERS) */) | 3431 | usage: (max NUMBER-OR-MARKER &rest NUMBERS-OR-MARKERS) */) |
| 3440 | (ptrdiff_t nargs, Lisp_Object *args) | 3432 | (ptrdiff_t nargs, Lisp_Object *args) |
| 3441 | { | 3433 | { |
| 3442 | return minmax_driver (nargs, args, ARITH_GRTR); | 3434 | return minmax_driver (nargs, args, Cmp_GT); |
| 3443 | } | 3435 | } |
| 3444 | 3436 | ||
| 3445 | DEFUN ("min", Fmin, Smin, 1, MANY, 0, | 3437 | DEFUN ("min", Fmin, Smin, 1, MANY, 0, |
| @@ -3448,7 +3440,7 @@ The value is always a number; markers are converted to numbers. | |||
| 3448 | usage: (min NUMBER-OR-MARKER &rest NUMBERS-OR-MARKERS) */) | 3440 | usage: (min NUMBER-OR-MARKER &rest NUMBERS-OR-MARKERS) */) |
| 3449 | (ptrdiff_t nargs, Lisp_Object *args) | 3441 | (ptrdiff_t nargs, Lisp_Object *args) |
| 3450 | { | 3442 | { |
| 3451 | return minmax_driver (nargs, args, ARITH_LESS); | 3443 | return minmax_driver (nargs, args, Cmp_LT); |
| 3452 | } | 3444 | } |
| 3453 | 3445 | ||
| 3454 | DEFUN ("logand", Flogand, Slogand, 0, MANY, 0, | 3446 | DEFUN ("logand", Flogand, Slogand, 0, MANY, 0, |
diff --git a/src/fileio.c b/src/fileio.c index fa280f2db00..22a566a1881 100644 --- a/src/fileio.c +++ b/src/fileio.c | |||
| @@ -5741,7 +5741,7 @@ DEFUN ("car-less-than-car", Fcar_less_than_car, Scar_less_than_car, 2, 2, 0, | |||
| 5741 | Lisp_Object ca = Fcar (a), cb = Fcar (b); | 5741 | Lisp_Object ca = Fcar (a), cb = Fcar (b); |
| 5742 | if (FIXNUMP (ca) && FIXNUMP (cb)) | 5742 | if (FIXNUMP (ca) && FIXNUMP (cb)) |
| 5743 | return XFIXNUM (ca) < XFIXNUM (cb) ? Qt : Qnil; | 5743 | return XFIXNUM (ca) < XFIXNUM (cb) ? Qt : Qnil; |
| 5744 | return arithcompare (ca, cb, ARITH_LESS); | 5744 | return arithcompare (ca, cb) & Cmp_LT ? Qt : Qnil; |
| 5745 | } | 5745 | } |
| 5746 | 5746 | ||
| 5747 | /* Build the complete list of annotations appropriate for writing out | 5747 | /* Build the complete list of annotations appropriate for writing out |
diff --git a/src/lisp.h b/src/lisp.h index 976b7a15251..8ac65ca429c 100644 --- a/src/lisp.h +++ b/src/lisp.h | |||
| @@ -4224,16 +4224,21 @@ extern void notify_variable_watchers (Lisp_Object, Lisp_Object, | |||
| 4224 | Lisp_Object, Lisp_Object); | 4224 | Lisp_Object, Lisp_Object); |
| 4225 | extern Lisp_Object indirect_function (Lisp_Object); | 4225 | extern Lisp_Object indirect_function (Lisp_Object); |
| 4226 | extern Lisp_Object find_symbol_value (Lisp_Object); | 4226 | extern Lisp_Object find_symbol_value (Lisp_Object); |
| 4227 | enum Arith_Comparison { | 4227 | |
| 4228 | ARITH_EQUAL, | 4228 | enum { |
| 4229 | ARITH_NOTEQUAL, | 4229 | Cmp_Bit_EQ, |
| 4230 | ARITH_LESS, | 4230 | Cmp_Bit_LT, |
| 4231 | ARITH_GRTR, | 4231 | Cmp_Bit_GT |
| 4232 | ARITH_LESS_OR_EQUAL, | ||
| 4233 | ARITH_GRTR_OR_EQUAL | ||
| 4234 | }; | 4232 | }; |
| 4235 | extern Lisp_Object arithcompare (Lisp_Object num1, Lisp_Object num2, | 4233 | |
| 4236 | enum Arith_Comparison comparison); | 4234 | /* code indicating a comparison outcome */ |
| 4235 | typedef enum { | ||
| 4236 | Cmp_EQ = 1 << Cmp_Bit_EQ, /* = */ | ||
| 4237 | Cmp_LT = 1 << Cmp_Bit_LT, /* < */ | ||
| 4238 | Cmp_GT = 1 << Cmp_Bit_GT /* > */ | ||
| 4239 | } cmp_bits_t; | ||
| 4240 | |||
| 4241 | extern cmp_bits_t arithcompare (Lisp_Object num1, Lisp_Object num2); | ||
| 4237 | 4242 | ||
| 4238 | /* Convert the Emacs representation CONS back to an integer of type | 4243 | /* Convert the Emacs representation CONS back to an integer of type |
| 4239 | TYPE, storing the result the variable VAR. Signal an error if CONS | 4244 | TYPE, storing the result the variable VAR. Signal an error if CONS |