Commit fd811164 authored by Boxiang Sun's avatar Boxiang Sun

add missing attributes to complex and also with some bug fixing

parent a8eb5671
......@@ -26,7 +26,7 @@ extern "C" PyObject* complex_pow(PyObject* v, PyObject* w, PyObject* z) noexcept
namespace pyston {
static inline void raiseDivZeroExc() {
raiseExcHelper(ZeroDivisionError, "complex divide by zero");
raiseExcHelper(ZeroDivisionError, "complex division by zero");
}
extern "C" Box* createPureImaginary(double i) {
......@@ -331,6 +331,51 @@ extern "C" Box* complexRDiv(BoxedComplex* _lhs, Box* _rhs) {
return complexDivComplex(lhs, _lhs);
}
Box* complexTruediv(BoxedComplex* lhs, Box* rhs) {
if (!PyComplex_Check(lhs))
raiseExcHelper(TypeError, "descriptor '__truediv__' requires a 'complex' object but received a '%s'",
getTypeName(lhs));
if (PyInt_Check(rhs)) {
return complexDivInt(lhs, static_cast<BoxedInt*>(rhs));
} else if (PyFloat_Check(rhs)) {
return complexDivFloat(lhs, static_cast<BoxedFloat*>(rhs));
} else if (PyComplex_Check(rhs)) {
return complexDivComplex(lhs, static_cast<BoxedComplex*>(rhs));
} else if (PyLong_Check(rhs)) {
double res = PyLong_AsDouble(rhs);
if (res == -1 && PyErr_Occurred())
throwCAPIException();
return complexDivFloat(lhs, (BoxedFloat*)boxFloat(res));
} else {
return NotImplemented;
}
}
Box* complexRTruediv(BoxedComplex* lhs, Box* _rhs) {
if (!PyComplex_Check(lhs))
raiseExcHelper(TypeError, "descriptor '__rtruediv__' requires a 'complex' object but received a '%s'",
getTypeName(lhs));
BoxedComplex* rhs = new BoxedComplex(0.0, 0.0);
if (PyInt_Check(_rhs)) {
rhs->real = (static_cast<BoxedInt*>(_rhs))->n;
} else if (PyFloat_Check(_rhs)) {
rhs->real = (static_cast<BoxedFloat*>(_rhs))->d;
} else if (PyComplex_Check(_rhs)) {
rhs = static_cast<BoxedComplex*>(_rhs);
} else if (PyLong_Check(_rhs)) {
double res = PyLong_AsDouble(_rhs);
if (res == -1 && PyErr_Occurred())
throwCAPIException();
rhs->real = res;
} else {
return NotImplemented;
}
return complexDivComplex(rhs, lhs);
}
Box* complexPos(BoxedComplex* self) {
if (!PyComplex_Check(self))
raiseExcHelper(TypeError, "descriptor '__pos__' requires a 'complex' object but received a '%s'",
......@@ -524,6 +569,30 @@ Box* complexStr(BoxedComplex* self) {
return r;
}
Box* complexInt(BoxedComplex* self) {
if (!PyComplex_Check(self))
raiseExcHelper(TypeError, "descriptor '__int__' requires a 'complex' object but received a '%s'",
getTypeName(self));
raiseExcHelper(TypeError, "can't convert complex to int");
}
Box* complexFloat(BoxedComplex* self) {
if (!PyComplex_Check(self))
raiseExcHelper(TypeError, "descriptor '__float__' requires a 'complex' object but received a '%s'",
getTypeName(self));
raiseExcHelper(TypeError, "can't convert complex to float");
}
Box* complexLong(BoxedComplex* self) {
if (!PyComplex_Check(self))
raiseExcHelper(TypeError, "descriptor '__long__' requires a 'complex' object but received a '%s'",
getTypeName(self));
raiseExcHelper(TypeError, "can't convert complex to long");
}
Box* complexRepr(BoxedComplex* self) {
if (!PyComplex_Check(self))
raiseExcHelper(TypeError, "descriptor '__repr__' requires a 'complex' object but received a '%s'",
......@@ -699,8 +768,11 @@ static Box* to_complex(Box* self) noexcept {
r = new BoxedComplex(static_cast<BoxedInt*>(self)->n, 0.0);
} else if (PyFloat_Check(self)) {
r = new BoxedComplex((static_cast<BoxedFloat*>(PyNumber_Float(self)))->d, 0.0);
} else if (self->cls == long_cls) {
r = new BoxedComplex(PyLong_AsDouble(self), 0.0);
} else if (PyLong_Check(self)) {
double real = PyLong_AsDouble(self);
if (real == -1 && PyErr_Occurred())
throwCAPIException();
r = new BoxedComplex(real, 0.0);
} else {
return NotImplemented;
}
......@@ -803,7 +875,6 @@ template <ExceptionStyle S> Box* _complexNew(Box* real, Box* imag) noexcept(S ==
return new BoxedComplex(real_f, imag_f);
}
template <ExceptionStyle S> Box* complexNew(BoxedClass* _cls, Box* _real, Box* _imag) noexcept(S == CAPI) {
if (!isSubclass(_cls->cls, type_cls)) {
if (S == CAPI) {
......@@ -854,29 +925,58 @@ template <ExceptionStyle S> Box* complexNew(BoxedClass* _cls, Box* _real, Box* _
return new (_cls) BoxedComplex(r->real, r->imag);
}
extern "C" Box* complexDivmod(BoxedComplex* lhs, BoxedComplex* rhs) {
if (!PyComplex_Check(lhs))
raiseExcHelper(TypeError, "descriptor '__divmod__' requires a 'complex' object but received a '%s'",
getTypeName(lhs));
Box* complexDivmodComplex(BoxedComplex* lhs, Box* _rhs) {
if (PyErr_Warn(PyExc_DeprecationWarning, "complex divmod(), // and % are deprecated") < 0)
return NULL;
Box* rhs = to_complex(_rhs);
if (rhs->real == 0.0 && rhs->imag == 0.0) {
if (rhs == NotImplemented)
return NotImplemented;
BoxedComplex* rhs_complex = static_cast<BoxedComplex*>(rhs);
if (rhs_complex->real == 0.0 && rhs_complex->imag == 0.0) {
raiseExcHelper(ZeroDivisionError, "complex divmod()");
}
BoxedComplex* div = (BoxedComplex*)complexDiv(lhs, rhs); /* The raw divisor value. */
BoxedComplex* div = (BoxedComplex*)complexDiv(lhs, rhs_complex); /* The raw divisor value. */
div->real = floor(div->real); /* Use the floor of the real part. */
div->imag = 0.0;
BoxedComplex* mod = (BoxedComplex*)complexSubComplex(lhs, (BoxedComplex*)complexMulComplex(rhs, div));
BoxedComplex* mod = (BoxedComplex*)complexSubComplex(lhs, (BoxedComplex*)complexMulComplex(rhs_complex, div));
Box* res = BoxedTuple::create({ div, mod });
return res;
}
extern "C" Box* complexMod(BoxedComplex* lhs, Box* _rhs) {
Box* complexDivmod(BoxedComplex* lhs, Box* rhs) {
if (!PyComplex_Check(lhs))
raiseExcHelper(TypeError, "descriptor '__mod__' requires a 'complex' object but received a '%s'",
raiseExcHelper(TypeError, "descriptor '__divmod__' requires a 'complex' object but received a '%s'",
getTypeName(lhs));
if (rhs == None)
return NotImplemented;
return complexDivmodComplex(lhs, rhs);
}
Box* complexRDivmod(BoxedComplex* lhs, Box* _rhs) {
if (!PyComplex_Check(lhs))
raiseExcHelper(TypeError, "descriptor '__rdivmod__' requires a 'complex' object but received a '%s'",
getTypeName(lhs));
if (_rhs == None)
return NotImplemented;
Box* rhs = to_complex(_rhs);
if (rhs == NotImplemented)
return NotImplemented;
BoxedComplex* rhs_complex = static_cast<BoxedComplex*>(rhs);
return complexDivmodComplex(rhs_complex, lhs);
}
Box* complexModComplex(BoxedComplex* lhs, Box* _rhs) {
if (PyErr_Warn(PyExc_DeprecationWarning, "complex divmod(), // and % are deprecated") < 0)
return NULL;
......@@ -898,18 +998,68 @@ extern "C" Box* complexMod(BoxedComplex* lhs, Box* _rhs) {
return mod;
}
Box* complexMod(BoxedComplex* lhs, Box* rhs) {
if (!PyComplex_Check(lhs))
raiseExcHelper(TypeError, "descriptor '__mod__' requires a 'complex' object but received a '%s'",
getTypeName(lhs));
if (rhs == None)
return NotImplemented;
return complexModComplex(lhs, rhs);
}
Box* complexRMod(BoxedComplex* lhs, Box* _rhs) {
if (!PyComplex_Check(lhs))
raiseExcHelper(TypeError, "descriptor '__rmod__' requires a 'complex' object but received a '%s'",
getTypeName(lhs));
if (_rhs == None)
return NotImplemented;
Box* rhs = to_complex(_rhs);
if (rhs == NotImplemented)
return NotImplemented;
BoxedComplex* rhs_complex = static_cast<BoxedComplex*>(rhs);
return complexModComplex(rhs_complex, lhs);
}
extern "C" Box* complexFloordiv(BoxedComplex* lhs, Box* _rhs) {
if (!PyComplex_Check(lhs))
raiseExcHelper(TypeError, "descriptor '__floordiv__' requires a 'complex' object but received a '%s'",
getTypeName(lhs));
Box* res = to_complex(_rhs);
if (res == NotImplemented) {
if (_rhs == None)
return NotImplemented;
Box* rhs = to_complex(_rhs);
if (rhs == NotImplemented) {
return NotImplemented;
}
BoxedComplex* rhs = (BoxedComplex*)res;
BoxedComplex* rhs_complex = (BoxedComplex*)rhs;
BoxedTuple* t = (BoxedTuple*)complexDivmod(lhs, rhs);
BoxedTuple* t = (BoxedTuple*)complexDivmod(lhs, rhs_complex);
return t->elts[0];
}
Box* complexRFloordiv(BoxedComplex* lhs, Box* _rhs) {
if (!PyComplex_Check(lhs))
raiseExcHelper(TypeError, "descriptor '__rfloordiv__' requires a 'complex' object but received a '%s'",
getTypeName(lhs));
if (_rhs == None)
return NotImplemented;
Box* rhs = to_complex(_rhs);
if (rhs == NotImplemented) {
return NotImplemented;
}
BoxedComplex* rhs_complex = (BoxedComplex*)rhs;
BoxedTuple* t = (BoxedTuple*)complexDivmod(rhs_complex, lhs);
return t->elts[0];
}
......@@ -1116,13 +1266,18 @@ void setupComplex() {
complex_cls->giveAttr("__rpow__", new BoxedFunction(FunctionMetadata::create((void*)complexRpow, UNKNOWN, 2)));
complex_cls->giveAttr("__mod__", new BoxedFunction(FunctionMetadata::create((void*)complexMod, UNKNOWN, 2)));
complex_cls->giveAttr("__divmod__",
new BoxedFunction(FunctionMetadata::create((void*)complexDivmod, BOXED_TUPLE, 2)));
complex_cls->giveAttr("__rmod__", new BoxedFunction(FunctionMetadata::create((void*)complexRMod, UNKNOWN, 2)));
complex_cls->giveAttr("__divmod__", new BoxedFunction(FunctionMetadata::create((void*)complexDivmod, UNKNOWN, 2)));
complex_cls->giveAttr("__rdivmod__",
new BoxedFunction(FunctionMetadata::create((void*)complexRDivmod, UNKNOWN, 2)));
complex_cls->giveAttr("__floordiv__",
new BoxedFunction(FunctionMetadata::create((void*)complexFloordiv, UNKNOWN, 2)));
complex_cls->giveAttr("__rfloordiv__",
new BoxedFunction(FunctionMetadata::create((void*)complexRFloordiv, UNKNOWN, 2)));
complex_cls->giveAttr("__truediv__",
new BoxedFunction(FunctionMetadata::create((void*)complexDivComplex, BOXED_COMPLEX, 2)));
new BoxedFunction(FunctionMetadata::create((void*)complexTruediv, UNKNOWN, 2)));
complex_cls->giveAttr("__rtruediv__",
new BoxedFunction(FunctionMetadata::create((void*)complexRTruediv, UNKNOWN, 2)));
complex_cls->giveAttr("conjugate",
new BoxedFunction(FunctionMetadata::create((void*)complexConjugate, BOXED_COMPLEX, 1)));
complex_cls->giveAttr("__coerce__", new BoxedFunction(FunctionMetadata::create((void*)complexCoerce, UNKNOWN, 2)));
......@@ -1141,11 +1296,20 @@ void setupComplex() {
complex_cls->giveAttr("__pos__", new BoxedFunction(FunctionMetadata::create((void*)complexPos, BOXED_COMPLEX, 1)));
complex_cls->giveAttr("__hash__", new BoxedFunction(FunctionMetadata::create((void*)complexHash, BOXED_INT, 1)));
complex_cls->giveAttr("__str__", new BoxedFunction(FunctionMetadata::create((void*)complexStr, STR, 1)));
complex_cls->giveAttr("__int__", new BoxedFunction(FunctionMetadata::create((void*)complexInt, UNKNOWN, 1)));
complex_cls->giveAttr("__float__", new BoxedFunction(FunctionMetadata::create((void*)complexFloat, UNKNOWN, 1)));
complex_cls->giveAttr("__long__", new BoxedFunction(FunctionMetadata::create((void*)complexLong, UNKNOWN, 1)));
complex_cls->giveAttr("__repr__", new BoxedFunction(FunctionMetadata::create((void*)complexRepr, STR, 1)));
complex_cls->giveAttr("real",
new BoxedMemberDescriptor(BoxedMemberDescriptor::DOUBLE, offsetof(BoxedComplex, real)));
complex_cls->giveAttr("imag",
new BoxedMemberDescriptor(BoxedMemberDescriptor::DOUBLE, offsetof(BoxedComplex, imag)));
complex_cls->giveAttr("__doc__",
boxString("complex(real[, imag]) -> complex number\n"
"\n"
"Create a complex number from a real part and an optional imaginary part.\n"
"This is equivalent to (real + imag*1j) where imag defaults to 0."));
for (auto& md : complex_methods) {
complex_cls->giveAttr(md.ml_name, new BoxedMethodDescriptor(&md, complex_cls));
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment