Use rich comparisons to fulfill an old wish: complex numbers now raise

exceptions when compared using <, <=, > or >=.

NOTE: This is a tentative change: this means that cmp() involving
complex numbers will raise an exception when the numbers differ, and
that in turn means that e.g. dictionaries and certain other compounds
(e.g. UserLists) containing complex numbers can't be compared either.
So we'll have to decide whether this is acceptable.  The alpha test
cycle is a good time to keep an eye on this!
This commit is contained in:
Guido van Rossum 2001-01-18 01:12:39 +00:00
parent 9d19cb8a70
commit be4cbb1668
1 changed files with 84 additions and 49 deletions

View File

@ -210,22 +210,6 @@ complex_repr(PyComplexObject *v)
return PyString_FromString(buf); return PyString_FromString(buf);
} }
static int
complex_compare(PyComplexObject *v, PyComplexObject *w)
{
/* Note: "greater" and "smaller" have no meaning for complex numbers,
but Python requires that they be defined nevertheless. */
Py_complex i, j;
i = v->cval;
j = w->cval;
if (i.real == j.real && i.imag == j.imag)
return 0;
else if (i.real != j.real)
return (i.real < j.real) ? -1 : 1;
else
return (i.imag < j.imag) ? -1 : 1;
}
static long static long
complex_hash(PyComplexObject *v) complex_hash(PyComplexObject *v)
{ {
@ -420,6 +404,47 @@ complex_coerce(PyObject **pv, PyObject **pw)
return 1; /* Can't do it */ return 1; /* Can't do it */
} }
static PyObject *
complex_richcompare(PyObject *v, PyObject *w, int op)
{
int c;
Py_complex i, j;
PyObject *res;
if (op != Py_EQ && op != Py_NE) {
PyErr_SetString(PyExc_TypeError,
"cannot compare complex numbers using <, <=, >, >=");
return NULL;
}
c = PyNumber_CoerceEx(&v, &w);
if (c < 0)
return NULL;
if (c > 0) {
Py_INCREF(Py_NotImplemented);
return Py_NotImplemented;
}
if (!PyComplex_Check(v) || !PyComplex_Check(w)) {
Py_DECREF(v);
Py_DECREF(w);
Py_INCREF(Py_NotImplemented);
return Py_NotImplemented;
}
i = ((PyComplexObject *)v)->cval;
j = ((PyComplexObject *)w)->cval;
Py_DECREF(v);
Py_DECREF(w);
if ((i.real == j.real && i.imag == j.imag) == (op == Py_EQ))
res = Py_True;
else
res = Py_False;
Py_INCREF(res);
return res;
}
static PyObject * static PyObject *
complex_int(PyObject *v) complex_int(PyObject *v)
{ {
@ -474,29 +499,29 @@ complex_getattr(PyComplexObject *self, char *name)
} }
static PyNumberMethods complex_as_number = { static PyNumberMethods complex_as_number = {
(binaryfunc)complex_add, /*nb_add*/ (binaryfunc)complex_add, /* nb_add */
(binaryfunc)complex_sub, /*nb_subtract*/ (binaryfunc)complex_sub, /* nb_subtract */
(binaryfunc)complex_mul, /*nb_multiply*/ (binaryfunc)complex_mul, /* nb_multiply */
(binaryfunc)complex_div, /*nb_divide*/ (binaryfunc)complex_div, /* nb_divide */
(binaryfunc)complex_remainder, /*nb_remainder*/ (binaryfunc)complex_remainder, /* nb_remainder */
(binaryfunc)complex_divmod, /*nb_divmod*/ (binaryfunc)complex_divmod, /* nb_divmod */
(ternaryfunc)complex_pow, /*nb_power*/ (ternaryfunc)complex_pow, /* nb_power */
(unaryfunc)complex_neg, /*nb_negative*/ (unaryfunc)complex_neg, /* nb_negative */
(unaryfunc)complex_pos, /*nb_positive*/ (unaryfunc)complex_pos, /* nb_positive */
(unaryfunc)complex_abs, /*nb_absolute*/ (unaryfunc)complex_abs, /* nb_absolute */
(inquiry)complex_nonzero, /*nb_nonzero*/ (inquiry)complex_nonzero, /* nb_nonzero */
0, /*nb_invert*/ 0, /* nb_invert */
0, /*nb_lshift*/ 0, /* nb_lshift */
0, /*nb_rshift*/ 0, /* nb_rshift */
0, /*nb_and*/ 0, /* nb_and */
0, /*nb_xor*/ 0, /* nb_xor */
0, /*nb_or*/ 0, /* nb_or */
(coercion)complex_coerce, /*nb_coerce*/ (coercion)complex_coerce, /* nb_coerce */
(unaryfunc)complex_int, /*nb_int*/ (unaryfunc)complex_int, /* nb_int */
(unaryfunc)complex_long, /*nb_long*/ (unaryfunc)complex_long, /* nb_long */
(unaryfunc)complex_float, /*nb_float*/ (unaryfunc)complex_float, /* nb_float */
0, /*nb_oct*/ 0, /* nb_oct */
0, /*nb_hex*/ 0, /* nb_hex */
}; };
PyTypeObject PyComplex_Type = { PyTypeObject PyComplex_Type = {
@ -505,16 +530,26 @@ PyTypeObject PyComplex_Type = {
"complex", "complex",
sizeof(PyComplexObject), sizeof(PyComplexObject),
0, 0,
(destructor)complex_dealloc, /*tp_dealloc*/ (destructor)complex_dealloc, /* tp_dealloc */
(printfunc)complex_print, /*tp_print*/ (printfunc)complex_print, /* tp_print */
(getattrfunc)complex_getattr, /*tp_getattr*/ (getattrfunc)complex_getattr, /* tp_getattr */
0, /*tp_setattr*/ 0, /* tp_setattr */
(cmpfunc)complex_compare, /*tp_compare*/ 0, /* tp_compare */
(reprfunc)complex_repr, /*tp_repr*/ (reprfunc)complex_repr, /* tp_repr */
&complex_as_number, /*tp_as_number*/ &complex_as_number, /* tp_as_number */
0, /*tp_as_sequence*/ 0, /* tp_as_sequence */
0, /*tp_as_mapping*/ 0, /* tp_as_mapping */
(hashfunc)complex_hash, /*tp_hash*/ (hashfunc)complex_hash, /* tp_hash */
0, /* tp_call */
0, /* tp_str */
0, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT, /* tp_flags */
0, /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
complex_richcompare, /* tp_richcompare */
}; };
#endif #endif