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

to Py_CmpToRich from the codebase (in longobject.c).
This commit is contained in:
Antoine Pitrou 2008-12-20 13:14:23 +00:00
parent c9928ccf01
commit 51f3ef9da0
3 changed files with 90 additions and 73 deletions

View File

@ -12,6 +12,8 @@ What's New in Python 3.1 alpha 0
Core and Builtins
-----------------
- Issue #3106: Speedup some comparisons (str/str and int/int).
- Issue #2183: Simplify and optimize bytecode for list, dict and set
comprehensions. Original patch for list comprehensions by Neal Norwitz.

View File

@ -2232,14 +2232,45 @@ long_compare(PyLongObject *a, PyLongObject *b)
return sign < 0 ? -1 : sign > 0 ? 1 : 0;
}
#define TEST_COND(cond) \
((cond) ? Py_True : Py_False)
static PyObject *
long_richcompare(PyObject *self, PyObject *other, int op)
{
PyObject *result;
int result;
PyObject *v;
CHECK_BINOP(self, other);
result = Py_CmpToRich(op, long_compare((PyLongObject*)self,
(PyLongObject*)other));
return result;
if (self == other)
result = 0;
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

View File

@ -6508,81 +6508,65 @@ PyUnicode_CompareWithASCIIString(PyObject* uni, const char* str)
return 0;
}
#define TEST_COND(cond) \
((cond) ? Py_True : Py_False)
PyObject *PyUnicode_RichCompare(PyObject *left,
PyObject *right,
int op)
{
int result;
result = PyUnicode_Compare(left, right);
if (result == -1 && PyErr_Occurred())
goto onError;
/* Convert the return value to a Boolean */
switch (op) {
case Py_EQ:
result = (result == 0);
break;
case Py_NE:
result = (result != 0);
break;
case Py_LE:
result = (result <= 0);
break;
case Py_GE:
result = (result >= 0);
break;
case Py_LT:
result = (result == -1);
break;
case Py_GT:
result = (result == 1);
break;
if (PyUnicode_Check(left) && PyUnicode_Check(right)) {
PyObject *v;
if (((PyUnicodeObject *) left)->length !=
((PyUnicodeObject *) right)->length) {
if (op == Py_EQ) {
Py_INCREF(Py_False);
return Py_False;
}
if (op == Py_NE) {
Py_INCREF(Py_True);
return Py_True;
}
}
if (left == right)
result = 0;
else
result = unicode_compare((PyUnicodeObject *)left,
(PyUnicodeObject *)right);
/* 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;
}
return PyBool_FromLong(result);
onError:
/* Standard case
Type errors mean that PyUnicode_FromObject() could not convert
one of the arguments (usually the right hand side) to Unicode,
ie. we can't handle the comparison request. However, it is
possible that the other object knows a comparison method, which
is why we return Py_NotImplemented to give the other object a
chance.
*/
if (PyErr_ExceptionMatches(PyExc_TypeError)) {
PyErr_Clear();
Py_INCREF(Py_NotImplemented);
return Py_NotImplemented;
}
if (op != Py_EQ && op != Py_NE)
return NULL;
/* 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);
Py_INCREF(Py_NotImplemented);
return Py_NotImplemented;
}
int PyUnicode_Contains(PyObject *container,