Commit 1ac82dda authored by Boxiang Sun's avatar Boxiang Sun

apply experimental complex changes

parent 9dbcaa45
...@@ -324,6 +324,7 @@ STDMODULE_SRCS := \ ...@@ -324,6 +324,7 @@ STDMODULE_SRCS := \
STDOBJECT_SRCS := \ STDOBJECT_SRCS := \
structseq.c \ structseq.c \
capsule.c \ capsule.c \
complexobject.c \
stringobject.c \ stringobject.c \
exceptions.c \ exceptions.c \
floatobject.c \ floatobject.c \
......
...@@ -86,7 +86,6 @@ add_library(PYSTON_OBJECTS OBJECT ${OPTIONAL_SRCS} ...@@ -86,7 +86,6 @@ add_library(PYSTON_OBJECTS OBJECT ${OPTIONAL_SRCS}
runtime/capi.cpp runtime/capi.cpp
runtime/classobj.cpp runtime/classobj.cpp
runtime/code.cpp runtime/code.cpp
runtime/complex.cpp
runtime/ctxswitching.S runtime/ctxswitching.S
runtime/cxx_unwind.cpp runtime/cxx_unwind.cpp
runtime/descr.cpp runtime/descr.cpp
......
...@@ -36,7 +36,7 @@ ...@@ -36,7 +36,7 @@
#include "codegen/irgen/util.h" #include "codegen/irgen/util.h"
#include "core/threading.h" #include "core/threading.h"
#include "core/types.h" #include "core/types.h"
#include "runtime/complex.h" // #include "runtime/complex.h"
#include "runtime/float.h" #include "runtime/float.h"
#include "runtime/generator.h" #include "runtime/generator.h"
#include "runtime/import.h" #include "runtime/import.h"
......
...@@ -91,5 +91,6 @@ int Py_NoSiteFlag = 0; ...@@ -91,5 +91,6 @@ int Py_NoSiteFlag = 0;
int Py_OptimizeFlag = 0; int Py_OptimizeFlag = 0;
int Py_VerboseFlag = 0; int Py_VerboseFlag = 0;
int Py_UnicodeFlag = 0; int Py_UnicodeFlag = 0;
int Py_DivisionWarningFlag = 0;
} }
} }
...@@ -2083,6 +2083,7 @@ void setupBuiltins() { ...@@ -2083,6 +2083,7 @@ void setupBuiltins() {
builtins_module->giveAttr("set", set_cls); builtins_module->giveAttr("set", set_cls);
builtins_module->giveAttr("frozenset", frozenset_cls); builtins_module->giveAttr("frozenset", frozenset_cls);
builtins_module->giveAttr("tuple", tuple_cls); builtins_module->giveAttr("tuple", tuple_cls);
assert(complex_cls);
builtins_module->giveAttr("complex", complex_cls); builtins_module->giveAttr("complex", complex_cls);
builtins_module->giveAttr("super", super_cls); builtins_module->giveAttr("super", super_cls);
builtins_module->giveAttr("property", property_cls); builtins_module->giveAttr("property", property_cls);
......
// Copyright (c) 2014-2015 Dropbox, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "runtime/complex.h"
#include "capi/typeobject.h"
#include "core/types.h"
#include "runtime/float.h"
#include "runtime/inline/boxing.h"
#include "runtime/objmodel.h"
#include "runtime/types.h"
extern "C" PyObject* complex_pow(PyObject* v, PyObject* w, PyObject* z) noexcept;
namespace pyston {
static inline void raiseDivZeroExc() {
raiseExcHelper(ZeroDivisionError, "complex divide by zero");
}
extern "C" Box* createPureImaginary(double i) {
return new BoxedComplex(0.0, i);
}
static PyObject* try_complex_special_method(PyObject* op) noexcept {
PyObject* f;
static PyObject* complexstr;
if (complexstr == NULL) {
complexstr = PyString_InternFromString("__complex__");
if (complexstr == NULL)
return NULL;
}
if (PyInstance_Check(op)) {
f = PyObject_GetAttr(op, complexstr);
if (f == NULL) {
if (PyErr_ExceptionMatches(PyExc_AttributeError))
PyErr_Clear();
else
return NULL;
}
} else {
f = _PyObject_LookupSpecial(op, "__complex__", &complexstr);
if (f == NULL && PyErr_Occurred())
return NULL;
}
if (f != NULL) {
PyObject* res = PyObject_CallFunctionObjArgs(f, NULL);
Py_DECREF(f);
return res;
}
return NULL;
}
extern "C" Py_complex PyComplex_AsCComplex(PyObject* op) noexcept {
Py_complex cv;
PyObject* newop = NULL;
assert(op);
/* If op is already of type PyComplex_Type, return its value */
if (PyComplex_Check(op)) {
cv.real = ((BoxedComplex*)op)->real;
cv.imag = ((BoxedComplex*)op)->imag;
return cv;
}
/* If not, use op's __complex__ method, if it exists */
/* return -1 on failure */
cv.real = -1.;
cv.imag = 0.;
newop = try_complex_special_method(op);
if (newop) {
if (!PyComplex_Check(newop)) {
PyErr_SetString(PyExc_TypeError, "__complex__ should return a complex object");
Py_DECREF(newop);
return cv;
}
cv.real = ((BoxedComplex*)newop)->real;
cv.imag = ((BoxedComplex*)newop)->imag;
Py_DECREF(newop);
return cv;
} else if (PyErr_Occurred()) {
return cv;
}
/* If neither of the above works, interpret op as a float giving the
real part of the result, and fill in the imaginary part as 0. */
else {
/* PyFloat_AsDouble will return -1 on failure */
cv.real = PyFloat_AsDouble(op);
return cv;
}
}
extern "C" double PyComplex_RealAsDouble(PyObject* op) noexcept {
if (PyComplex_Check(op)) {
return static_cast<BoxedComplex*>(op)->real;
} else {
return PyFloat_AsDouble(op);
}
}
extern "C" double PyComplex_ImagAsDouble(PyObject* op) noexcept {
if (PyComplex_Check(op)) {
return static_cast<BoxedComplex*>(op)->imag;
} else {
return 0.0;
}
}
extern "C" PyObject* PyComplex_FromDoubles(double real, double imag) noexcept {
return new BoxedComplex(real, imag);
}
extern "C" PyObject* PyComplex_FromCComplex(Py_complex val) noexcept {
return new BoxedComplex(val.real, val.imag);
}
// addition
extern "C" Box* complexAddComplex(BoxedComplex* lhs, BoxedComplex* rhs) {
assert(lhs->cls == complex_cls);
assert(rhs->cls == complex_cls);
return boxComplex(lhs->real + rhs->real, lhs->imag + rhs->imag);
}
extern "C" Box* complexAddFloat(BoxedComplex* lhs, BoxedFloat* rhs) {
assert(lhs->cls == complex_cls);
assert(rhs->cls == float_cls);
return boxComplex(lhs->real + rhs->d, lhs->imag);
}
extern "C" Box* complexAddInt(BoxedComplex* lhs, BoxedInt* rhs) {
assert(lhs->cls == complex_cls);
assert(PyInt_Check(rhs));
return boxComplex(lhs->real + (double)rhs->n, lhs->imag);
}
extern "C" Box* complexAdd(BoxedComplex* lhs, Box* rhs) {
assert(lhs->cls == complex_cls);
if (PyInt_Check(rhs)) {
return complexAddInt(lhs, static_cast<BoxedInt*>(rhs));
} else if (rhs->cls == float_cls) {
return complexAddFloat(lhs, static_cast<BoxedFloat*>(rhs));
} else if (rhs->cls == complex_cls) {
return complexAddComplex(lhs, static_cast<BoxedComplex*>(rhs));
} else {
return NotImplemented;
}
}
// subtraction
extern "C" Box* complexSubComplex(BoxedComplex* lhs, BoxedComplex* rhs) {
assert(lhs->cls == complex_cls);
assert(rhs->cls == complex_cls);
return boxComplex(lhs->real - rhs->real, lhs->imag - rhs->imag);
}
extern "C" Box* complexSubFloat(BoxedComplex* lhs, BoxedFloat* rhs) {
assert(lhs->cls == complex_cls);
assert(rhs->cls == float_cls);
return boxComplex(lhs->real - rhs->d, lhs->imag);
}
extern "C" Box* complexSubInt(BoxedComplex* lhs, BoxedInt* rhs) {
assert(lhs->cls == complex_cls);
assert(PyInt_Check(rhs));
return boxComplex(lhs->real - (double)rhs->n, lhs->imag);
}
extern "C" Box* complexSub(BoxedComplex* lhs, Box* rhs) {
assert(lhs->cls == complex_cls);
if (PyInt_Check(rhs)) {
return complexSubInt(lhs, static_cast<BoxedInt*>(rhs));
} else if (rhs->cls == float_cls) {
return complexSubFloat(lhs, static_cast<BoxedFloat*>(rhs));
} else if (rhs->cls == complex_cls) {
return complexSubComplex(lhs, static_cast<BoxedComplex*>(rhs));
} else {
return NotImplemented;
}
}
extern "C" Box* complexRSub(BoxedComplex* _lhs, Box* _rhs) {
if (!PyComplex_Check(_lhs))
raiseExcHelper(TypeError, "descriptor '__rsub__' requires a 'complex' object but received a '%s'",
getTypeName(_lhs));
BoxedComplex* lhs = new BoxedComplex(0.0, 0.0);
if (PyInt_Check(_rhs)) {
lhs->real = (static_cast<BoxedInt*>(_rhs))->n;
} else if (_rhs->cls == float_cls) {
lhs->real = (static_cast<BoxedFloat*>(_rhs))->d;
} else if (_rhs->cls == complex_cls) {
lhs = static_cast<BoxedComplex*>(_rhs);
} else {
return NotImplemented;
}
return complexSubComplex(lhs, _lhs);
}
// multiplication
extern "C" Box* complexMulComplex(BoxedComplex* lhs, BoxedComplex* rhs) {
assert(lhs->cls == complex_cls);
assert(rhs->cls == complex_cls);
return boxComplex(lhs->real * rhs->real - lhs->imag * rhs->imag, lhs->real * rhs->imag + lhs->imag * rhs->real);
}
extern "C" Box* complexMulFloat(BoxedComplex* lhs, BoxedFloat* rhs) {
assert(lhs->cls == complex_cls);
assert(rhs->cls == float_cls);
return boxComplex(lhs->real * rhs->d, lhs->imag * rhs->d);
}
extern "C" Box* complexMulInt(BoxedComplex* lhs, BoxedInt* rhs) {
assert(lhs->cls == complex_cls);
assert(PyInt_Check(rhs));
return boxComplex(lhs->real * (double)rhs->n, lhs->imag * (double)rhs->n);
}
extern "C" Box* complexMul(BoxedComplex* lhs, Box* rhs) {
assert(lhs->cls == complex_cls);
if (PyInt_Check(rhs)) {
return complexMulInt(lhs, static_cast<BoxedInt*>(rhs));
} else if (rhs->cls == float_cls) {
return complexMulFloat(lhs, static_cast<BoxedFloat*>(rhs));
} else if (rhs->cls == complex_cls) {
return complexMulComplex(lhs, static_cast<BoxedComplex*>(rhs));
} else {
return NotImplemented;
}
}
// division
Box* complexDivComplex(BoxedComplex* lhs, BoxedComplex* rhs) {
if (!PyComplex_Check(lhs))
raiseExcHelper(TypeError, "descriptor '__div__' requires a 'complex' object but received a '%s'",
getTypeName(lhs));
assert(rhs->cls == complex_cls);
double real_f, imag_f;
const double abs_breal = rhs->real < 0 ? -rhs->real : rhs->real;
const double abs_bimag = rhs->imag < 0 ? -rhs->imag : rhs->imag;
if (abs_breal >= abs_bimag) {
/* divide tops and bottom by rhs.real */
if (abs_breal == 0.0) {
raiseDivZeroExc();
real_f = imag_f = 0.0;
} else {
const double ratio = rhs->imag / rhs->real;
const double denom = rhs->real + rhs->imag * ratio;
real_f = (lhs->real + lhs->imag * ratio) / denom;
imag_f = (lhs->imag - lhs->real * ratio) / denom;
}
} else {
/* divide tops and bottom by rhs->imag */
const double ratio = rhs->real / rhs->imag;
const double denom = rhs->real * ratio + rhs->imag;
real_f = (lhs->real * ratio + lhs->imag) / denom;
imag_f = (lhs->imag * ratio - lhs->real) / denom;
}
return boxComplex(real_f, imag_f);
}
extern "C" Box* complexDivFloat(BoxedComplex* lhs, BoxedFloat* rhs) {
if (!PyComplex_Check(lhs))
raiseExcHelper(TypeError, "descriptor '__div__' requires a 'complex' object but received a '%s'",
getTypeName(lhs));
assert(rhs->cls == float_cls);
if (rhs->d == 0.0) {
raiseDivZeroExc();
}
return boxComplex(lhs->real / rhs->d, lhs->imag / rhs->d);
}
extern "C" Box* complexDivInt(BoxedComplex* lhs, BoxedInt* rhs) {
if (!PyComplex_Check(lhs))
raiseExcHelper(TypeError, "descriptor '__div__' requires a 'complex' object but received a '%s'",
getTypeName(lhs));
assert(PyInt_Check(rhs));
if (rhs->n == 0) {
raiseDivZeroExc();
}
return boxComplex(lhs->real / (double)rhs->n, lhs->imag / (double)rhs->n);
}
extern "C" Box* complexDiv(BoxedComplex* lhs, Box* rhs) {
if (!PyComplex_Check(lhs))
raiseExcHelper(TypeError, "descriptor '__div__' requires a 'complex' object but received a '%s'",
getTypeName(lhs));
if (PyInt_Check(rhs)) {
return complexDivInt(lhs, static_cast<BoxedInt*>(rhs));
} else if (rhs->cls == float_cls) {
return complexDivFloat(lhs, static_cast<BoxedFloat*>(rhs));
} else if (rhs->cls == complex_cls) {
return complexDivComplex(lhs, static_cast<BoxedComplex*>(rhs));
} else {
return NotImplemented;
}
}
extern "C" Box* complexRDiv(BoxedComplex* _lhs, Box* _rhs) {
if (!PyComplex_Check(_lhs))
raiseExcHelper(TypeError, "descriptor '__rdiv__' requires a 'complex' object but received a '%s'",
getTypeName(_lhs));
BoxedComplex* lhs = new BoxedComplex(0.0, 0.0);
if (PyInt_Check(_rhs)) {
lhs->real = (static_cast<BoxedInt*>(_rhs))->n;
} else if (_rhs->cls == float_cls) {
lhs->real = (static_cast<BoxedFloat*>(_rhs))->d;
} else if (_rhs->cls == complex_cls) {
lhs = static_cast<BoxedComplex*>(_rhs);
} else {
return NotImplemented;
}
return complexDivComplex(lhs, _lhs);
}
Box* complexPos(BoxedComplex* self) {
if (!PyComplex_Check(self))
raiseExcHelper(TypeError, "descriptor '__pos__' requires a 'complex' object but received a '%s'",
getTypeName(self));
return PyComplex_FromDoubles(self->real, self->imag);
}
// str and repr
Box* complex_fmt(double r, double i, int precision, char format_code) noexcept {
PyObject* result = NULL;
/* If these are non-NULL, they'll need to be freed. */
char* pre = NULL;
char* im = NULL;
/* These do not need to be freed. re is either an alias
for pre or a pointer to a constant. lead and tail
are pointers to constants. */
std::string lead = "";
std::string tail = "";
std::string re = "";
std::string result_str;
if (r == 0. && copysign(1.0, r) == 1.0) {
re = "";
im = PyOS_double_to_string(i, format_code, precision, 0, NULL);
if (!im) {
PyErr_NoMemory();
goto done;
}
} else {
/* Format imaginary part with signr part without */
pre = PyOS_double_to_string(r, format_code, precision, 0, NULL);
if (!pre) {
PyErr_NoMemory();
goto done;
}
re = std::string(pre);
im = PyOS_double_to_string(i, format_code, precision, Py_DTSF_SIGN, NULL);
if (!im) {
PyErr_NoMemory();
goto done;
}
lead = "(";
tail = ")";
}
/* Alloc the final buffer. Add one for the "j" in the format string,
and one for the trailing zero. */
result_str = lead + std::string(re) + std::string(im) + "j" + tail;
result = PyString_FromString(result_str.c_str());
done:
PyMem_Free(im);
PyMem_Free(pre);
return result;
}
static void _addFunc(const char* name, ConcreteCompilerType* rtn_type, void* complex_func, void* float_func,
void* int_func, void* boxed_func) {
FunctionMetadata* md = new FunctionMetadata(2, false, false);
md->addVersion(complex_func, rtn_type, { BOXED_COMPLEX, BOXED_COMPLEX });
md->addVersion(float_func, rtn_type, { BOXED_COMPLEX, BOXED_FLOAT });
md->addVersion(int_func, rtn_type, { BOXED_COMPLEX, BOXED_INT });
md->addVersion(boxed_func, UNKNOWN, { BOXED_COMPLEX, UNKNOWN });
complex_cls->giveAttr(name, new BoxedFunction(md));
}
Box* complexPow(BoxedComplex* lhs, Box* _rhs, Box* mod) {
if (!PyComplex_Check(lhs))
raiseExcHelper(TypeError, "descriptor '__pow__' requires a 'complex' object but received a '%s'",
getTypeName(lhs));
PyObject* res = complex_pow(lhs, _rhs, mod);
if (res == NULL)
throwCAPIException();
return res;
}
Box* complexRpow(BoxedComplex* _lhs, Box* _rhs) {
if (!PyComplex_Check(_lhs))
raiseExcHelper(TypeError, "descriptor '__rpow__' requires a 'complex' object but received a '%s'",
getTypeName(_lhs));
BoxedComplex* lhs = new BoxedComplex(0.0, 0.0);
if (PyInt_Check(_rhs)) {
lhs->real = (static_cast<BoxedInt*>(_rhs))->n;
} else if (_rhs->cls == float_cls) {
lhs->real = (static_cast<BoxedFloat*>(_rhs))->d;
} else if (_rhs->cls == complex_cls) {
lhs = static_cast<BoxedComplex*>(_rhs);
} else {
return NotImplemented;
}
return complexPow(lhs, _lhs, None);
}
Box* complexHash(BoxedComplex* self) {
if (!PyComplex_Check(self))
raiseExcHelper(TypeError, "descriptor '__hash__' requires a 'complex' object but received a '%s'",
getTypeName(self));
long hashreal, hashimag, combined;
hashreal = _Py_HashDouble(self->real);
if (hashreal == -1) {
throwCAPIException();
}
hashimag = _Py_HashDouble(self->imag);
if (hashimag == -1) {
throwCAPIException();
}
/* Note: if the imaginary part is 0, hashimag is 0 now,
* so the following returns hashreal unchanged. This is
* important because numbers of different types that
* compare equal must have the same hash value, so that
* hash(x + 0*j) must equal hash(x).
*/
combined = hashreal + 1000003 * hashimag;
if (combined == -1)
combined = -2;
return boxInt(combined);
}
Box* complexCoerce(Box* lhs, Box* rhs) {
Py_complex cval;
cval.imag = 0.;
if (PyInt_Check(rhs)) {
cval.real = (double)PyInt_AsLong(rhs);
rhs = PyComplex_FromCComplex(cval);
} else if (PyLong_Check(rhs)) {
cval.real = PyLong_AsDouble(rhs);
if (cval.real == -1.0 && PyErr_Occurred()) {
throwCAPIException();
}
rhs = PyComplex_FromCComplex(cval);
} else if (PyFloat_Check(rhs)) {
cval.real = PyFloat_AsDouble(rhs);
rhs = PyComplex_FromCComplex(cval);
} else if (!PyComplex_Check(rhs)) {
return NotImplemented;
}
return BoxedTuple::create({ lhs, rhs });
}
Box* complexConjugate(BoxedComplex* self) {
if (!PyComplex_Check(self))
raiseExcHelper(TypeError, "descriptor 'conjuagte' requires a 'complex' object but received a '%s'",
getTypeName(self));
return new BoxedComplex(self->real, -self->imag);
}
Box* complexAbs(BoxedComplex* _self) {
if (!PyComplex_Check(_self))
raiseExcHelper(TypeError, "descriptor '__abs__' requires a 'complex' object but received a '%s'",
getTypeName(_self));
double result;
Py_complex self = PyComplex_AsCComplex(_self);
result = c_abs(self);
if (errno == ERANGE) {
raiseExcHelper(OverflowError, "absolute value too large");
}
return PyFloat_FromDouble(result);
}
Box* complexGetnewargs(BoxedComplex* self) {
if (!PyComplex_Check(self))
raiseExcHelper(TypeError, "descriptor '__getnewargs__' requires a 'complex' object but received a '%s'",
getTypeName(self));
return BoxedTuple::create({ boxFloat(self->real), boxFloat(self->imag) });
}
Box* complexNonzero(BoxedComplex* self) {
if (!PyComplex_Check(self))
raiseExcHelper(TypeError, "descriptor '__nonzero__' require a 'complex' object but received a '%s'",
getTypeName(self));
bool res = self->real != 0.0 || self->imag != 0.0;
return boxBool(res);
}
Box* complexStr(BoxedComplex* self) {
if (!PyComplex_Check(self))
raiseExcHelper(TypeError, "descriptor '__str__' requires a 'complex' object but received a '%s'",
getTypeName(self));
Box* r = complex_fmt(self->real, self->imag, 12, 'g');
if (!r) {
throwCAPIException();
}
return r;
}
Box* complexRepr(BoxedComplex* self) {
if (!PyComplex_Check(self))
raiseExcHelper(TypeError, "descriptor '__repr__' requires a 'complex' object but received a '%s'",
getTypeName(self));
Box* r = complex_fmt(self->real, self->imag, 16, 'g');
if (!r) {
throwCAPIException();
}
return r;
}
static PyObject* complex_subtype_from_string(PyObject* v) noexcept {
const char* s, *start;
char* end;
double x = 0.0, y = 0.0, z;
int got_bracket = 0;
#ifdef Py_USING_UNICODE
char* s_buffer = NULL;
#endif
Py_ssize_t len;
if (PyString_Check(v)) {
s = PyString_AS_STRING(v);
len = PyString_GET_SIZE(v);
}
#ifdef Py_USING_UNICODE
else if (PyUnicode_Check(v)) {
s_buffer = (char*)PyMem_MALLOC(PyUnicode_GET_SIZE(v) + 1);
if (s_buffer == NULL)
return PyErr_NoMemory();
if (PyUnicode_EncodeDecimal(PyUnicode_AS_UNICODE(v), PyUnicode_GET_SIZE(v), s_buffer, NULL))
goto error;
s = s_buffer;
len = strlen(s);
}
#endif
else if (PyObject_AsCharBuffer(v, &s, &len)) {
PyErr_SetString(PyExc_TypeError, "complex() arg is not a string");
return NULL;
}
/* position on first nonblank */
start = s;
while (Py_ISSPACE(*s))
s++;
if (*s == '(') {
/* Skip over possible bracket from repr(). */
got_bracket = 1;
s++;
while (Py_ISSPACE(*s))
s++;
}
/* a valid complex string usually takes one of the three forms:
<float> - real part only
<float>j - imaginary part only
<float><signed-float>j - real and imaginary parts
where <float> represents any numeric string that's accepted by the
float constructor (including 'nan', 'inf', 'infinity', etc.), and
<signed-float> is any string of the form <float> whose first
character is '+' or '-'.
For backwards compatibility, the extra forms
<float><sign>j
<sign>j
j
are also accepted, though support for these forms may be removed from
a future version of Python.
*/
/* first look for forms starting with <float> */
z = PyOS_string_to_double(s, &end, NULL);
if (z == -1.0 && PyErr_Occurred()) {
if (PyErr_ExceptionMatches(PyExc_ValueError))
PyErr_Clear();
else
goto error;
}
if (end != s) {
/* all 4 forms starting with <float> land here */
s = end;
if (*s == '+' || *s == '-') {
/* <float><signed-float>j | <float><sign>j */
x = z;
y = PyOS_string_to_double(s, &end, NULL);
if (y == -1.0 && PyErr_Occurred()) {
if (PyErr_ExceptionMatches(PyExc_ValueError))
PyErr_Clear();
else
goto error;
}
if (end != s)
/* <float><signed-float>j */
s = end;
else {
/* <float><sign>j */
y = *s == '+' ? 1.0 : -1.0;
s++;
}
if (!(*s == 'j' || *s == 'J'))
goto parse_error;
s++;
} else if (*s == 'j' || *s == 'J') {
/* <float>j */
s++;
y = z;
} else
/* <float> */
x = z;
} else {
/* not starting with <float>; must be <sign>j or j */
if (*s == '+' || *s == '-') {
/* <sign>j */
y = *s == '+' ? 1.0 : -1.0;
s++;
} else
/* j */
y = 1.0;
if (!(*s == 'j' || *s == 'J'))
goto parse_error;
s++;
}
/* trailing whitespace and closing bracket */
while (Py_ISSPACE(*s))
s++;
if (got_bracket) {
/* if there was an opening parenthesis, then the corresponding
closing parenthesis should be right here */
if (*s != ')')
goto parse_error;
s++;
while (Py_ISSPACE(*s))
s++;
}
/* we should now be at the end of the string */
if (s - start != len)
goto parse_error;
#ifdef Py_USING_UNICODE
if (s_buffer)
PyMem_FREE(s_buffer);
#endif
return new BoxedComplex(x, y);
parse_error:
PyErr_SetString(PyExc_ValueError, "complex() arg is a malformed string");
error:
#ifdef Py_USING_UNICODE
if (s_buffer)
PyMem_FREE(s_buffer);
#endif
return NULL;
}
static Box* to_complex(Box* self) noexcept {
BoxedComplex* r;
if (self == None || self == NULL) {
return new BoxedComplex(0.0, 0.0);
}
static BoxedString* complex_str = internStringImmortal("__complex__");
if (PyComplex_Check(self) && !PyObject_HasAttr((PyObject*)self, complex_str)) {
r = (BoxedComplex*)self;
} else if (PyInt_Check(self)) {
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 {
return NotImplemented;
}
return r;
}
template <ExceptionStyle S> static Box* try_special_method(Box* self) noexcept(S == CAPI) {
if (self == None || self == NULL) {
return None;
}
static BoxedString* float_str = internStringImmortal("__float__");
if (PyObject_HasAttr((PyObject*)self, float_str)) {
Box* r_f = callattrInternal<S, NOT_REWRITABLE>(self, float_str, CLASS_ONLY, NULL, ArgPassSpec(0), NULL, NULL,
NULL, NULL, NULL);
if (!PyFloat_Check(r_f)) {
if (S == CAPI) {
if (!PyErr_Occurred())
PyErr_Format(PyExc_TypeError, "__float__ returned non-float (type %.200s)", r_f->cls->tp_name);
return NULL;
} else {
raiseExcHelper(TypeError, "__float__ returned non-float (type %.200s)", r_f->cls->tp_name);
}
}
return (BoxedFloat*)r_f;
}
static BoxedString* complex_str = internStringImmortal("__complex__");
if (PyObject_HasAttr((PyObject*)self, complex_str)) {
Box* r = callattrInternal<S, NOT_REWRITABLE>(self, complex_str, CLASS_OR_INST, NULL, ArgPassSpec(0), NULL, NULL,
NULL, NULL, NULL);
if (!r) {
if (S == CAPI) {
if (!PyErr_Occurred())
PyErr_Format(TypeError, "complex() argument must be a string or a number, not '%s'\n",
getTypeName(self));
return NULL;
} else {
raiseExcHelper(TypeError, "complex() argument must be a string or a number, not '%s'\n",
getTypeName(self));
}
}
if (!PyComplex_Check(r)) {
if (S == CAPI) {
PyErr_Format(TypeError, "__complex__ returned non-complex (type %s)", r->cls->tp_name);
return NULL;
} else
raiseExcHelper(TypeError, "__complex__ returned non-complex (type %s)", r->cls->tp_name);
}
return static_cast<BoxedComplex*>(r);
}
return None;
}
template <ExceptionStyle S> Box* _complexNew(Box* real, Box* imag) noexcept(S == CAPI) {
// handle str and unicode
if (real != None && real != NULL) {
if (PyString_Check(real) || PyUnicode_Check(real)) {
if (imag != None && imag != NULL) {
raiseExcHelper(TypeError, "complex() can't take second arg if first is a string");
}
Box* res = complex_subtype_from_string(real);
if (res == NULL) {
throwCAPIException();
}
return res;
}
}
if (real != None && real != NULL && real->cls == complex_cls && (imag == NULL || imag == None)) {
return static_cast<BoxedComplex*>(real);
}
Box* _real = try_special_method<S>(real);
Box* _imag = try_special_method<S>(imag);
if (_real != None && _real != NULL) {
real = _real;
}
if (_imag != None && _imag != NULL) {
imag = _imag;
}
double real_f, imag_f;
bool real_is_complex = false, imag_is_complex = false;
if (real == None || real == NULL) {
real_f = 0.0;
} else if (PyComplex_Check(real)) {
real_f = ((BoxedComplex*)real)->real;
real_is_complex = true;
} else {
real_f = ((BoxedFloat*)PyNumber_Float(real))->d;
}
if (imag == None || imag == NULL) {
imag_f = 0.0;
} else if (PyComplex_Check(imag)) {
imag_f = ((BoxedComplex*)imag)->real;
imag_is_complex = true;
} else {
imag_f = ((BoxedFloat*)PyNumber_Float(imag))->d;
}
if (imag_is_complex) {
real_f -= ((BoxedComplex*)imag)->imag;
}
if (real_is_complex) {
imag_f += ((BoxedComplex*)real)->imag;
}
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) {
PyErr_Format(TypeError, "complex.__new__(X): X is not a type object (%s)", getTypeName(_cls));
return NULL;
} else
raiseExcHelper(TypeError, "complex.__new__(X): X is not a type object (%s)", getTypeName(_cls));
}
BoxedClass* cls = static_cast<BoxedClass*>(_cls);
if (PyComplex_Check(cls)) {
if (S == CAPI) {
PyErr_Format(TypeError, "complex.__new__(%s): %s is not a subtype of complex", getNameOfClass(cls),
getNameOfClass(cls));
return NULL;
} else
raiseExcHelper(TypeError, "complex.__new__(%s): %s is not a subtype of complex", getNameOfClass(cls),
getNameOfClass(cls));
}
// check second argument
if (_imag != NULL && (PyString_Check(_imag) || PyUnicode_Check(_imag))) {
if (S == CAPI) {
PyErr_Format(TypeError, "complex() second arg can't be a string");
return NULL;
} else
raiseExcHelper(TypeError, "complex() second arg can't be a string");
}
// we can't use None as default value, because complex(None) should raise TypeError,
// but complex() should return `0j`. So use NULL as default value.
// Here check we pass complex(None, None), complex(None)
// or complex(imag=None) to the constructor
if ((_real == None) && (_imag == None || _imag == NULL)) {
raiseExcHelper(TypeError, "complex() argument must be a string or number");
}
if (cls == complex_cls)
return _complexNew<S>(_real, _imag);
BoxedComplex* r = (BoxedComplex*)_complexNew<S>(_real, _imag);
if (!r) {
assert(S == CAPI);
return NULL;
}
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));
if (PyErr_Warn(PyExc_DeprecationWarning, "complex divmod(), // and % are deprecated") < 0)
return NULL;
if (rhs->real == 0.0 && rhs->imag == 0.0) {
raiseExcHelper(ZeroDivisionError, "complex divmod()");
}
BoxedComplex* div = (BoxedComplex*)complexDiv(lhs, rhs); /* 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));
Box* res = BoxedTuple::create({ div, mod });
return res;
}
extern "C" 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 (PyErr_Warn(PyExc_DeprecationWarning, "complex divmod(), // and % are deprecated") < 0)
return NULL;
Box* res = to_complex(_rhs);
if (res == NotImplemented) {
return NotImplemented;
}
BoxedComplex* rhs = (BoxedComplex*)res;
if (rhs->real == 0.0 && rhs->imag == 0.0) {
raiseExcHelper(ZeroDivisionError, "complex remainder");
}
BoxedComplex* div = (BoxedComplex*)complexDiv(lhs, rhs); /* 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));
return mod;
}
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) {
return NotImplemented;
}
BoxedComplex* rhs = (BoxedComplex*)res;
BoxedTuple* t = (BoxedTuple*)complexDivmod(lhs, rhs);
return t->elts[0];
}
static PyObject* complex_richcompare(PyObject* v, PyObject* w, int op) noexcept {
PyObject* res;
int equal;
if (op != Py_EQ && op != Py_NE) {
/* for backwards compatibility, comparisons with non-numbers return
* NotImplemented. Only comparisons with core numeric types raise
* TypeError.
*/
if (PyInt_Check(w) || PyLong_Check(w) || PyFloat_Check(w) || PyComplex_Check(w)) {
PyErr_SetString(PyExc_TypeError, "no ordering relation is defined "
"for complex numbers");
return NULL;
}
return Py_NotImplemented;
}
assert(PyComplex_Check(v));
BoxedComplex* lhs = static_cast<BoxedComplex*>(v);
if (PyInt_Check(w) || PyLong_Check(w)) {
/* Check for 0->g0 imaginary part first to avoid the rich
* comparison when possible->g
*/
if (lhs->imag == 0.0) {
PyObject* j, *sub_res;
j = PyFloat_FromDouble(lhs->real);
if (j == NULL)
return NULL;
sub_res = PyObject_RichCompare(j, w, op);
Py_DECREF(j);
return sub_res;
} else {
equal = 0;
}
} else if (PyFloat_Check(w)) {
equal = (lhs->real == PyFloat_AsDouble(w) && lhs->imag == 0.0);
} else if (PyComplex_Check(w)) {
BoxedComplex* rhs = static_cast<BoxedComplex*>(w);
equal = (lhs->real == rhs->real && lhs->imag == rhs->imag);
} else {
return Py_NotImplemented;
}
if (equal == (op == Py_EQ))
res = Py_True;
else
res = Py_False;
Py_INCREF(res);
return res;
}
extern "C" Box* complexEq(BoxedComplex* lhs, Box* rhs) {
if (lhs->cls != complex_cls) {
raiseExcHelper(TypeError, "descriptor '__eq__' requires a 'complex' object but recieved a '%s'",
getTypeName(lhs));
}
Box* res = complex_richcompare(lhs, rhs, Py_EQ);
if (!res) {
throwCAPIException();
}
return res;
}
extern "C" Box* complexNe(BoxedComplex* lhs, Box* rhs) {
if (lhs->cls != complex_cls) {
raiseExcHelper(TypeError, "descriptor '__ne__' requires a 'complex' object but recieved a '%s'",
getTypeName(lhs));
}
Box* res = complex_richcompare(lhs, rhs, Py_NE);
if (!res) {
throwCAPIException();
}
return res;
}
extern "C" Box* complexLe(BoxedComplex* lhs, Box* rhs) {
if (lhs->cls != complex_cls) {
raiseExcHelper(TypeError, "descriptor '__le__' requires a 'complex' object but recieved a '%s'",
getTypeName(lhs));
}
Box* res = complex_richcompare(lhs, rhs, Py_LE);
if (!res) {
throwCAPIException();
}
return res;
}
extern "C" Box* complexLt(BoxedComplex* lhs, Box* rhs) {
if (lhs->cls != complex_cls) {
raiseExcHelper(TypeError, "descriptor '__lt__' requires a 'complex' object but recieved a '%s'",
getTypeName(lhs));
}
Box* res = complex_richcompare(lhs, rhs, Py_LT);
if (!res) {
throwCAPIException();
}
return res;
}
extern "C" Box* complexGe(BoxedComplex* lhs, Box* rhs) {
if (lhs->cls != complex_cls) {
raiseExcHelper(TypeError, "descriptor '__ge__' requires a 'complex' object but recieved a '%s'",
getTypeName(lhs));
}
Box* res = complex_richcompare(lhs, rhs, Py_GE);
if (!res) {
throwCAPIException();
}
return res;
}
extern "C" Box* complexGt(BoxedComplex* lhs, Box* rhs) {
if (lhs->cls != complex_cls) {
raiseExcHelper(TypeError, "descriptor '__gt__' requires a 'complex' object but recieved a '%s'",
getTypeName(lhs));
}
Box* res = complex_richcompare(lhs, rhs, Py_GT);
if (!res) {
throwCAPIException();
}
return res;
}
Box* complexNeg(Box* _self) {
assert(_self->cls == complex_cls);
BoxedComplex* self = (BoxedComplex*)_self;
return PyComplex_FromDoubles(-self->real, -self->imag);
}
PyObject* complex_neg(PyComplexObject* v) {
BoxedComplex* self = (BoxedComplex*)v;
return PyComplex_FromDoubles(-self->real, -self->imag);
}
// Pyston change: make not static
PyObject* complex__format__(PyObject* self, PyObject* args) {
PyObject* format_spec;
if (!PyArg_ParseTuple(args, "O:__format__", &format_spec))
return NULL;
if (PyBytes_Check(format_spec))
return _PyComplex_FormatAdvanced(self, PyBytes_AS_STRING(format_spec), PyBytes_GET_SIZE(format_spec));
if (PyUnicode_Check(format_spec)) {
/* Convert format_spec to a str */
PyObject* result;
PyObject* str_spec = PyObject_Str(format_spec);
if (str_spec == NULL)
return NULL;
result = _PyComplex_FormatAdvanced(self, PyBytes_AS_STRING(str_spec), PyBytes_GET_SIZE(str_spec));
Py_DECREF(str_spec);
return result;
}
PyErr_SetString(PyExc_TypeError, "__format__ requires str or unicode");
return NULL;
}
static PyMethodDef complex_methods[] = {
{ "__format__", (PyCFunction)complex__format__, METH_VARARGS, NULL },
};
void setupComplex() {
static PyNumberMethods complex_as_number;
complex_cls->tp_as_number = &complex_as_number;
auto complex_new = FunctionMetadata::create((void*)complexNew<CXX>, UNKNOWN, 3, false, false,
ParamNames({ "", "real", "imag" }, "", ""), CXX);
complex_new->addVersion((void*)complexNew<CAPI>, UNKNOWN, CAPI);
complex_cls->giveAttr("__new__", new BoxedFunction(complex_new, { NULL, NULL }));
_addFunc("__add__", BOXED_COMPLEX, (void*)complexAddComplex, (void*)complexAddFloat, (void*)complexAddInt,
(void*)complexAdd);
_addFunc("__radd__", BOXED_COMPLEX, (void*)complexAddComplex, (void*)complexAddFloat, (void*)complexAddInt,
(void*)complexAdd);
_addFunc("__sub__", BOXED_COMPLEX, (void*)complexSubComplex, (void*)complexSubFloat, (void*)complexSubInt,
(void*)complexSub);
_addFunc("__mul__", BOXED_COMPLEX, (void*)complexMulComplex, (void*)complexMulFloat, (void*)complexMulInt,
(void*)complexMul);
_addFunc("__rmul__", BOXED_COMPLEX, (void*)complexMulComplex, (void*)complexMulFloat, (void*)complexMulInt,
(void*)complexMul);
_addFunc("__div__", BOXED_COMPLEX, (void*)complexDivComplex, (void*)complexDivFloat, (void*)complexDivInt,
(void*)complexDiv);
complex_cls->giveAttr("__rsub__", new BoxedFunction(FunctionMetadata::create((void*)complexRSub, UNKNOWN, 2)));
complex_cls->giveAttr("__rdiv__", new BoxedFunction(FunctionMetadata::create((void*)complexRDiv, UNKNOWN, 2)));
complex_cls->giveAttr(
"__pow__", new BoxedFunction(FunctionMetadata::create((void*)complexPow, UNKNOWN, 3, false, false), { None }));
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("__floordiv__",
new BoxedFunction(FunctionMetadata::create((void*)complexFloordiv, UNKNOWN, 2)));
complex_cls->giveAttr("__truediv__",
new BoxedFunction(FunctionMetadata::create((void*)complexDivComplex, BOXED_COMPLEX, 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)));
complex_cls->giveAttr("__abs__", new BoxedFunction(FunctionMetadata::create((void*)complexAbs, BOXED_FLOAT, 1)));
complex_cls->giveAttr("__getnewargs__",
new BoxedFunction(FunctionMetadata::create((void*)complexGetnewargs, BOXED_TUPLE, 1)));
complex_cls->giveAttr("__nonzero__",
new BoxedFunction(FunctionMetadata::create((void*)complexNonzero, BOXED_BOOL, 1)));
complex_cls->giveAttr("__eq__", new BoxedFunction(FunctionMetadata::create((void*)complexEq, UNKNOWN, 2)));
complex_cls->giveAttr("__ne__", new BoxedFunction(FunctionMetadata::create((void*)complexNe, UNKNOWN, 2)));
complex_cls->giveAttr("__le__", new BoxedFunction(FunctionMetadata::create((void*)complexLe, UNKNOWN, 2)));
complex_cls->giveAttr("__lt__", new BoxedFunction(FunctionMetadata::create((void*)complexLt, UNKNOWN, 2)));
complex_cls->giveAttr("__ge__", new BoxedFunction(FunctionMetadata::create((void*)complexGe, UNKNOWN, 2)));
complex_cls->giveAttr("__gt__", new BoxedFunction(FunctionMetadata::create((void*)complexGt, UNKNOWN, 2)));
complex_cls->giveAttr("__neg__", new BoxedFunction(FunctionMetadata::create((void*)complexNeg, BOXED_COMPLEX, 1)));
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("__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)));
for (auto& md : complex_methods) {
complex_cls->giveAttr(md.ml_name, new BoxedMethodDescriptor(&md, complex_cls));
}
add_operators(complex_cls);
complex_cls->freeze();
complex_cls->tp_as_number->nb_negative = (unaryfunc)complex_neg;
complex_cls->tp_richcompare = complex_richcompare;
}
void teardownComplex() {
}
}
// Copyright (c) 2014-2015 Dropbox, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef PYSTON_RUNTIME_COMPLEX_H
#define PYSTON_RUNTIME_COMPLEX_H
#include "core/types.h"
namespace pyston {
extern "C" Box* createPureImaginary(double i);
}
#endif
...@@ -26,10 +26,10 @@ extern "C" inline Box* boxFloat(double d) { ...@@ -26,10 +26,10 @@ extern "C" inline Box* boxFloat(double d) {
return new BoxedFloat(d); return new BoxedFloat(d);
} }
extern "C" inline Box* boxComplex(double r, double i) __attribute__((visibility("default"))); // extern "C" inline Box* boxComplex(double r, double i) __attribute__((visibility("default")));
extern "C" inline Box* boxComplex(double r, double i) { // extern "C" inline Box* boxComplex(double r, double i) {
return new BoxedComplex(r, i); // return new BoxedComplex(r, i);
} // }
extern "C" inline bool unboxBool(Box* b) __attribute__((visibility("default"))); extern "C" inline bool unboxBool(Box* b) __attribute__((visibility("default")));
extern "C" inline bool unboxBool(Box* b) { extern "C" inline bool unboxBool(Box* b) {
......
...@@ -20,7 +20,7 @@ ...@@ -20,7 +20,7 @@
#include "core/ast.h" #include "core/ast.h"
#include "core/threading.h" #include "core/threading.h"
#include "core/types.h" #include "core/types.h"
#include "runtime/complex.h" // #include "runtime/complex.h"
#include "runtime/float.h" #include "runtime/float.h"
#include "runtime/generator.h" #include "runtime/generator.h"
#include "runtime/import.h" #include "runtime/import.h"
...@@ -69,7 +69,7 @@ void force() { ...@@ -69,7 +69,7 @@ void force() {
FORCE(createClosure); FORCE(createClosure);
FORCE(createGenerator); FORCE(createGenerator);
FORCE(createLong); FORCE(createLong);
FORCE(createPureImaginary); // FORCE(createPureImaginary);
FORCE(createSet); FORCE(createSet);
FORCE(decodeUTF8StringPtr); FORCE(decodeUTF8StringPtr);
......
...@@ -35,7 +35,7 @@ ...@@ -35,7 +35,7 @@
#include "core/types.h" #include "core/types.h"
#include "runtime/classobj.h" #include "runtime/classobj.h"
#include "runtime/code.h" #include "runtime/code.h"
#include "runtime/complex.h" // #include "runtime/complex.h"
#include "runtime/dict.h" #include "runtime/dict.h"
#include "runtime/file.h" #include "runtime/file.h"
#include "runtime/hiddenclass.h" #include "runtime/hiddenclass.h"
...@@ -568,7 +568,7 @@ BoxedFloat* BoxedModule::getFloatConstant(double d) { ...@@ -568,7 +568,7 @@ BoxedFloat* BoxedModule::getFloatConstant(double d) {
Box* BoxedModule::getPureImaginaryConstant(double d) { Box* BoxedModule::getPureImaginaryConstant(double d) {
Box*& r = imaginary_constants[getDoubleBits(d)]; Box*& r = imaginary_constants[getDoubleBits(d)];
if (!r) if (!r)
r = createPureImaginary(d); r = PyComplex_FromDoubles(0.0, d);
return r; return r;
} }
...@@ -1557,9 +1557,9 @@ void BoxedClosure::gcHandler(GCVisitor* v, Box* b) { ...@@ -1557,9 +1557,9 @@ void BoxedClosure::gcHandler(GCVisitor* v, Box* b) {
extern "C" { extern "C" {
BoxedClass* object_cls, *type_cls, *none_cls, *bool_cls, *int_cls, *float_cls, BoxedClass* object_cls, *type_cls, *none_cls, *bool_cls, *int_cls, *float_cls,
* str_cls = NULL, *function_cls, *instancemethod_cls, *list_cls, *slice_cls, *module_cls, *dict_cls, *tuple_cls, * str_cls = NULL, *function_cls, *instancemethod_cls, *list_cls, *slice_cls, *module_cls, *dict_cls, *tuple_cls,
*file_cls, *member_descriptor_cls, *closure_cls, *generator_cls, *null_importer_cls, *complex_cls, *file_cls, *member_descriptor_cls, *closure_cls, *generator_cls, *null_importer_cls, *basestring_cls,
*basestring_cls, *property_cls, *staticmethod_cls, *classmethod_cls, *attrwrapper_cls, *pyston_getset_cls, *property_cls, *staticmethod_cls, *classmethod_cls, *attrwrapper_cls, *pyston_getset_cls, *capi_getset_cls,
*capi_getset_cls, *builtin_function_or_method_cls, *attrwrapperiter_cls, *set_cls, *frozenset_cls; *builtin_function_or_method_cls, *attrwrapperiter_cls, *set_cls, *frozenset_cls;
BoxedTuple* EmptyTuple; BoxedTuple* EmptyTuple;
} }
...@@ -3689,7 +3689,7 @@ void setupRuntime() { ...@@ -3689,7 +3689,7 @@ void setupRuntime() {
int_cls = new (0) BoxedClass(object_cls, NULL, 0, 0, sizeof(BoxedInt), false, "int"); int_cls = new (0) BoxedClass(object_cls, NULL, 0, 0, sizeof(BoxedInt), false, "int");
int_cls->tp_flags |= Py_TPFLAGS_INT_SUBCLASS; int_cls->tp_flags |= Py_TPFLAGS_INT_SUBCLASS;
bool_cls = new (0) BoxedClass(int_cls, NULL, 0, 0, sizeof(BoxedBool), false, "bool"); bool_cls = new (0) BoxedClass(int_cls, NULL, 0, 0, sizeof(BoxedBool), false, "bool");
complex_cls = new (0) BoxedClass(object_cls, NULL, 0, 0, sizeof(BoxedComplex), false, "complex"); // complex_cls = new (0) BoxedClass(object_cls, NULL, 0, 0, sizeof(BoxedComplex), false, "complex");
long_cls = new (0) BoxedClass(object_cls, &BoxedLong::gchandler, 0, 0, sizeof(BoxedLong), false, "long"); long_cls = new (0) BoxedClass(object_cls, &BoxedLong::gchandler, 0, 0, sizeof(BoxedLong), false, "long");
long_cls->tp_flags |= Py_TPFLAGS_LONG_SUBCLASS; long_cls->tp_flags |= Py_TPFLAGS_LONG_SUBCLASS;
float_cls = new (0) BoxedClass(object_cls, NULL, 0, 0, sizeof(BoxedFloat), false, "float"); float_cls = new (0) BoxedClass(object_cls, NULL, 0, 0, sizeof(BoxedFloat), false, "float");
...@@ -3739,7 +3739,7 @@ void setupRuntime() { ...@@ -3739,7 +3739,7 @@ void setupRuntime() {
file_cls->tp_mro = BoxedTuple::create({ file_cls, object_cls }); file_cls->tp_mro = BoxedTuple::create({ file_cls, object_cls });
int_cls->tp_mro = BoxedTuple::create({ int_cls, object_cls }); int_cls->tp_mro = BoxedTuple::create({ int_cls, object_cls });
bool_cls->tp_mro = BoxedTuple::create({ bool_cls, object_cls }); bool_cls->tp_mro = BoxedTuple::create({ bool_cls, object_cls });
complex_cls->tp_mro = BoxedTuple::create({ complex_cls, object_cls }); // complex_cls->tp_mro = BoxedTuple::create({ complex_cls, object_cls });
long_cls->tp_mro = BoxedTuple::create({ long_cls, object_cls }); long_cls->tp_mro = BoxedTuple::create({ long_cls, object_cls });
float_cls->tp_mro = BoxedTuple::create({ float_cls, object_cls }); float_cls->tp_mro = BoxedTuple::create({ float_cls, object_cls });
function_cls->tp_mro = BoxedTuple::create({ function_cls, object_cls }); function_cls->tp_mro = BoxedTuple::create({ function_cls, object_cls });
...@@ -3794,7 +3794,7 @@ void setupRuntime() { ...@@ -3794,7 +3794,7 @@ void setupRuntime() {
file_cls->finishInitialization(); file_cls->finishInitialization();
int_cls->finishInitialization(); int_cls->finishInitialization();
bool_cls->finishInitialization(); bool_cls->finishInitialization();
complex_cls->finishInitialization(); // complex_cls->finishInitialization();
long_cls->finishInitialization(); long_cls->finishInitialization();
float_cls->finishInitialization(); float_cls->finishInitialization();
function_cls->finishInitialization(); function_cls->finishInitialization();
...@@ -3925,7 +3925,6 @@ void setupRuntime() { ...@@ -3925,7 +3925,6 @@ void setupRuntime() {
setupBool(); setupBool();
setupLong(); setupLong();
setupFloat(); setupFloat();
setupComplex();
setupStr(); setupStr();
setupList(); setupList();
setupDict(); setupDict();
...@@ -4078,6 +4077,7 @@ void setupRuntime() { ...@@ -4078,6 +4077,7 @@ void setupRuntime() {
attrwrapperiter_cls->tp_iter = PyObject_SelfIter; attrwrapperiter_cls->tp_iter = PyObject_SelfIter;
attrwrapperiter_cls->tp_iternext = AttrWrapperIter::next_capi; attrwrapperiter_cls->tp_iternext = AttrWrapperIter::next_capi;
PyType_Ready(&PyComplex_Type);
setupBuiltins(); setupBuiltins();
_PyExc_Init(); _PyExc_Init();
setupThread(); setupThread();
...@@ -4181,7 +4181,7 @@ void teardownRuntime() { ...@@ -4181,7 +4181,7 @@ void teardownRuntime() {
teardownList(); teardownList();
teardownInt(); teardownInt();
teardownFloat(); teardownFloat();
teardownComplex(); // teardownComplex();
teardownStr(); teardownStr();
teardownBool(); teardownBool();
teardownDict(); teardownDict();
......
...@@ -46,8 +46,6 @@ void setupInt(); ...@@ -46,8 +46,6 @@ void setupInt();
void teardownInt(); void teardownInt();
void setupFloat(); void setupFloat();
void teardownFloat(); void teardownFloat();
void setupComplex();
void teardownComplex();
void setupStr(); void setupStr();
void teardownStr(); void teardownStr();
void setupList(); void setupList();
...@@ -91,13 +89,11 @@ extern "C" { ...@@ -91,13 +89,11 @@ extern "C" {
extern BoxedClass* object_cls, *type_cls, *bool_cls, *int_cls, *long_cls, *float_cls, *str_cls, *function_cls, extern BoxedClass* object_cls, *type_cls, *bool_cls, *int_cls, *long_cls, *float_cls, *str_cls, *function_cls,
*none_cls, *instancemethod_cls, *list_cls, *slice_cls, *module_cls, *dict_cls, *tuple_cls, *file_cls, *none_cls, *instancemethod_cls, *list_cls, *slice_cls, *module_cls, *dict_cls, *tuple_cls, *file_cls,
*enumerate_cls, *xrange_cls, *member_descriptor_cls, *null_importer_cls, *method_cls, *closure_cls, *generator_cls, *enumerate_cls, *xrange_cls, *member_descriptor_cls, *null_importer_cls, *method_cls, *closure_cls, *generator_cls,
*complex_cls, *basestring_cls, *property_cls, *staticmethod_cls, *classmethod_cls, *attrwrapper_cls, *basestring_cls, *property_cls, *staticmethod_cls, *classmethod_cls, *attrwrapper_cls, *pyston_getset_cls,
*pyston_getset_cls, *capi_getset_cls, *builtin_function_or_method_cls, *set_cls, *frozenset_cls, *code_cls, *capi_getset_cls, *builtin_function_or_method_cls, *set_cls, *frozenset_cls, *code_cls, *frame_cls, *capifunc_cls,
*frame_cls, *capifunc_cls, *wrapperdescr_cls, *wrapperobject_cls; *wrapperdescr_cls, *wrapperobject_cls;
} }
#define unicode_cls (&PyUnicode_Type) #define complex_cls (&PyComplex_Type)
#define memoryview_cls (&PyMemoryView_Type)
#define unicode_cls (&PyUnicode_Type) #define unicode_cls (&PyUnicode_Type)
#define memoryview_cls (&PyMemoryView_Type) #define memoryview_cls (&PyMemoryView_Type)
...@@ -380,15 +376,15 @@ public: ...@@ -380,15 +376,15 @@ public:
static_assert(sizeof(BoxedFloat) == sizeof(PyFloatObject), ""); static_assert(sizeof(BoxedFloat) == sizeof(PyFloatObject), "");
static_assert(offsetof(BoxedFloat, d) == offsetof(PyFloatObject, ob_fval), ""); static_assert(offsetof(BoxedFloat, d) == offsetof(PyFloatObject, ob_fval), "");
class BoxedComplex : public Box { // class BoxedComplex : public Box {
public: // public:
double real; // double real;
double imag; // double imag;
//
BoxedComplex(double r, double i) __attribute__((visibility("default"))) : real(r), imag(i) {} // BoxedComplex(double r, double i) __attribute__((visibility("default"))) : real(r), imag(i) {}
//
DEFAULT_CLASS_SIMPLE(complex_cls); // DEFAULT_CLASS_SIMPLE(complex_cls);
}; // };
class BoxedBool : public BoxedInt { class BoxedBool : public BoxedInt {
public: public:
......
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