@@ -198,6 +198,11 @@ extern "C" Box* complexDiv(BoxedComplex* lhs, Box* rhs) {
198
198
}
199
199
}
200
200
201
+ Box* complexPos (BoxedComplex* self) {
202
+ assert (self->cls == complex_cls);
203
+ return PyComplex_FromDoubles (self->real , self->imag );
204
+ }
205
+
201
206
// str and repr
202
207
// For now, just print the same way as ordinary doubles.
203
208
// TODO this is wrong, e.g. if real or imaginary part is an integer, there should
@@ -260,6 +265,60 @@ Box* complexNew(Box* _cls, Box* real, Box* imag) {
260
265
return new BoxedComplex (real_f, imag_f);
261
266
}
262
267
268
+ static PyObject* complex_richcompare (PyObject* v, PyObject* w, int op) noexcept {
269
+ PyObject* res;
270
+ int equal;
271
+
272
+ if (op != Py_EQ && op != Py_NE) {
273
+ /* for backwards compatibility, comparisons with non-numbers return
274
+ * NotImplemented. Only comparisons with core numeric types raise
275
+ * TypeError.
276
+ */
277
+ if (PyInt_Check (w) || PyLong_Check (w) || PyFloat_Check (w) || PyComplex_Check (w)) {
278
+ PyErr_SetString (PyExc_TypeError, " no ordering relation is defined "
279
+ " for complex numbers" );
280
+ return NULL ;
281
+ }
282
+ return Py_NotImplemented;
283
+ }
284
+
285
+ assert (PyComplex_Check (v));
286
+ BoxedComplex* lhs = static_cast <BoxedComplex*>(v);
287
+
288
+ if (PyInt_Check (w) || PyLong_Check (w)) {
289
+ /* Check for 0->g0 imaginary part first to avoid the rich
290
+ * comparison when possible->g
291
+ */
292
+ if (lhs->imag == 0.0 ) {
293
+ PyObject* j, *sub_res;
294
+ j = PyFloat_FromDouble (lhs->real );
295
+ if (j == NULL )
296
+ return NULL ;
297
+
298
+ sub_res = PyObject_RichCompare (j, w, op);
299
+ Py_DECREF (j);
300
+ return sub_res;
301
+ } else {
302
+ equal = 0 ;
303
+ }
304
+ } else if (PyFloat_Check (w)) {
305
+ equal = (lhs->real == PyFloat_AsDouble (w) && lhs->imag == 0.0 );
306
+ } else if (PyComplex_Check (w)) {
307
+ BoxedComplex* rhs = static_cast <BoxedComplex*>(w);
308
+ equal = (lhs->real == rhs->real && lhs->imag == rhs->imag );
309
+ } else {
310
+ return Py_NotImplemented;
311
+ }
312
+
313
+ if (equal == (op == Py_EQ))
314
+ res = Py_True;
315
+ else
316
+ res = Py_False;
317
+
318
+ Py_INCREF (res);
319
+ return res;
320
+ }
321
+
263
322
void setupComplex () {
264
323
complex_cls->giveAttr (" __new__" , new BoxedFunction (boxRTFunction ((void *)complexNew, UNKNOWN, 3 , 2 , false , false ),
265
324
{ boxInt (0 ), boxInt (0 ) }));
@@ -276,13 +335,15 @@ void setupComplex() {
276
335
_addFunc (" __div__" , BOXED_COMPLEX, (void *)complexDivComplex, (void *)complexDivFloat, (void *)complexDivInt,
277
336
(void *)complexDiv);
278
337
338
+ complex_cls->giveAttr (" __pos__" , new BoxedFunction (boxRTFunction ((void *)complexPos, BOXED_COMPLEX, 1 )));
279
339
complex_cls->giveAttr (" __str__" , new BoxedFunction (boxRTFunction ((void *)complexStr, STR, 1 )));
280
340
complex_cls->giveAttr (" __repr__" , new BoxedFunction (boxRTFunction ((void *)complexRepr, STR, 1 )));
281
341
complex_cls->giveAttr (" real" ,
282
342
new BoxedMemberDescriptor (BoxedMemberDescriptor::DOUBLE, offsetof (BoxedComplex, real)));
283
343
complex_cls->giveAttr (" imag" ,
284
344
new BoxedMemberDescriptor (BoxedMemberDescriptor::DOUBLE, offsetof (BoxedComplex, imag)));
285
345
complex_cls->freeze ();
346
+ complex_cls->tp_richcompare = complex_richcompare;
286
347
}
287
348
288
349
void teardownComplex () {
0 commit comments