Commit 51f3ef9d authored by Antoine Pitrou's avatar Antoine Pitrou

Issue #3106: Speedup some comparisons. This also removes the last call

to Py_CmpToRich from the codebase (in longobject.c).
parent c9928ccf
...@@ -12,6 +12,8 @@ What's New in Python 3.1 alpha 0 ...@@ -12,6 +12,8 @@ What's New in Python 3.1 alpha 0
Core and Builtins Core and Builtins
----------------- -----------------
- Issue #3106: Speedup some comparisons (str/str and int/int).
- Issue #2183: Simplify and optimize bytecode for list, dict and set - Issue #2183: Simplify and optimize bytecode for list, dict and set
comprehensions. Original patch for list comprehensions by Neal Norwitz. comprehensions. Original patch for list comprehensions by Neal Norwitz.
......
...@@ -2232,14 +2232,45 @@ long_compare(PyLongObject *a, PyLongObject *b) ...@@ -2232,14 +2232,45 @@ long_compare(PyLongObject *a, PyLongObject *b)
return sign < 0 ? -1 : sign > 0 ? 1 : 0; return sign < 0 ? -1 : sign > 0 ? 1 : 0;
} }
#define TEST_COND(cond) \
((cond) ? Py_True : Py_False)
static PyObject * static PyObject *
long_richcompare(PyObject *self, PyObject *other, int op) long_richcompare(PyObject *self, PyObject *other, int op)
{ {
PyObject *result; int result;
PyObject *v;
CHECK_BINOP(self, other); CHECK_BINOP(self, other);
result = Py_CmpToRich(op, long_compare((PyLongObject*)self, if (self == other)
(PyLongObject*)other)); result = 0;
return result; else
result = long_compare((PyLongObject*)self, (PyLongObject*)other);
/* Convert the return value to a Boolean */
switch (op) {
case Py_EQ:
v = TEST_COND(result == 0);
break;
case Py_NE:
v = TEST_COND(result != 0);
break;
case Py_LE:
v = TEST_COND(result <= 0);
break;
case Py_GE:
v = TEST_COND(result >= 0);
break;
case Py_LT:
v = TEST_COND(result == -1);
break;
case Py_GT:
v = TEST_COND(result == 1);
break;
default:
PyErr_BadArgument();
return NULL;
}
Py_INCREF(v);
return v;
} }
static long static long
......
...@@ -6508,81 +6508,65 @@ PyUnicode_CompareWithASCIIString(PyObject* uni, const char* str) ...@@ -6508,81 +6508,65 @@ PyUnicode_CompareWithASCIIString(PyObject* uni, const char* str)
return 0; return 0;
} }
#define TEST_COND(cond) \
((cond) ? Py_True : Py_False)
PyObject *PyUnicode_RichCompare(PyObject *left, PyObject *PyUnicode_RichCompare(PyObject *left,
PyObject *right, PyObject *right,
int op) int op)
{ {
int result; int result;
result = PyUnicode_Compare(left, right); if (PyUnicode_Check(left) && PyUnicode_Check(right)) {
if (result == -1 && PyErr_Occurred()) PyObject *v;
goto onError; if (((PyUnicodeObject *) left)->length !=
((PyUnicodeObject *) right)->length) {
/* Convert the return value to a Boolean */ if (op == Py_EQ) {
switch (op) { Py_INCREF(Py_False);
case Py_EQ: return Py_False;
result = (result == 0); }
break; if (op == Py_NE) {
case Py_NE: Py_INCREF(Py_True);
result = (result != 0); return Py_True;
break; }
case Py_LE: }
result = (result <= 0); if (left == right)
break; result = 0;
case Py_GE: else
result = (result >= 0); result = unicode_compare((PyUnicodeObject *)left,
break; (PyUnicodeObject *)right);
case Py_LT:
result = (result == -1); /* Convert the return value to a Boolean */
break; switch (op) {
case Py_GT: case Py_EQ:
result = (result == 1); v = TEST_COND(result == 0);
break; break;
} case Py_NE:
return PyBool_FromLong(result); v = TEST_COND(result != 0);
break;
onError: case Py_LE:
v = TEST_COND(result <= 0);
/* Standard case break;
case Py_GE:
Type errors mean that PyUnicode_FromObject() could not convert v = TEST_COND(result >= 0);
one of the arguments (usually the right hand side) to Unicode, break;
ie. we can't handle the comparison request. However, it is case Py_LT:
possible that the other object knows a comparison method, which v = TEST_COND(result == -1);
is why we return Py_NotImplemented to give the other object a break;
chance. case Py_GT:
v = TEST_COND(result == 1);
*/ break;
if (PyErr_ExceptionMatches(PyExc_TypeError)) { default:
PyErr_Clear(); PyErr_BadArgument();
Py_INCREF(Py_NotImplemented); return NULL;
return Py_NotImplemented; }
Py_INCREF(v);
return v;
} }
if (op != Py_EQ && op != Py_NE)
return NULL; Py_INCREF(Py_NotImplemented);
return Py_NotImplemented;
/* Equality comparison.
This is a special case: we silence any PyExc_UnicodeDecodeError
and instead turn it into a PyErr_UnicodeWarning.
*/
if (!PyErr_ExceptionMatches(PyExc_UnicodeDecodeError))
return NULL;
PyErr_Clear();
if (PyErr_WarnEx(PyExc_UnicodeWarning,
(op == Py_EQ) ?
"equal comparison "
"failed to convert both arguments to str - "
"interpreting them as being unequal"
:
"Unicode unequal comparison "
"failed to convert both arguments to str - "
"interpreting them as being unequal",
1) < 0)
return NULL;
result = (op == Py_NE);
return PyBool_FromLong(result);
} }
int PyUnicode_Contains(PyObject *container, int PyUnicode_Contains(PyObject *container,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment