summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAntoine Pitrou <solipsis@pitrou.net>2008-12-20 13:14:23 (GMT)
committerAntoine Pitrou <solipsis@pitrou.net>2008-12-20 13:14:23 (GMT)
commit51f3ef9da082435f063d2e78de1dd20fa65cf0de (patch)
tree254a2f82d7c66ac4ee73de9cd31374af99b11c62
parentc9928ccf0184fb3db4b05d7eab8cd366882d513f (diff)
downloadcpython-51f3ef9da082435f063d2e78de1dd20fa65cf0de.zip
cpython-51f3ef9da082435f063d2e78de1dd20fa65cf0de.tar.gz
cpython-51f3ef9da082435f063d2e78de1dd20fa65cf0de.tar.bz2
Issue #3106: Speedup some comparisons. This also removes the last call
to Py_CmpToRich from the codebase (in longobject.c).
-rw-r--r--Misc/NEWS2
-rw-r--r--Objects/longobject.c39
-rw-r--r--Objects/unicodeobject.c122
3 files changed, 90 insertions, 73 deletions
diff --git a/Misc/NEWS b/Misc/NEWS
index 9274a83..98dae61 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -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.
diff --git a/Objects/longobject.c b/Objects/longobject.c
index 677221a..362d0ad 100644
--- a/Objects/longobject.c
+++ b/Objects/longobject.c
@@ -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
diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c
index 6f64a07..38c3385 100644
--- a/Objects/unicodeobject.c
+++ b/Objects/unicodeobject.c
@@ -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;
- }
- 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 (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;
}
- 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,