From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: Barry OReilly Newsgroups: gmane.emacs.bugs Subject: bug#14892: [PATCH] Enhance Elisp compare functions (< <= > >=) to take var args Date: Tue, 10 Sep 2013 19:35:43 -0400 Message-ID: References: NNTP-Posting-Host: plane.gmane.org Mime-Version: 1.0 Content-Type: multipart/alternative; boundary=f46d0443044e9b3a5e04e60ff679 X-Trace: ger.gmane.org 1378856177 26927 80.91.229.3 (10 Sep 2013 23:36:17 GMT) X-Complaints-To: usenet@ger.gmane.org NNTP-Posting-Date: Tue, 10 Sep 2013 23:36:17 +0000 (UTC) Cc: 14892@debbugs.gnu.org To: Stefan Monnier Original-X-From: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org Wed Sep 11 01:36:17 2013 Return-path: Envelope-to: geb-bug-gnu-emacs@m.gmane.org Original-Received: from lists.gnu.org ([208.118.235.17]) by plane.gmane.org with esmtp (Exim 4.69) (envelope-from ) id 1VJXTl-0001lk-5V for geb-bug-gnu-emacs@m.gmane.org; Wed, 11 Sep 2013 01:36:17 +0200 Original-Received: from localhost ([::1]:60448 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1VJXTk-0006zr-JE for geb-bug-gnu-emacs@m.gmane.org; Tue, 10 Sep 2013 19:36:16 -0400 Original-Received: from eggs.gnu.org ([2001:4830:134:3::10]:43353) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1VJXTc-0006ze-0r for bug-gnu-emacs@gnu.org; Tue, 10 Sep 2013 19:36:12 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1VJXTX-0006w4-4V for bug-gnu-emacs@gnu.org; Tue, 10 Sep 2013 19:36:07 -0400 Original-Received: from debbugs.gnu.org ([140.186.70.43]:45353) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1VJXTW-0006ve-W4 for bug-gnu-emacs@gnu.org; Tue, 10 Sep 2013 19:36:03 -0400 Original-Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.80) (envelope-from ) id 1VJXTW-0001tq-DR for bug-gnu-emacs@gnu.org; Tue, 10 Sep 2013 19:36:02 -0400 X-Loop: help-debbugs@gnu.org Resent-From: Barry OReilly Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Tue, 10 Sep 2013 23:36:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 14892 X-GNU-PR-Package: emacs X-GNU-PR-Keywords: patch Original-Received: via spool by 14892-submit@debbugs.gnu.org id=B14892.13788561547286 (code B ref 14892); Tue, 10 Sep 2013 23:36:02 +0000 Original-Received: (at 14892) by debbugs.gnu.org; 10 Sep 2013 23:35:54 +0000 Original-Received: from localhost ([127.0.0.1]:53644 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.80) (envelope-from ) id 1VJXTN-0001tQ-3X for submit@debbugs.gnu.org; Tue, 10 Sep 2013 19:35:54 -0400 Original-Received: from mail-we0-f173.google.com ([74.125.82.173]:44105) by debbugs.gnu.org with esmtp (Exim 4.80) (envelope-from ) id 1VJXTJ-0001tA-5p for 14892@debbugs.gnu.org; Tue, 10 Sep 2013 19:35:50 -0400 Original-Received: by mail-we0-f173.google.com with SMTP id w62so6316624wes.32 for <14892@debbugs.gnu.org>; Tue, 10 Sep 2013 16:35:43 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=mime-version:in-reply-to:references:date:message-id:subject:from:to :cc:content-type; bh=wD5csNclfIlbNggTpo2M4G1UXbNbkUbTqFYWOLyfYw4=; b=Qdujli3BwU5cS/c2oMzFJKv8zVi1So64T06xD4zAplYujNbIWjGmeT0invYm27/UnW nv2p7s9s4TCxb2zyL8SUElyKL3Zx/C4dE4crJqucCxkNuPkil+J7oNZ+xwsGw78X7LE0 Vk4J0g0CjWFf3JGVbaGKxtOl12jbAgVyX47khJO7OBgQIdaM6/GZRTOFKV18BRUsep9d e9q7WcGPgS3IAO3nnUWcHzHuq15trs+2yDg5E7zxTHCAqrrqjIWiV64nOoz2gI2VQqcr gu12jp3WoTdiUryGBvRmcY++DT9P7bPXiqRq0i3A5LAjE10f+qSGdudXcjJ0TMHRf5ms hocg== X-Received: by 10.180.97.38 with SMTP id dx6mr15056854wib.26.1378856143107; Tue, 10 Sep 2013 16:35:43 -0700 (PDT) Original-Received: by 10.194.234.234 with HTTP; Tue, 10 Sep 2013 16:35:43 -0700 (PDT) In-Reply-To: X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.15 Precedence: list X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x X-Received-From: 140.186.70.43 X-BeenThere: bug-gnu-emacs@gnu.org List-Id: "Bug reports for GNU Emacs, the Swiss army knife of text editors" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org Original-Sender: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org Xref: news.gmane.org gmane.emacs.bugs:78198 Archived-At: --f46d0443044e9b3a5e04e60ff679 Content-Type: text/plain; charset=ISO-8859-1 Benchmarking the same way: Before patch: (0.062154 0 0.0) After patch: (0.061831 0 0.0) I renamed the comparison enum as I moved it to lisp.h so as it is less polluting to those that include it. diff --git a/src/bytecode.c b/src/bytecode.c index e0e7b22..3ac8b45 100644 --- a/src/bytecode.c +++ b/src/bytecode.c @@ -1367,7 +1367,7 @@ exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth, Lisp_Object v1; BEFORE_POTENTIAL_GC (); v1 = POP; - TOP = Fgtr (TOP, v1); + TOP = arithcompare (TOP, v1, ARITH_GRTR); AFTER_POTENTIAL_GC (); NEXT; } @@ -1377,7 +1377,7 @@ exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth, Lisp_Object v1; BEFORE_POTENTIAL_GC (); v1 = POP; - TOP = Flss (TOP, v1); + TOP = arithcompare (TOP, v1, ARITH_LESS); AFTER_POTENTIAL_GC (); NEXT; } @@ -1387,7 +1387,7 @@ exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth, Lisp_Object v1; BEFORE_POTENTIAL_GC (); v1 = POP; - TOP = Fleq (TOP, v1); + TOP = arithcompare (TOP, v1, ARITH_LESS_OR_EQUAL); AFTER_POTENTIAL_GC (); NEXT; } @@ -1397,7 +1397,7 @@ exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth, Lisp_Object v1; BEFORE_POTENTIAL_GC (); v1 = POP; - TOP = Fgeq (TOP, v1); + TOP = arithcompare (TOP, v1, ARITH_GRTR_OR_EQUAL); AFTER_POTENTIAL_GC (); NEXT; } diff --git a/src/data.c b/src/data.c index 9f4bd1f..7f28028 100644 --- a/src/data.c +++ b/src/data.c @@ -2255,10 +2255,8 @@ bool-vector. IDX starts at 0. */) /* Arithmetic functions */ -enum comparison { equal, notequal, less, grtr, less_or_equal, grtr_or_equal }; - -static Lisp_Object -arithcompare (Lisp_Object num1, Lisp_Object num2, enum comparison comparison) +Lisp_Object +arithcompare (Lisp_Object num1, Lisp_Object num2, enum Arith_Comparison comparison) { double f1 = 0, f2 = 0; bool floatp = 0; @@ -2275,32 +2273,32 @@ arithcompare (Lisp_Object num1, Lisp_Object num2, enum comparison comparison) switch (comparison) { - case equal: + case ARITH_EQUAL: if (floatp ? f1 == f2 : XINT (num1) == XINT (num2)) return Qt; return Qnil; - case notequal: + case ARITH_NOTEQUAL: if (floatp ? f1 != f2 : XINT (num1) != XINT (num2)) return Qt; return Qnil; - case less: + case ARITH_LESS: if (floatp ? f1 < f2 : XINT (num1) < XINT (num2)) return Qt; return Qnil; - case less_or_equal: + case ARITH_LESS_OR_EQUAL: if (floatp ? f1 <= f2 : XINT (num1) <= XINT (num2)) return Qt; return Qnil; - case grtr: + case ARITH_GRTR: if (floatp ? f1 > f2 : XINT (num1) > XINT (num2)) return Qt; return Qnil; - case grtr_or_equal: + case ARITH_GRTR_OR_EQUAL: if (floatp ? f1 >= f2 : XINT (num1) >= XINT (num2)) return Qt; return Qnil; @@ -2310,48 +2308,60 @@ arithcompare (Lisp_Object num1, Lisp_Object num2, enum comparison comparison) } } -DEFUN ("=", Feqlsign, Seqlsign, 2, 2, 0, - doc: /* Return t if two args, both numbers or markers, are equal. */) - (register Lisp_Object num1, Lisp_Object num2) +static Lisp_Object +arithcompare_driver (ptrdiff_t nargs, Lisp_Object *args, + enum Arith_Comparison comparison) { - return arithcompare (num1, num2, equal); + for (ptrdiff_t argnum = 1; argnum < nargs; ++argnum) + { + if (EQ (Qnil, arithcompare (args[argnum-1], args[argnum], comparison))) + return Qnil; + } + return Qt; } -DEFUN ("<", Flss, Slss, 2, 2, 0, - doc: /* Return t if first arg is less than second arg. Both must be numbers or markers. */) - (register Lisp_Object num1, Lisp_Object num2) +DEFUN ("=", Feqlsign, Seqlsign, 1, MANY, 0, + doc: /* Return t if args, all numbers or markers, are equal. */) + (ptrdiff_t nargs, Lisp_Object *args) { - return arithcompare (num1, num2, less); + return arithcompare_driver (nargs, args, ARITH_EQUAL); } -DEFUN (">", Fgtr, Sgtr, 2, 2, 0, - doc: /* Return t if first arg is greater than second arg. Both must be numbers or markers. */) - (register Lisp_Object num1, Lisp_Object num2) +DEFUN ("<", Flss, Slss, 1, MANY, 0, + doc: /* Return t if each arg is less than the next arg. All must be numbers or markers. */) + (ptrdiff_t nargs, Lisp_Object *args) { - return arithcompare (num1, num2, grtr); + return arithcompare_driver (nargs, args, ARITH_LESS); } -DEFUN ("<=", Fleq, Sleq, 2, 2, 0, - doc: /* Return t if first arg is less than or equal to second arg. -Both must be numbers or markers. */) - (register Lisp_Object num1, Lisp_Object num2) +DEFUN (">", Fgtr, Sgtr, 1, MANY, 0, + doc: /* Return t if each arg is greater than the next arg. All must be numbers or markers. */) + (ptrdiff_t nargs, Lisp_Object *args) { - return arithcompare (num1, num2, less_or_equal); + return arithcompare_driver (nargs, args, ARITH_GRTR); } -DEFUN (">=", Fgeq, Sgeq, 2, 2, 0, - doc: /* Return t if first arg is greater than or equal to second arg. -Both must be numbers or markers. */) - (register Lisp_Object num1, Lisp_Object num2) +DEFUN ("<=", Fleq, Sleq, 1, MANY, 0, + doc: /* Return t if each arg is less than or equal to the next arg. +All must be numbers or markers. */) + (ptrdiff_t nargs, Lisp_Object *args) +{ + return arithcompare_driver (nargs, args, ARITH_LESS_OR_EQUAL); +} + +DEFUN (">=", Fgeq, Sgeq, 1, MANY, 0, + doc: /* Return t if each arg is greater than or equal to the next arg. +All must be numbers or markers. */) + (ptrdiff_t nargs, Lisp_Object *args) { - return arithcompare (num1, num2, grtr_or_equal); + return arithcompare_driver (nargs, args, ARITH_GRTR_OR_EQUAL); } DEFUN ("/=", Fneq, Sneq, 2, 2, 0, doc: /* Return t if first arg is not equal to second arg. Both must be numbers or markers. */) (register Lisp_Object num1, Lisp_Object num2) { - return arithcompare (num1, num2, notequal); + return arithcompare (num1, num2, ARITH_NOTEQUAL); } DEFUN ("zerop", Fzerop, Szerop, 1, 1, 0, diff --git a/src/fileio.c b/src/fileio.c index 0e6113f..1a2bdfa 100644 --- a/src/fileio.c +++ b/src/fileio.c @@ -5121,7 +5121,8 @@ DEFUN ("car-less-than-car", Fcar_less_than_car, Scar_less_than_car, 2, 2, 0, doc: /* Return t if (car A) is numerically less than (car B). */) (Lisp_Object a, Lisp_Object b) { - return Flss (Fcar (a), Fcar (b)); + Lisp_Object args[2] = { Fcar (a), Fcar (b), }; + return Flss (2, args); } /* Build the complete list of annotations appropriate for writing out diff --git a/src/lisp.h b/src/lisp.h index 38b538d..2b1af1f 100644 --- a/src/lisp.h +++ b/src/lisp.h @@ -3160,6 +3160,16 @@ EXFUN (Fbyteorder, 0) ATTRIBUTE_CONST; /* Defined in data.c. */ extern Lisp_Object indirect_function (Lisp_Object); extern Lisp_Object find_symbol_value (Lisp_Object); +enum Arith_Comparison { + ARITH_EQUAL, + ARITH_NOTEQUAL, + ARITH_LESS, + ARITH_GRTR, + ARITH_LESS_OR_EQUAL, + ARITH_GRTR_OR_EQUAL +}; +extern Lisp_Object arithcompare (Lisp_Object num1, Lisp_Object num2, + enum Arith_Comparison comparison); /* Convert the integer I to an Emacs representation, either the integer itself, or a cons of two or three integers, or if all else fails a float. diff --git a/test/automated/data-tests.el b/test/automated/data-tests.el index e69de29..2298fa3 100644 --- a/test/automated/data-tests.el +++ b/test/automated/data-tests.el @@ -0,0 +1,75 @@ +;;; data-tests.el --- tests for src/data.c + +;; Copyright (C) 2013 Free Software Foundation, Inc. + +;; This file is part of GNU Emacs. + +;; This program is free software: you can redistribute it and/or +;; modify it under the terms of the GNU General Public License as +;; published by the Free Software Foundation, either version 3 of the +;; License, or (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, but +;; WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +;; General Public License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see `http://www.gnu.org/licenses/'. + +;;; Commentary: + +;;; Code: + +(ert-deftest data-tests-= () + (should-error (=)) + (should (= 1)) + (should (= 2 2)) + (should (= 9 9 9 9 9 9 9 9 9)) + (should-not (apply #'= '(3 8 3))) + (should-error (= 9 9 'foo)) + ;; Short circuits before getting to bad arg + (should-not (= 9 8 'foo))) + +(ert-deftest data-tests-< () + (should-error (<)) + (should (< 1)) + (should (< 2 3)) + (should (< -6 -1 0 2 3 4 8 9 999)) + (should-not (apply #'< '(3 8 3))) + (should-error (< 9 10 'foo)) + ;; Short circuits before getting to bad arg + (should-not (< 9 8 'foo))) + +(ert-deftest data-tests-> () + (should-error (>)) + (should (> 1)) + (should (> 3 2)) + (should (> 6 1 0 -2 -3 -4 -8 -9 -999)) + (should-not (apply #'> '(3 8 3))) + (should-error (> 9 8 'foo)) + ;; Short circuits before getting to bad arg + (should-not (> 8 9 'foo))) + +(ert-deftest data-tests-<= () + (should-error (<=)) + (should (<= 1)) + (should (<= 2 3)) + (should (<= -6 -1 -1 0 0 0 2 3 4 8 999)) + (should-not (apply #'<= '(3 8 3 3))) + (should-error (<= 9 10 'foo)) + ;; Short circuits before getting to bad arg + (should-not (<= 9 8 'foo))) + +(ert-deftest data-tests->= () + (should-error (>=)) + (should (>= 1)) + (should (>= 3 2)) + (should (>= 666 1 0 0 -2 -3 -3 -3 -4 -8 -8 -9 -999)) + (should-not (apply #'>= '(3 8 3))) + (should-error (>= 9 8 'foo)) + ;; Short circuits before getting to bad arg + (should-not (>= 8 9 'foo))) + +;;; data-tests.el ends here + --f46d0443044e9b3a5e04e60ff679 Content-Type: text/html; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable
Benchmarking the same way:

=A0 Before patch: (0.062= 154 0 0.0)
=A0 After patch:=A0 (0.061831 0 0.0)

I renamed the com= parison enum as I moved it to lisp.h so as it is less
polluting to those= that include it.

diff --git a/src/bytecode.c b/src/bytecode.c
index e0e7b22..3ac8b45 = 100644
--- a/src/bytecode.c
+++ b/src/bytecode.c
@@ -1367,7 +1367,= 7 @@ exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object m= axdepth,
=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 Lisp_Object v1;
=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0 BEFORE_POTENTIAL_GC ();
=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 v= 1 =3D POP;
-=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 TOP =3D Fgtr (TOP, v1);
+= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 TOP =3D arithcompare (TOP, v1, ARITH_GRTR);<= br>=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 AFTER_POTENTIAL_GC ();
=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 NEXT;
=A0=A0=A0=A0=A0=A0=A0=A0=A0 }@@ -1377,7 +1377,7 @@ exec_byte_code (Lisp_Object bytestr, Lisp_Object vec= tor, Lisp_Object maxdepth,
=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 Lisp_Object= v1;
=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 BEFORE_POTENTIAL_GC ();
=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0 v1 =3D POP;
-=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 TOP =3D Flss (TOP, v1);
+=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0 TOP =3D arithcompare (TOP, v1, ARITH_LESS);
=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0 AFTER_POTENTIAL_GC ();
=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0 NEXT;
=A0=A0=A0=A0=A0=A0=A0=A0=A0 }
@@ -1387,7 +1387,7 @@ exec= _byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth,<= br> =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 Lisp_Object v1;
=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0 BEFORE_POTENTIAL_GC ();
=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 v= 1 =3D POP;
-=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 TOP =3D Fleq (TOP, v1);
+= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 TOP =3D arithcompare (TOP, v1, ARITH_LESS_OR= _EQUAL);
=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 AFTER_POTENTIAL_GC ();
=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 NEXT;
=A0=A0=A0=A0=A0=A0=A0=A0=A0 }@@ -1397,7 +1397,7 @@ exec_byte_code (Lisp_Object bytestr, Lisp_Object vec= tor, Lisp_Object maxdepth,
=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 Lisp_Object= v1;
=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 BEFORE_POTENTIAL_GC ();
=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0 v1 =3D POP;
-=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 TOP =3D Fgeq (TOP, v1);
+=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0 TOP =3D arithcompare (TOP, v1, ARITH_GRTR_OR_EQUAL);
=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 AFTER_POTENTIAL_GC ();
=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0 NEXT;
=A0=A0=A0=A0=A0=A0=A0=A0=A0 }
diff --git a/src/= data.c b/src/data.c
index 9f4bd1f..7f28028 100644
--- a/src/data.c
+++ b/src/data.c
@@ -2255,10 +2255,8 @@ bool-vector.= =A0 IDX starts at 0.=A0 */)
=A0

=A0/* Arithmetic functions */
= =A0
-enum comparison { equal, notequal, less, grtr, less_or_equal, grtr_= or_equal };
-
-static Lisp_Object
-arithcompare (Lisp_Object num1, Lisp_Object nu= m2, enum comparison comparison)
+Lisp_Object
+arithcompare (Lisp_Obje= ct num1, Lisp_Object num2, enum Arith_Comparison comparison)
=A0{
=A0= =A0 double f1 =3D 0, f2 =3D 0;
=A0=A0 bool floatp =3D 0;
@@ -2275,32 +2273,32 @@ arithcompare (Lisp_Obj= ect num1, Lisp_Object num2, enum comparison comparison)
=A0
=A0=A0 sw= itch (comparison)
=A0=A0=A0=A0 {
-=A0=A0=A0 case equal:
+=A0=A0=A0= case ARITH_EQUAL:
=A0=A0=A0=A0=A0=A0 if (floatp ? f1 =3D=3D f2 : XINT (= num1) =3D=3D XINT (num2))
=A0=A0=A0=A0=A0=A0=A0 return Qt;
=A0=A0=A0=A0=A0=A0 return Qnil;
=A0<= br>-=A0=A0=A0 case notequal:
+=A0=A0=A0 case ARITH_NOTEQUAL:
=A0=A0= =A0=A0=A0=A0 if (floatp ? f1 !=3D f2 : XINT (num1) !=3D XINT (num2))
=A0= =A0=A0=A0=A0=A0=A0 return Qt;
=A0=A0=A0=A0=A0=A0 return Qnil;
=A0
= -=A0=A0=A0 case less:
+=A0=A0=A0 case ARITH_LESS:
=A0=A0=A0=A0=A0=A0 if (floatp ? f1 < f2 := XINT (num1) < XINT (num2))
=A0=A0=A0=A0=A0=A0=A0 return Qt;
=A0= =A0=A0=A0=A0=A0 return Qnil;
=A0
-=A0=A0=A0 case less_or_equal:
+= =A0=A0=A0 case ARITH_LESS_OR_EQUAL:
=A0=A0=A0=A0=A0=A0 if (floatp ? f1 &= lt;=3D f2 : XINT (num1) <=3D XINT (num2))
=A0=A0=A0=A0=A0=A0=A0 return Qt;
=A0=A0=A0=A0=A0=A0 return Qnil;
=A0<= br>-=A0=A0=A0 case grtr:
+=A0=A0=A0 case ARITH_GRTR:
=A0=A0=A0=A0=A0= =A0 if (floatp ? f1 > f2 : XINT (num1) > XINT (num2))
=A0=A0=A0=A0= =A0=A0=A0 return Qt;
=A0=A0=A0=A0=A0=A0 return Qnil;
=A0
-=A0=A0= =A0 case grtr_or_equal:
+=A0=A0=A0 case ARITH_GRTR_OR_EQUAL:
=A0=A0=A0=A0=A0=A0 if (floatp ? f1 = >=3D f2 : XINT (num1) >=3D XINT (num2))
=A0=A0=A0=A0=A0=A0=A0 retu= rn Qt;
=A0=A0=A0=A0=A0=A0 return Qnil;
@@ -2310,48 +2308,60 @@ arithc= ompare (Lisp_Object num1, Lisp_Object num2, enum comparison comparison)
=A0=A0=A0=A0 }
=A0}
=A0
-DEFUN ("=3D", Feqlsign, Seqlsig= n, 2, 2, 0,
-=A0=A0=A0=A0=A0=A0 doc: /* Return t if two args, both numbe= rs or markers, are equal.=A0 */)
-=A0 (register Lisp_Object num1, Lisp_O= bject num2)
+static Lisp_Object
+arithcompare_driver (ptrdiff_t nargs, Lisp_Object *args,
+=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 enum Arith_Comparison comp= arison)
=A0{
-=A0 return arithcompare (num1, num2, equal);
+=A0 fo= r (ptrdiff_t argnum =3D 1; argnum < nargs; ++argnum)
+=A0=A0=A0 {
+=A0=A0=A0=A0=A0 if (EQ (Qnil, arithcompare (args[argnum-1]= , args[argnum], comparison)))
+=A0=A0=A0=A0=A0=A0=A0 return Qnil;
+= =A0=A0=A0 }
+=A0 return Qt;
=A0}
=A0
-DEFUN ("<", = Flss, Slss, 2, 2, 0,
-=A0=A0=A0=A0=A0=A0 doc: /* Return t if first arg i= s less than second arg.=A0 Both must be numbers or markers.=A0 */)
-=A0 (register Lisp_Object num1, Lisp_Object num2)
+DEFUN ("=3D&quo= t;, Feqlsign, Seqlsign, 1, MANY, 0,
+=A0=A0=A0=A0=A0=A0 doc: /* Return t= if args, all numbers or markers, are equal.=A0 */)
+=A0 (ptrdiff_t narg= s, Lisp_Object *args)
=A0{
-=A0 return arithcompare (num1, num2, less);
+=A0 return arithco= mpare_driver (nargs, args, ARITH_EQUAL);
=A0}
=A0
-DEFUN ("&g= t;", Fgtr, Sgtr, 2, 2, 0,
-=A0=A0=A0=A0=A0=A0 doc: /* Return t if f= irst arg is greater than second arg.=A0 Both must be numbers or markers.=A0= */)
-=A0 (register Lisp_Object num1, Lisp_Object num2)
+DEFUN ("<&qu= ot;, Flss, Slss, 1, MANY, 0,
+=A0=A0=A0=A0=A0=A0 doc: /* Return t if eac= h arg is less than the next arg.=A0 All must be numbers or markers.=A0 */)<= br>+=A0 (ptrdiff_t nargs, Lisp_Object *args)
=A0{
-=A0 return arithcompare (num1, num2, grtr);
+=A0 return arithco= mpare_driver (nargs, args, ARITH_LESS);
=A0}
=A0
-DEFUN ("<= ;=3D", Fleq, Sleq, 2, 2, 0,
-=A0=A0=A0=A0=A0=A0 doc: /* Return t if= first arg is less than or equal to second arg.
-Both must be numbers or markers.=A0 */)
-=A0 (register Lisp_Object num1= , Lisp_Object num2)
+DEFUN (">", Fgtr, Sgtr, 1, MANY, 0,+=A0=A0=A0=A0=A0=A0 doc: /* Return t if each arg is greater than the next = arg.=A0 All must be numbers or markers.=A0 */)
+=A0 (ptrdiff_t nargs, Lisp_Object *args)
=A0{
-=A0 return arithcompa= re (num1, num2, less_or_equal);
+=A0 return arithcompare_driver (nargs, = args, ARITH_GRTR);
=A0}
=A0
-DEFUN (">=3D", Fgeq, Sge= q, 2, 2, 0,
-=A0=A0=A0=A0=A0=A0 doc: /* Return t if first arg is greater than or equal = to second arg.
-Both must be numbers or markers.=A0 */)
-=A0 (registe= r Lisp_Object num1, Lisp_Object num2)
+DEFUN ("<=3D", Fleq,= Sleq, 1, MANY, 0,
+=A0=A0=A0=A0=A0=A0 doc: /* Return t if each arg is less than or equal to t= he next arg.
+All must be numbers or markers.=A0 */)
+=A0 (ptrdiff_t = nargs, Lisp_Object *args)
+{
+=A0 return arithcompare_driver (nargs, = args, ARITH_LESS_OR_EQUAL);
+}
+
+DEFUN (">=3D", Fgeq, Sgeq, 1, MANY, 0,
+=A0=A0= =A0=A0=A0=A0 doc: /* Return t if each arg is greater than or equal to the n= ext arg.
+All must be numbers or markers.=A0 */)
+=A0 (ptrdiff_t narg= s, Lisp_Object *args)
=A0{
-=A0 return arithcompare (num1, num2, grtr_or_equal);
+=A0 retur= n arithcompare_driver (nargs, args, ARITH_GRTR_OR_EQUAL);
=A0}
=A0=A0DEFUN ("/=3D", Fneq, Sneq, 2, 2, 0,
=A0=A0=A0=A0=A0=A0=A0 = doc: /* Return t if first arg is not equal to second arg.=A0 Both must be n= umbers or markers.=A0 */)
=A0=A0 (register Lisp_Object num1, Lisp_Object num2)
=A0{
-=A0 return= arithcompare (num1, num2, notequal);
+=A0 return arithcompare (num1, nu= m2, ARITH_NOTEQUAL);
=A0}
=A0
=A0DEFUN ("zerop", Fzerop,= Szerop, 1, 1, 0,
diff --git a/src/fileio.c b/src/fileio.c
index 0e6113f..1a2bdfa 100644--- a/src/fileio.c
+++ b/src/fileio.c
@@ -5121,7 +5121,8 @@ DEFUN (= "car-less-than-car", Fcar_less_than_car, Scar_less_than_car, 2, 2= , 0,
=A0=A0=A0=A0=A0=A0=A0 doc: /* Return t if (car A) is numerically less than = (car B).=A0 */)
=A0=A0 (Lisp_Object a, Lisp_Object b)
=A0{
-=A0 re= turn Flss (Fcar (a), Fcar (b));
+=A0 Lisp_Object args[2] =3D { Fcar (a),= Fcar (b), };
+=A0 return Flss (2, args);
=A0}
=A0
=A0/* Build the complete list of annotations appropriate for= writing out
diff --git a/src/lisp.h b/src/lisp.h
index 38b538d..2b1a= f1f 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -3160,6 +3160,16 @= @ EXFUN (Fbyteorder, 0) ATTRIBUTE_CONST;
=A0/* Defined in data.c.=A0 */
=A0extern Lisp_Object indirect_function (= Lisp_Object);
=A0extern Lisp_Object find_symbol_value (Lisp_Object);
= +enum Arith_Comparison {
+=A0 ARITH_EQUAL,
+=A0 ARITH_NOTEQUAL,
+= =A0 ARITH_LESS,
+=A0 ARITH_GRTR,
+=A0 ARITH_LESS_OR_EQUAL,
+=A0 ARITH_GRTR_OR_EQUAL+};
+extern Lisp_Object arithcompare (Lisp_Object num1, Lisp_Object nu= m2,
+=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 enum Arith_Comparison comparison);
=A0
=A0/* Convert the integer I to an Emacs representation, either the i= nteger
=A0=A0=A0 itself, or a cons of two or three integers, or if all e= lse fails a float.
diff --git a/test/automated/data-tests.el b/test/auto= mated/data-tests.el
index e69de29..2298fa3 100644
--- a/test/automated/data-tests.el
+++ = b/test/automated/data-tests.el
@@ -0,0 +1,75 @@
+;;; data-tests.el --= - tests for src/data.c
+
+;; Copyright (C) 2013 Free Software Foundat= ion, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; This program is free s= oftware: you can redistribute it and/or
+;; modify it under the terms of= the GNU General Public License as
+;; published by the Free Software Fo= undation, either version 3 of the
+;; License, or (at your option) any later version.
+;;
+;; This prog= ram is distributed in the hope that it will be useful, but
+;; WITHOUT A= NY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or= FITNESS FOR A PARTICULAR PURPOSE.=A0 See the GNU
+;; General Public License for more details.
+;;
+;; You should have = received a copy of the GNU General Public License
+;; along with this pr= ogram.=A0 If not, see `http://www.= gnu.org/licenses/'.
+
+;;; Commentary:
+
+;;; Code:
+
+(ert-deftest data-tests-= =3D ()
+=A0 (should-error (=3D))
+=A0 (should (=3D 1))
+=A0 (shoul= d (=3D 2 2))
+=A0 (should (=3D 9 9 9 9 9 9 9 9 9))
+=A0 (should-not (= apply #'=3D '(3 8 3)))
+=A0 (should-error (=3D 9 9 'foo))
+=A0 ;; Short circuits before get= ting to bad arg
+=A0 (should-not (=3D 9 8 'foo)))
+
+(ert-deft= est data-tests-< ()
+=A0 (should-error (<))
+=A0 (should (< = 1))
+=A0 (should (< 2 3))
+=A0 (should (< -6 -1 0 2 3 4 8 9 999))
+=A0 (should-not (apply #'= ;< '(3 8 3)))
+=A0 (should-error (< 9 10 'foo))
+=A0 ;;= Short circuits before getting to bad arg
+=A0 (should-not (< 9 8 = 9;foo)))
+
+(ert-deftest data-tests-> ()
+=A0 (should-error (>))
+=A0= (should (> 1))
+=A0 (should (> 3 2))
+=A0 (should (> 6 1 0 = -2 -3 -4 -8 -9 -999))
+=A0 (should-not (apply #'> '(3 8 3)))<= br>+=A0 (should-error (> 9 8 'foo))
+=A0 ;; Short circuits before getting to bad arg
+=A0 (should-not (> = 8 9 'foo)))
+
+(ert-deftest data-tests-<=3D ()
+=A0 (should= -error (<=3D))
+=A0 (should (<=3D 1))
+=A0 (should (<=3D 2 3= ))
+=A0 (should (<=3D -6 -1 -1 0 0 0 2 3 4 8 999))
+=A0 (should-not (apply #'<=3D '(3 8 3 3)))
+=A0 (should-erro= r (<=3D 9 10 'foo))
+=A0 ;; Short circuits before getting to bad = arg
+=A0 (should-not (<=3D 9 8 'foo)))
+
+(ert-deftest data= -tests->=3D ()
+=A0 (should-error (>=3D))
+=A0 (should (>=3D 1))
+=A0 (should = (>=3D 3 2))
+=A0 (should (>=3D 666 1 0 0 -2 -3 -3 -3 -4 -8 -8 -9 -= 999))
+=A0 (should-not (apply #'>=3D '(3 8 3)))
+=A0 (shou= ld-error (>=3D 9 8 'foo))
+=A0 ;; Short circuits before getting to bad arg
+=A0 (should-not (>= =3D 8 9 'foo)))
+
+;;; data-tests.el ends here
+

--f46d0443044e9b3a5e04e60ff679--