diff -r 886912964fec Include/longobject.h --- a/Include/longobject.h Thu Jun 12 20:52:31 2008 +0200 +++ b/Include/longobject.h Fri Jun 13 20:33:47 2008 +0200 @@ -133,6 +133,13 @@ PyAPI_FUNC(PyObject *) _PyLong_FormatAdv Py_UNICODE *format_spec, Py_ssize_t format_spec_len); +PyAPI_FUNC(PyObject *) PyLong_RichCompare( + PyObject *left, /* Left long */ + PyObject *right, /* Right long */ + int op /* Operation: Py_EQ, Py_NE, Py_GT, etc. */ + ); + + /* These aren't really part of the long object, but they're handy. The functions are in Python/mystrtoul.c. */ diff -r 886912964fec Objects/longobject.c --- a/Objects/longobject.c Thu Jun 12 20:52:31 2008 +0200 +++ b/Objects/longobject.c Fri Jun 13 20:33:47 2008 +0200 @@ -2191,37 +2191,60 @@ static int static int long_compare(PyLongObject *a, PyLongObject *b) { - Py_ssize_t sign; - - if (Py_SIZE(a) != Py_SIZE(b)) { - if (ABS(Py_SIZE(a)) == 0 && ABS(Py_SIZE(b)) == 0) - sign = 0; - else - sign = Py_SIZE(a) - Py_SIZE(b); + Py_ssize_t sa = Py_SIZE(a), sb = Py_SIZE(b), i; + if (sa != sb) { + return sa > sb ? 1 : -1; } - else { - Py_ssize_t i = ABS(Py_SIZE(a)); - while (--i >= 0 && a->ob_digit[i] == b->ob_digit[i]) - ; - if (i < 0) - sign = 0; - else { - sign = (int)a->ob_digit[i] - (int)b->ob_digit[i]; - if (Py_SIZE(a) < 0) - sign = -sign; + i = ABS(sa); + while (--i >= 0) { + digit ad = a->ob_digit[i], bd = b->ob_digit[i]; + if (ad != bd) { + if (sa < 0) + return ad < bd ? 1 : -1; + else + return ad > bd ? 1 : -1; } } - return sign < 0 ? -1 : sign > 0 ? 1 : 0; + return 0; } -static PyObject * -long_richcompare(PyObject *self, PyObject *other, int op) +#define TEST_COND(cond) \ + ((cond) ? Py_True : Py_False) + +PyObject * +PyLong_RichCompare(PyObject *self, PyObject *other, int op) { - PyObject *result; + int cmp; + PyObject *v; CHECK_BINOP(self, other); - result = Py_CmpToRich(op, long_compare((PyLongObject*)self, - (PyLongObject*)other)); - return result; + cmp = long_compare((PyLongObject*)self, + (PyLongObject*)other); + /* Convert the return value to a Boolean */ + switch (op) { + case Py_EQ: + v = TEST_COND(cmp == 0); + break; + case Py_NE: + v = TEST_COND(cmp != 0); + break; + case Py_LE: + v = TEST_COND(cmp <= 0); + break; + case Py_GE: + v = TEST_COND(cmp >= 0); + break; + case Py_LT: + v = TEST_COND(cmp == -1); + break; + case Py_GT: + v = TEST_COND(cmp == 1); + break; + default: + PyErr_BadArgument(); + return NULL; + } + Py_INCREF(v); + return v; } static long @@ -3760,7 +3783,7 @@ PyTypeObject PyLong_Type = { long_doc, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ - long_richcompare, /* tp_richcompare */ + PyLong_RichCompare, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ diff -r 886912964fec Objects/unicodeobject.c --- a/Objects/unicodeobject.c Thu Jun 12 20:52:31 2008 +0200 +++ b/Objects/unicodeobject.c Fri Jun 13 20:33:47 2008 +0200 @@ -6487,81 +6487,62 @@ PyUnicode_CompareWithASCIIString(PyObjec 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 (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) ? - "Unicode equal comparison " - "failed to convert both arguments to Unicode - " - "interpreting them as being unequal" - : - "Unicode unequal comparison " - "failed to convert both arguments to Unicode - " - "interpreting them as being unequal", - 1) < 0) - return NULL; - result = (op == Py_NE); - return PyBool_FromLong(result); + 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; + } + } + 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; + } + + Py_INCREF(Py_NotImplemented); + return Py_NotImplemented; } int PyUnicode_Contains(PyObject *container, diff -r 886912964fec Python/ceval.c --- a/Python/ceval.c Thu Jun 12 20:52:31 2008 +0200 +++ b/Python/ceval.c Fri Jun 13 20:33:47 2008 +0200 @@ -3743,6 +3743,29 @@ cmp_outcome(int op, register PyObject *v } res = PyErr_GivenExceptionMatches(v, w); break; + case PyCmp_EQ: + case PyCmp_LE: + case PyCmp_GE: + res = 1; + case PyCmp_NE: + case PyCmp_LT: + case PyCmp_GT: + /* Optimization note: we must be careful, a few objects can be + unequal to themselves (e.g. float("nan")). To keep things + simple and fast, we only check for the two most common builtin + types */ + if (Py_TYPE(v) == Py_TYPE(w)) { + if (PyLong_CheckExact(v)) { + if (v == w) + break; + return PyLong_RichCompare(v, w, op); + } + if (PyUnicode_CheckExact(v)) { + if (v == w) + break; + return PyUnicode_RichCompare(v, w, op); + } + } default: return PyObject_RichCompare(v, w, op); }