Commit 9216f615 authored by Marius Wachtler's avatar Marius Wachtler

Merge pull request #1030 from Daetalus/numeric_fixing

Add some missing attributes to Int object
parents f1e9b55f 91517da6
...@@ -747,7 +747,8 @@ float_rem(PyObject *v, PyObject *w) ...@@ -747,7 +747,8 @@ float_rem(PyObject *v, PyObject *w)
return PyFloat_FromDouble(mod); return PyFloat_FromDouble(mod);
} }
static PyObject * // pyston change: make this not static
PyObject *
float_divmod(PyObject *v, PyObject *w) float_divmod(PyObject *v, PyObject *w)
{ {
double vx, wx; double vx, wx;
...@@ -987,7 +988,8 @@ float_nonzero(PyFloatObject *v) ...@@ -987,7 +988,8 @@ float_nonzero(PyFloatObject *v)
return v->ob_fval != 0.0; return v->ob_fval != 0.0;
} }
static int // pyston change: make not static
int
float_coerce(PyObject **pv, PyObject **pw) float_coerce(PyObject **pv, PyObject **pw)
{ {
if (PyInt_Check(*pw)) { if (PyInt_Check(*pw)) {
...@@ -1949,7 +1951,8 @@ PyDoc_STRVAR(float_getformat_doc, ...@@ -1949,7 +1951,8 @@ PyDoc_STRVAR(float_getformat_doc,
"'unknown', 'IEEE, big-endian' or 'IEEE, little-endian' best describes the\n" "'unknown', 'IEEE, big-endian' or 'IEEE, little-endian' best describes the\n"
"format of floating point numbers used by the C type named by typestr."); "format of floating point numbers used by the C type named by typestr.");
static PyObject * // pyston change: make not static
PyObject *
float_setformat(PyTypeObject *v, PyObject* args) float_setformat(PyTypeObject *v, PyObject* args)
{ {
char* typestr; char* typestr;
......
...@@ -27,11 +27,14 @@ ...@@ -27,11 +27,14 @@
#include "runtime/types.h" #include "runtime/types.h"
#include "runtime/util.h" #include "runtime/util.h"
extern "C" PyObject* float_divmod(PyObject* v, PyObject* w) noexcept;
extern "C" int float_coerce(PyObject** v, PyObject** w) noexcept;
extern "C" PyObject* float_hex(PyObject* v) noexcept; extern "C" PyObject* float_hex(PyObject* v) noexcept;
extern "C" PyObject* float_fromhex(PyObject* cls, PyObject* arg) noexcept; extern "C" PyObject* float_fromhex(PyObject* cls, PyObject* arg) noexcept;
extern "C" PyObject* float_as_integer_ratio(PyObject* v, PyObject* unused) noexcept; extern "C" PyObject* float_as_integer_ratio(PyObject* v, PyObject* unused) noexcept;
extern "C" PyObject* float_is_integer(PyObject* v) noexcept; extern "C" PyObject* float_is_integer(PyObject* v) noexcept;
extern "C" PyObject* float__format__(PyObject* v) noexcept; extern "C" PyObject* float__format__(PyObject* v) noexcept;
extern "C" PyObject* float_setformat(PyTypeObject* v, PyObject* args) noexcept;
extern "C" PyObject* float_pow(PyObject* v, PyObject* w, PyObject* z) noexcept; extern "C" PyObject* float_pow(PyObject* v, PyObject* w, PyObject* z) noexcept;
extern "C" PyObject* float_str(PyObject* v) noexcept; extern "C" PyObject* float_str(PyObject* v) noexcept;
extern "C" int float_pow_unboxed(double iv, double iw, double* res) noexcept; extern "C" int float_pow_unboxed(double iv, double iw, double* res) noexcept;
...@@ -213,6 +216,28 @@ extern "C" Box* floatRDiv(BoxedFloat* lhs, Box* rhs) { ...@@ -213,6 +216,28 @@ extern "C" Box* floatRDiv(BoxedFloat* lhs, Box* rhs) {
if (rhs_f == -1.0 && PyErr_Occurred()) { if (rhs_f == -1.0 && PyErr_Occurred()) {
throwCAPIException(); throwCAPIException();
} }
raiseDivZeroExcIfZero(lhs->d);
return boxFloat(rhs_f / lhs->d);
} else {
return NotImplemented;
}
}
Box* floatRTruediv(BoxedFloat* lhs, Box* rhs) {
if (!PyFloat_Check(lhs))
raiseExcHelper(TypeError, "descriptor '__rtruediv__' requires a 'float' object but received a '%s'",
getTypeName(lhs));
if (PyInt_Check(rhs)) {
return floatRDivInt(lhs, static_cast<BoxedInt*>(rhs));
} else if (PyFloat_Check(rhs)) {
return floatRDivFloat(lhs, static_cast<BoxedFloat*>(rhs));
} else if (PyLong_Check(rhs)) {
double rhs_f = PyLong_AsDouble(rhs);
if (rhs_f == -1.0 && PyErr_Occurred()) {
throwCAPIException();
}
raiseDivZeroExcIfZero(lhs->d);
return boxFloat(rhs_f / lhs->d); return boxFloat(rhs_f / lhs->d);
} else { } else {
return NotImplemented; return NotImplemented;
...@@ -631,6 +656,30 @@ extern "C" Box* floatRMod(BoxedFloat* lhs, Box* rhs) { ...@@ -631,6 +656,30 @@ extern "C" Box* floatRMod(BoxedFloat* lhs, Box* rhs) {
} }
} }
Box* floatDivmod(BoxedFloat* lhs, Box* rhs) {
if (!PyFloat_Check(lhs))
raiseExcHelper(TypeError, "descriptor '__divmod__' requires a 'float' object but received a '%s'",
getTypeName(lhs));
Box* res = float_divmod(lhs, rhs);
if (!res) {
throwCAPIException();
}
return res;
}
Box* floatRDivmod(BoxedFloat* lhs, Box* rhs) {
if (!PyFloat_Check(lhs))
raiseExcHelper(TypeError, "descriptor '__rdivmod__' requires a 'float' object but received a '%s'",
getTypeName(lhs));
Box* res = float_divmod(rhs, lhs);
if (!res) {
throwCAPIException();
}
return res;
}
extern "C" Box* floatPow(BoxedFloat* lhs, Box* rhs, Box* mod) { extern "C" Box* floatPow(BoxedFloat* lhs, Box* rhs, Box* mod) {
Box* res = float_pow(lhs, rhs, mod); Box* res = float_pow(lhs, rhs, mod);
if (!res) { if (!res) {
...@@ -653,6 +702,18 @@ extern "C" Box* floatPowInt(BoxedFloat* lhs, BoxedInt* rhs, Box* mod = None) { ...@@ -653,6 +702,18 @@ extern "C" Box* floatPowInt(BoxedFloat* lhs, BoxedInt* rhs, Box* mod = None) {
return floatPow(lhs, rhs, mod); return floatPow(lhs, rhs, mod);
} }
Box* floatRPow(BoxedFloat* lhs, Box* rhs) {
if (!PyFloat_Check(lhs))
raiseExcHelper(TypeError, "descriptor '__rpow__' requires a 'float' object but received a '%s'",
getTypeName(lhs));
Box* res = float_pow(rhs, lhs, None);
if (!res) {
throwCAPIException();
}
return res;
}
extern "C" double pow_float_float(double lhs, double rhs) { extern "C" double pow_float_float(double lhs, double rhs) {
double res; double res;
int err = float_pow_unboxed(lhs, rhs, &res); int err = float_pow_unboxed(lhs, rhs, &res);
...@@ -862,7 +923,10 @@ template <ExceptionStyle S> static BoxedFloat* _floatNew(Box* a) noexcept(S == C ...@@ -862,7 +923,10 @@ template <ExceptionStyle S> static BoxedFloat* _floatNew(Box* a) noexcept(S == C
} else if (PyLong_Check(a)) { } else if (PyLong_Check(a)) {
double a_f = PyLong_AsDouble(a); double a_f = PyLong_AsDouble(a);
if (a_f == -1.0 && PyErr_Occurred()) { if (a_f == -1.0 && PyErr_Occurred()) {
throwCAPIException(); if (S == CAPI)
return NULL;
else
throwCAPIException();
} }
return new BoxedFloat(a_f); return new BoxedFloat(a_f);
} else if (a->cls == str_cls || a->cls == unicode_cls) { } else if (a->cls == str_cls || a->cls == unicode_cls) {
...@@ -968,11 +1032,7 @@ Box* floatRepr(BoxedFloat* self) { ...@@ -968,11 +1032,7 @@ Box* floatRepr(BoxedFloat* self) {
return float_str_or_repr(self->d, 0, 'r'); return float_str_or_repr(self->d, 0, 'r');
} }
Box* floatTrunc(BoxedFloat* self) { Box* floatToInt(BoxedFloat* self) {
if (!PyFloat_Check(self))
raiseExcHelper(TypeError, "descriptor '__trunc__' requires a 'float' object but received a '%s'",
getTypeName(self));
double wholepart; /* integral portion of x, rounded toward 0 */ double wholepart; /* integral portion of x, rounded toward 0 */
(void)modf(self->d, &wholepart); (void)modf(self->d, &wholepart);
...@@ -998,6 +1058,45 @@ Box* floatTrunc(BoxedFloat* self) { ...@@ -998,6 +1058,45 @@ Box* floatTrunc(BoxedFloat* self) {
return PyLong_FromDouble(wholepart); return PyLong_FromDouble(wholepart);
} }
Box* floatTrunc(BoxedFloat* self) {
if (!PyFloat_Check(self))
raiseExcHelper(TypeError, "descriptor '__trunc__' requires a 'float' object but received a '%s'",
getTypeName(self));
return floatToInt(self);
}
Box* floatInt(BoxedFloat* self) {
if (!PyFloat_Check(self))
raiseExcHelper(TypeError, "descriptor '__int__' requires a 'float' object but received a '%s'",
getTypeName(self));
return floatToInt(self);
}
Box* floatLong(BoxedFloat* self) {
if (!PyFloat_Check(self))
raiseExcHelper(TypeError, "descriptor '__long__' requires a 'float' object but received a '%s'",
getTypeName(self));
double x = PyFloat_AsDouble(self);
return PyLong_FromDouble(x);
}
Box* floatCoerce(BoxedFloat* _self, Box* other) {
if (!PyFloat_Check(_self))
raiseExcHelper(TypeError, "descriptor '__coerce__' requires a 'float' object but received a '%s'",
getTypeName(_self));
Box* self = static_cast<Box*>(_self);
int result = float_coerce(&self, &other);
if (result == 0)
return BoxedTuple::create({ self, other });
else if (result == 1)
return NotImplemented;
else
throwCAPIException();
}
Box* floatHash(BoxedFloat* self) { Box* floatHash(BoxedFloat* self) {
if (!PyFloat_Check(self)) if (!PyFloat_Check(self))
raiseExcHelper(TypeError, "descriptor '__hash__' requires a 'float' object but received a '%s'", raiseExcHelper(TypeError, "descriptor '__hash__' requires a 'float' object but received a '%s'",
...@@ -1577,12 +1676,25 @@ static PyObject* float_getnewargs(PyFloatObject* v) noexcept { ...@@ -1577,12 +1676,25 @@ static PyObject* float_getnewargs(PyFloatObject* v) noexcept {
return Py_BuildValue("(d)", v->ob_fval); return Py_BuildValue("(d)", v->ob_fval);
} }
static PyMethodDef float_methods[] = { { "hex", (PyCFunction)float_hex, METH_NOARGS, NULL }, PyDoc_STRVAR(float_setformat_doc, "float.__setformat__(typestr, fmt) -> None\n"
{ "fromhex", (PyCFunction)float_fromhex, METH_O | METH_CLASS, NULL }, "\n"
{ "as_integer_ratio", (PyCFunction)float_as_integer_ratio, METH_NOARGS, NULL }, "You probably don't want to use this function. It exists mainly to be\n"
"used in Python's test suite.\n"
{ "is_integer", (PyCFunction)float_is_integer, METH_NOARGS, NULL }, "\n"
{ "__format__", (PyCFunction)float__format__, METH_VARARGS, NULL } }; "typestr must be 'double' or 'float'. fmt must be one of 'unknown',\n"
"'IEEE, big-endian' or 'IEEE, little-endian', and in addition can only be\n"
"one of the latter two if it appears to match the underlying C reality.\n"
"\n"
"Override the automatic determination of C-level floating point type.\n"
"This affects how floats are converted to and from binary strings.");
static PyMethodDef float_methods[]
= { { "hex", (PyCFunction)float_hex, METH_NOARGS, NULL },
{ "fromhex", (PyCFunction)float_fromhex, METH_O | METH_CLASS, NULL },
{ "as_integer_ratio", (PyCFunction)float_as_integer_ratio, METH_NOARGS, NULL },
{ "__setformat__", (PyCFunction)float_setformat, METH_VARARGS | METH_CLASS, float_setformat_doc },
{ "is_integer", (PyCFunction)float_is_integer, METH_NOARGS, NULL },
{ "__format__", (PyCFunction)float__format__, METH_VARARGS, NULL } };
void setupFloat() { void setupFloat() {
static PyNumberMethods float_as_number; static PyNumberMethods float_as_number;
...@@ -1600,6 +1712,7 @@ void setupFloat() { ...@@ -1600,6 +1712,7 @@ void setupFloat() {
float_cls->giveAttr("__rfloordiv__", float_cls->giveAttr("__rfloordiv__",
new BoxedFunction(FunctionMetadata::create((void*)floatRFloorDiv, BOXED_FLOAT, 2))); new BoxedFunction(FunctionMetadata::create((void*)floatRFloorDiv, BOXED_FLOAT, 2)));
_addFunc("__truediv__", BOXED_FLOAT, (void*)floatDivFloat, (void*)floatDivInt, (void*)floatTruediv); _addFunc("__truediv__", BOXED_FLOAT, (void*)floatDivFloat, (void*)floatDivInt, (void*)floatTruediv);
float_cls->giveAttr("__rtruediv__", new BoxedFunction(FunctionMetadata::create((void*)floatRTruediv, UNKNOWN, 2)));
_addFunc("__mod__", BOXED_FLOAT, (void*)floatModFloat, (void*)floatModInt, (void*)floatMod); _addFunc("__mod__", BOXED_FLOAT, (void*)floatModFloat, (void*)floatModInt, (void*)floatMod);
_addFunc("__rmod__", BOXED_FLOAT, (void*)floatRModFloat, (void*)floatRModInt, (void*)floatRMod); _addFunc("__rmod__", BOXED_FLOAT, (void*)floatRModFloat, (void*)floatRModInt, (void*)floatRMod);
...@@ -1607,8 +1720,11 @@ void setupFloat() { ...@@ -1607,8 +1720,11 @@ void setupFloat() {
float_cls->giveAttr("__rmul__", float_cls->getattr(internStringMortal("__mul__"))); float_cls->giveAttr("__rmul__", float_cls->getattr(internStringMortal("__mul__")));
_addFuncPow("__pow__", BOXED_FLOAT, (void*)floatPowFloat, (void*)floatPowInt, (void*)floatPow); _addFuncPow("__pow__", BOXED_FLOAT, (void*)floatPowFloat, (void*)floatPowInt, (void*)floatPow);
float_cls->giveAttr("__rpow__", new BoxedFunction(FunctionMetadata::create((void*)floatRPow, UNKNOWN, 2)));
_addFunc("__sub__", BOXED_FLOAT, (void*)floatSubFloat, (void*)floatSubInt, (void*)floatSub); _addFunc("__sub__", BOXED_FLOAT, (void*)floatSubFloat, (void*)floatSubInt, (void*)floatSub);
_addFunc("__rsub__", BOXED_FLOAT, (void*)floatRSubFloat, (void*)floatRSubInt, (void*)floatRSub); _addFunc("__rsub__", BOXED_FLOAT, (void*)floatRSubFloat, (void*)floatRSubInt, (void*)floatRSub);
float_cls->giveAttr("__divmod__", new BoxedFunction(FunctionMetadata::create((void*)floatDivmod, UNKNOWN, 2)));
float_cls->giveAttr("__rdivmod__", new BoxedFunction(FunctionMetadata::create((void*)floatRDivmod, UNKNOWN, 2)));
auto float_new = FunctionMetadata::create((void*)floatNew<CXX>, UNKNOWN, 2, false, false, ParamNames::empty(), CXX); auto float_new = FunctionMetadata::create((void*)floatNew<CXX>, UNKNOWN, 2, false, false, ParamNames::empty(), CXX);
float_new->addVersion((void*)floatNew<CAPI>, UNKNOWN, CAPI); float_new->addVersion((void*)floatNew<CAPI>, UNKNOWN, CAPI);
...@@ -1632,8 +1748,11 @@ void setupFloat() { ...@@ -1632,8 +1748,11 @@ void setupFloat() {
float_cls->giveAttr("__float__", new BoxedFunction(FunctionMetadata::create((void*)floatFloat, BOXED_FLOAT, 1))); float_cls->giveAttr("__float__", new BoxedFunction(FunctionMetadata::create((void*)floatFloat, BOXED_FLOAT, 1)));
float_cls->giveAttr("__str__", new BoxedFunction(FunctionMetadata::create((void*)floatStr, STR, 1))); float_cls->giveAttr("__str__", new BoxedFunction(FunctionMetadata::create((void*)floatStr, STR, 1)));
float_cls->giveAttr("__repr__", new BoxedFunction(FunctionMetadata::create((void*)floatRepr, STR, 1))); float_cls->giveAttr("__repr__", new BoxedFunction(FunctionMetadata::create((void*)floatRepr, STR, 1)));
float_cls->giveAttr("__coerce__", new BoxedFunction(FunctionMetadata::create((void*)floatCoerce, UNKNOWN, 2)));
float_cls->giveAttr("__trunc__", new BoxedFunction(FunctionMetadata::create((void*)floatTrunc, UNKNOWN, 1))); float_cls->giveAttr("__trunc__", new BoxedFunction(FunctionMetadata::create((void*)floatTrunc, UNKNOWN, 1)));
float_cls->giveAttr("__int__", new BoxedFunction(FunctionMetadata::create((void*)floatInt, UNKNOWN, 1)));
float_cls->giveAttr("__long__", new BoxedFunction(FunctionMetadata::create((void*)floatLong, UNKNOWN, 1)));
float_cls->giveAttr("__hash__", new BoxedFunction(FunctionMetadata::create((void*)floatHash, BOXED_INT, 1))); float_cls->giveAttr("__hash__", new BoxedFunction(FunctionMetadata::create((void*)floatHash, BOXED_INT, 1)));
float_cls->giveAttr("real", new (pyston_getset_cls) BoxedGetsetDescriptor(floatConjugate, NULL, NULL)); float_cls->giveAttr("real", new (pyston_getset_cls) BoxedGetsetDescriptor(floatConjugate, NULL, NULL));
...@@ -1641,6 +1760,9 @@ void setupFloat() { ...@@ -1641,6 +1760,9 @@ void setupFloat() {
float_cls->giveAttr("conjugate", float_cls->giveAttr("conjugate",
new BoxedFunction(FunctionMetadata::create((void*)floatConjugate, BOXED_FLOAT, 1))); new BoxedFunction(FunctionMetadata::create((void*)floatConjugate, BOXED_FLOAT, 1)));
float_cls->giveAttr("__doc__", boxString("float(x) -> floating point number\n"
"\n"
"Convert a string or number to a floating point number, if possible."));
float_cls->giveAttr("__getformat__", float_cls->giveAttr("__getformat__",
new BoxedBuiltinFunctionOrMethod(FunctionMetadata::create((void*)floatGetFormat, STR, 1), new BoxedBuiltinFunctionOrMethod(FunctionMetadata::create((void*)floatGetFormat, STR, 1),
"__getformat__", floatGetFormatDoc)); "__getformat__", floatGetFormatDoc));
......
...@@ -149,9 +149,17 @@ Box* getFrame(int depth) { ...@@ -149,9 +149,17 @@ Box* getFrame(int depth) {
return BoxedFrame::boxFrame(std::move(it)); return BoxedFrame::boxFrame(std::move(it));
} }
extern "C" int PyFrame_GetLineNumber(PyFrameObject* f) noexcept { extern "C" int PyFrame_GetLineNumber(PyFrameObject* _f) noexcept {
BoxedInt* lineno = (BoxedInt*)BoxedFrame::lineno((Box*)f, NULL); // TODO remove this when we are able to introspect exited frames:
return lineno->n; // We check if the frame exited and only return the correct line number when it is still available.
// Because of a limitation in out current frame introspection we can also not inspect OSRed frames.
BoxedFrame* f = (BoxedFrame*)_f;
PythonFrameIterator new_it = f->it.getCurrentVersion();
if (new_it.exists() && new_it.getFrameInfo()->frame_obj == f) {
BoxedInt* lineno = (BoxedInt*)BoxedFrame::lineno((Box*)f, NULL);
return lineno->n;
}
return -1;
} }
extern "C" PyObject* PyFrame_GetGlobals(PyFrameObject* f) noexcept { extern "C" PyObject* PyFrame_GetGlobals(PyFrameObject* f) noexcept {
......
...@@ -378,6 +378,16 @@ extern "C" i64 mod_i64_i64(i64 lhs, i64 rhs) { ...@@ -378,6 +378,16 @@ extern "C" i64 mod_i64_i64(i64 lhs, i64 rhs) {
} }
extern "C" Box* pow_i64_i64(i64 lhs, i64 rhs, Box* mod) { extern "C" Box* pow_i64_i64(i64 lhs, i64 rhs, Box* mod) {
if (mod != None) {
if (!PyInt_Check(mod)) {
return NotImplemented;
}
BoxedInt* mod_int = static_cast<BoxedInt*>(mod);
if (mod_int->n == 0) {
raiseExcHelper(ValueError, "pow() 3rd argument cannot be 0");
}
}
i64 orig_rhs = rhs; i64 orig_rhs = rhs;
i64 rtn = 1, curpow = lhs; i64 rtn = 1, curpow = lhs;
...@@ -424,6 +434,19 @@ extern "C" Box* intAdd(BoxedInt* lhs, Box* rhs) { ...@@ -424,6 +434,19 @@ extern "C" Box* intAdd(BoxedInt* lhs, Box* rhs) {
} }
} }
Box* intRAdd(BoxedInt* lhs, Box* rhs) {
if (!PyInt_Check(lhs))
raiseExcHelper(TypeError, "descriptor '__radd__' requires a 'int' object but received a '%s'",
getTypeName(lhs));
if (PyInt_Check(rhs)) {
BoxedInt* rhs_int = static_cast<BoxedInt*>(rhs);
return add_i64_i64(lhs->n, rhs_int->n);
} else {
return NotImplemented;
}
}
extern "C" Box* intAndInt(BoxedInt* lhs, BoxedInt* rhs) { extern "C" Box* intAndInt(BoxedInt* lhs, BoxedInt* rhs) {
assert(PyInt_Check(lhs)); assert(PyInt_Check(lhs));
assert(PyInt_Check(rhs)); assert(PyInt_Check(rhs));
...@@ -441,6 +464,18 @@ extern "C" Box* intAnd(BoxedInt* lhs, Box* rhs) { ...@@ -441,6 +464,18 @@ extern "C" Box* intAnd(BoxedInt* lhs, Box* rhs) {
return boxInt(lhs->n & rhs_int->n); return boxInt(lhs->n & rhs_int->n);
} }
Box* intRAnd(BoxedInt* lhs, Box* rhs) {
if (!PyInt_Check(lhs))
raiseExcHelper(TypeError, "descriptor '__rand__' requires a 'int' object but received a '%s'",
getTypeName(lhs));
if (!PyInt_Check(rhs)) {
return NotImplemented;
}
BoxedInt* rhs_int = static_cast<BoxedInt*>(rhs);
return boxInt(lhs->n & rhs_int->n);
}
extern "C" Box* intOrInt(BoxedInt* lhs, BoxedInt* rhs) { extern "C" Box* intOrInt(BoxedInt* lhs, BoxedInt* rhs) {
assert(PyInt_Check(lhs)); assert(PyInt_Check(lhs));
assert(PyInt_Check(rhs)); assert(PyInt_Check(rhs));
...@@ -458,6 +493,17 @@ extern "C" Box* intOr(BoxedInt* lhs, Box* rhs) { ...@@ -458,6 +493,17 @@ extern "C" Box* intOr(BoxedInt* lhs, Box* rhs) {
return boxInt(lhs->n | rhs_int->n); return boxInt(lhs->n | rhs_int->n);
} }
Box* intROr(BoxedInt* lhs, Box* rhs) {
if (!PyInt_Check(lhs))
raiseExcHelper(TypeError, "descriptor '__ror__' requires a 'int' object but received a '%s'", getTypeName(lhs));
if (!PyInt_Check(rhs)) {
return NotImplemented;
}
BoxedInt* rhs_int = static_cast<BoxedInt*>(rhs);
return boxInt(lhs->n | rhs_int->n);
}
extern "C" Box* intXorInt(BoxedInt* lhs, BoxedInt* rhs) { extern "C" Box* intXorInt(BoxedInt* lhs, BoxedInt* rhs) {
assert(PyInt_Check(lhs)); assert(PyInt_Check(lhs));
assert(PyInt_Check(rhs)); assert(PyInt_Check(rhs));
...@@ -475,6 +521,18 @@ extern "C" Box* intXor(BoxedInt* lhs, Box* rhs) { ...@@ -475,6 +521,18 @@ extern "C" Box* intXor(BoxedInt* lhs, Box* rhs) {
return boxInt(lhs->n ^ rhs_int->n); return boxInt(lhs->n ^ rhs_int->n);
} }
Box* intRXor(BoxedInt* lhs, Box* rhs) {
if (!PyInt_Check(lhs))
raiseExcHelper(TypeError, "descriptor '__rxor__' requires a 'int' object but received a '%s'",
getTypeName(lhs));
if (!PyInt_Check(rhs)) {
return NotImplemented;
}
BoxedInt* rhs_int = static_cast<BoxedInt*>(rhs);
return boxInt(lhs->n ^ rhs_int->n);
}
extern "C" Box* intDivInt(BoxedInt* lhs, BoxedInt* rhs) { extern "C" Box* intDivInt(BoxedInt* lhs, BoxedInt* rhs) {
assert(PyInt_Check(lhs)); assert(PyInt_Check(lhs));
assert(PyInt_Check(rhs)); assert(PyInt_Check(rhs));
...@@ -504,6 +562,18 @@ extern "C" Box* intDiv(BoxedInt* lhs, Box* rhs) { ...@@ -504,6 +562,18 @@ extern "C" Box* intDiv(BoxedInt* lhs, Box* rhs) {
} }
} }
Box* intRDiv(BoxedInt* lhs, Box* rhs) {
if (!PyInt_Check(lhs))
raiseExcHelper(TypeError, "descriptor '__rdiv__' requires a 'int' object but received a '%s'",
getTypeName(lhs));
if (PyInt_Check(rhs)) {
return div_i64_i64(static_cast<BoxedInt*>(rhs)->n, lhs->n);
} else {
return NotImplemented;
}
}
extern "C" Box* intFloordivInt(BoxedInt* lhs, BoxedInt* rhs) { extern "C" Box* intFloordivInt(BoxedInt* lhs, BoxedInt* rhs) {
assert(PyInt_Check(lhs)); assert(PyInt_Check(lhs));
assert(PyInt_Check(rhs)); assert(PyInt_Check(rhs));
...@@ -534,6 +604,18 @@ extern "C" Box* intFloordiv(BoxedInt* lhs, Box* rhs) { ...@@ -534,6 +604,18 @@ extern "C" Box* intFloordiv(BoxedInt* lhs, Box* rhs) {
} }
} }
Box* intRFloordiv(BoxedInt* lhs, Box* rhs) {
if (!PyInt_Check(lhs))
raiseExcHelper(TypeError, "descriptor '__rfloordiv__' requires a 'int' object but received a '%s'",
getTypeName(lhs));
if (!PyInt_Check(rhs)) {
return NotImplemented;
}
return div_i64_i64(static_cast<BoxedInt*>(rhs)->n, lhs->n);
}
extern "C" Box* intTruedivInt(BoxedInt* lhs, BoxedInt* rhs) { extern "C" Box* intTruedivInt(BoxedInt* lhs, BoxedInt* rhs) {
assert(PyInt_Check(lhs)); assert(PyInt_Check(lhs));
assert(PyInt_Check(rhs)); assert(PyInt_Check(rhs));
...@@ -568,6 +650,18 @@ extern "C" Box* intTruediv(BoxedInt* lhs, Box* rhs) { ...@@ -568,6 +650,18 @@ extern "C" Box* intTruediv(BoxedInt* lhs, Box* rhs) {
} }
} }
Box* intRTruediv(BoxedInt* lhs, Box* rhs) {
if (!PyInt_Check(lhs))
raiseExcHelper(TypeError, "descriptor '__rtruediv__' requires a 'int' object but received a '%s'",
getTypeName(lhs));
if (PyInt_Check(rhs)) {
return intTruedivInt(static_cast<BoxedInt*>(rhs), lhs);
} else {
return NotImplemented;
}
}
extern "C" Box* intLShiftInt(BoxedInt* lhs, BoxedInt* rhs) { extern "C" Box* intLShiftInt(BoxedInt* lhs, BoxedInt* rhs) {
assert(PyInt_Check(lhs)); assert(PyInt_Check(lhs));
assert(PyInt_Check(rhs)); assert(PyInt_Check(rhs));
...@@ -581,7 +675,7 @@ extern "C" Box* intLShiftInt(BoxedInt* lhs, BoxedInt* rhs) { ...@@ -581,7 +675,7 @@ extern "C" Box* intLShiftInt(BoxedInt* lhs, BoxedInt* rhs) {
if ((res >> rhs->n) == lhs->n) if ((res >> rhs->n) == lhs->n)
return boxInt(lhs->n << rhs->n); return boxInt(lhs->n << rhs->n);
} }
return longLshift(boxLong(lhs->n), rhs); return longLShiftLong(boxLong(lhs->n), rhs);
} }
extern "C" Box* intLShift(BoxedInt* lhs, Box* rhs) { extern "C" Box* intLShift(BoxedInt* lhs, Box* rhs) {
...@@ -590,7 +684,7 @@ extern "C" Box* intLShift(BoxedInt* lhs, Box* rhs) { ...@@ -590,7 +684,7 @@ extern "C" Box* intLShift(BoxedInt* lhs, Box* rhs) {
getTypeName(lhs)); getTypeName(lhs));
if (rhs->cls == long_cls) if (rhs->cls == long_cls)
return longLshift(boxLong(lhs->n), rhs); return longLShiftLong(boxLong(lhs->n), rhs);
if (!PyInt_Check(rhs)) { if (!PyInt_Check(rhs)) {
return NotImplemented; return NotImplemented;
...@@ -599,6 +693,19 @@ extern "C" Box* intLShift(BoxedInt* lhs, Box* rhs) { ...@@ -599,6 +693,19 @@ extern "C" Box* intLShift(BoxedInt* lhs, Box* rhs) {
return intLShiftInt(lhs, rhs_int); return intLShiftInt(lhs, rhs_int);
} }
Box* intRLShift(BoxedInt* lhs, Box* rhs) {
if (!PyInt_Check(lhs))
raiseExcHelper(TypeError, "descriptor '__rlshift__' requires a 'int' object but received a '%s'",
getTypeName(lhs));
if (!PyInt_Check(rhs)) {
return NotImplemented;
}
BoxedInt* rhs_int = static_cast<BoxedInt*>(rhs);
return intLShiftInt(rhs_int, lhs);
}
extern "C" Box* intModInt(BoxedInt* lhs, BoxedInt* rhs) { extern "C" Box* intModInt(BoxedInt* lhs, BoxedInt* rhs) {
assert(PyInt_Check(lhs)); assert(PyInt_Check(lhs));
assert(PyInt_Check(rhs)); assert(PyInt_Check(rhs));
...@@ -616,6 +723,18 @@ extern "C" Box* intMod(BoxedInt* lhs, Box* rhs) { ...@@ -616,6 +723,18 @@ extern "C" Box* intMod(BoxedInt* lhs, Box* rhs) {
return boxInt(mod_i64_i64(lhs->n, rhs_int->n)); return boxInt(mod_i64_i64(lhs->n, rhs_int->n));
} }
Box* intRMod(BoxedInt* lhs, Box* rhs) {
if (!PyInt_Check(lhs))
raiseExcHelper(TypeError, "descriptor '__rmod__' requires a 'int' object but received a '%s'",
getTypeName(lhs));
if (!PyInt_Check(rhs)) {
return NotImplemented;
}
BoxedInt* rhs_int = static_cast<BoxedInt*>(rhs);
return boxInt(mod_i64_i64(rhs_int->n, lhs->n));
}
extern "C" Box* intDivmod(BoxedInt* lhs, Box* rhs) { extern "C" Box* intDivmod(BoxedInt* lhs, Box* rhs) {
if (!PyInt_Check(lhs)) if (!PyInt_Check(lhs))
raiseExcHelper(TypeError, "descriptor '__divmod__' requires a 'int' object but received a '%s'", raiseExcHelper(TypeError, "descriptor '__divmod__' requires a 'int' object but received a '%s'",
...@@ -637,6 +756,16 @@ extern "C" Box* intDivmod(BoxedInt* lhs, Box* rhs) { ...@@ -637,6 +756,16 @@ extern "C" Box* intDivmod(BoxedInt* lhs, Box* rhs) {
return createTuple(2, arg); return createTuple(2, arg);
} }
Box* intRDivmod(BoxedInt* lhs, Box* rhs) {
if (!PyInt_Check(lhs))
raiseExcHelper(TypeError, "descriptor '__rdivmod__' requires a 'int' object but received a '%s'",
getTypeName(lhs));
if (!PyInt_Check(rhs)) {
return NotImplemented;
}
return intDivmod(static_cast<BoxedInt*>(rhs), lhs);
}
extern "C" Box* intMulInt(BoxedInt* lhs, BoxedInt* rhs) { extern "C" Box* intMulInt(BoxedInt* lhs, BoxedInt* rhs) {
assert(PyInt_Check(lhs)); assert(PyInt_Check(lhs));
...@@ -665,6 +794,17 @@ extern "C" Box* intMul(BoxedInt* lhs, Box* rhs) { ...@@ -665,6 +794,17 @@ extern "C" Box* intMul(BoxedInt* lhs, Box* rhs) {
} }
} }
Box* intRMul(BoxedInt* lhs, Box* rhs) {
if (!PyInt_Check(lhs))
raiseExcHelper(TypeError, "descriptor '__rmul__' requires a 'int' object but received a '%s'",
getTypeName(lhs));
if (!PyInt_Check(rhs))
return NotImplemented;
return intMul(lhs, rhs);
}
static void _addFuncPow(const char* name, ConcreteCompilerType* rtn_type, void* float_func, void* int_func) { static void _addFuncPow(const char* name, ConcreteCompilerType* rtn_type, void* float_func, void* int_func) {
std::vector<ConcreteCompilerType*> v_ifu{ BOXED_INT, BOXED_FLOAT, UNKNOWN }; std::vector<ConcreteCompilerType*> v_ifu{ BOXED_INT, BOXED_FLOAT, UNKNOWN };
std::vector<ConcreteCompilerType*> v_uuu{ UNKNOWN, UNKNOWN, UNKNOWN }; std::vector<ConcreteCompilerType*> v_uuu{ UNKNOWN, UNKNOWN, UNKNOWN };
...@@ -704,17 +844,10 @@ extern "C" Box* intPow(BoxedInt* lhs, Box* rhs, Box* mod) { ...@@ -704,17 +844,10 @@ extern "C" Box* intPow(BoxedInt* lhs, Box* rhs, Box* mod) {
return NotImplemented; return NotImplemented;
BoxedInt* rhs_int = static_cast<BoxedInt*>(rhs); BoxedInt* rhs_int = static_cast<BoxedInt*>(rhs);
BoxedInt* mod_int = static_cast<BoxedInt*>(mod);
if (mod != None) { if (mod != None) {
if (rhs_int->n < 0) if (rhs_int->n < 0)
raiseExcHelper(TypeError, "pow() 2nd argument " raiseExcHelper(TypeError, "pow() 2nd argument "
"cannot be negative when 3rd argument specified"); "cannot be negative when 3rd argument specified");
if (!PyInt_Check(mod)) {
return NotImplemented;
} else if (mod_int->n == 0) {
raiseExcHelper(ValueError, "pow() 3rd argument cannot be 0");
}
} }
Box* rtn = pow_i64_i64(lhs->n, rhs_int->n, mod); Box* rtn = pow_i64_i64(lhs->n, rhs_int->n, mod);
...@@ -723,8 +856,29 @@ extern "C" Box* intPow(BoxedInt* lhs, Box* rhs, Box* mod) { ...@@ -723,8 +856,29 @@ extern "C" Box* intPow(BoxedInt* lhs, Box* rhs, Box* mod) {
return rtn; return rtn;
} }
extern "C" Box* intRShiftInt(BoxedInt* lhs, BoxedInt* rhs) { Box* intRPow(BoxedInt* lhs, Box* rhs, Box* mod) {
assert(PyInt_Check(lhs)); if (!PyInt_Check(lhs))
raiseExcHelper(TypeError, "descriptor '__rpow__' requires a 'int' object but received a '%s'",
getTypeName(lhs));
if (!PyInt_Check(rhs))
return NotImplemented;
BoxedInt* rhs_int = static_cast<BoxedInt*>(rhs);
if (mod != None) {
if (lhs->n < 0)
raiseExcHelper(TypeError, "pow() 2nd argument "
"cannot be negative when 3rd argument specified");
}
Box* rtn = pow_i64_i64(rhs_int->n, lhs->n, mod);
if (PyLong_Check(rtn))
return longInt(rtn);
return rtn;
}
Box* intRShiftInt(BoxedInt* lhs, BoxedInt* rhs) {
if (!PyInt_Check(lhs))
raiseExcHelper(TypeError, "descriptor '__rshift__' requires a 'int' object but received a '%s'",
getTypeName(lhs));
assert(PyInt_Check(rhs)); assert(PyInt_Check(rhs));
if (rhs->n < 0) if (rhs->n < 0)
...@@ -739,7 +893,7 @@ extern "C" Box* intRShift(BoxedInt* lhs, Box* rhs) { ...@@ -739,7 +893,7 @@ extern "C" Box* intRShift(BoxedInt* lhs, Box* rhs) {
getTypeName(lhs)); getTypeName(lhs));
if (rhs->cls == long_cls) if (rhs->cls == long_cls)
return longRshift(boxLong(lhs->n), rhs); return longRShiftLong(boxLong(lhs->n), rhs);
if (!PyInt_Check(rhs)) { if (!PyInt_Check(rhs)) {
return NotImplemented; return NotImplemented;
...@@ -748,6 +902,18 @@ extern "C" Box* intRShift(BoxedInt* lhs, Box* rhs) { ...@@ -748,6 +902,18 @@ extern "C" Box* intRShift(BoxedInt* lhs, Box* rhs) {
return intRShiftInt(lhs, rhs_int); return intRShiftInt(lhs, rhs_int);
} }
Box* intRRShift(BoxedInt* lhs, Box* rhs) {
if (!PyInt_Check(lhs))
raiseExcHelper(TypeError, "descriptor '__rrshift__' requires a 'int' object but received a '%s'",
getTypeName(lhs));
if (!PyInt_Check(rhs)) {
return NotImplemented;
}
BoxedInt* rhs_int = static_cast<BoxedInt*>(rhs);
return intRShiftInt(rhs_int, lhs);
}
extern "C" Box* intSubInt(BoxedInt* lhs, BoxedInt* rhs) { extern "C" Box* intSubInt(BoxedInt* lhs, BoxedInt* rhs) {
assert(PyInt_Check(lhs)); assert(PyInt_Check(lhs));
assert(PyInt_Check(rhs)); assert(PyInt_Check(rhs));
...@@ -775,6 +941,19 @@ extern "C" Box* intSub(BoxedInt* lhs, Box* rhs) { ...@@ -775,6 +941,19 @@ extern "C" Box* intSub(BoxedInt* lhs, Box* rhs) {
} }
} }
Box* intRSub(BoxedInt* lhs, Box* rhs) {
if (!PyInt_Check(lhs))
raiseExcHelper(TypeError, "descriptor '__rsub__' requires a 'int' object but received a '%s'",
getTypeName(lhs));
if (PyInt_Check(rhs)) {
BoxedInt* rhs_int = static_cast<BoxedInt*>(rhs);
return sub_i64_i64(rhs_int->n, lhs->n);
} else {
return NotImplemented;
}
}
extern "C" Box* intInvert(BoxedInt* v) { extern "C" Box* intInvert(BoxedInt* v) {
if (!PyInt_Check(v)) if (!PyInt_Check(v))
raiseExcHelper(TypeError, "descriptor '__invert__' requires a 'int' object but received a '%s'", raiseExcHelper(TypeError, "descriptor '__invert__' requires a 'int' object but received a '%s'",
...@@ -836,6 +1015,16 @@ extern "C" Box* intHash(BoxedInt* self) { ...@@ -836,6 +1015,16 @@ extern "C" Box* intHash(BoxedInt* self) {
return boxInt(self->n); return boxInt(self->n);
} }
Box* intAbs(BoxedInt* v) {
if (!PyInt_Check(v))
raiseExcHelper(TypeError, "descriptor '__abs__' requires a 'int' object but received a '%s'", getTypeName(v));
if (v->n == PYSTON_INT_MIN) {
return longNeg(boxLong(v->n));
}
return boxInt(std::abs(v->n));
}
extern "C" Box* intBin(BoxedInt* self) { extern "C" Box* intBin(BoxedInt* self) {
if (!PyInt_Check(self)) if (!PyInt_Check(self))
raiseExcHelper(TypeError, "descriptor '__bin__' requires a 'int' object but received a '%s'", raiseExcHelper(TypeError, "descriptor '__bin__' requires a 'int' object but received a '%s'",
...@@ -844,6 +1033,20 @@ extern "C" Box* intBin(BoxedInt* self) { ...@@ -844,6 +1033,20 @@ extern "C" Box* intBin(BoxedInt* self) {
return _PyInt_Format(reinterpret_cast<PyIntObject*>(self), 2, 0); return _PyInt_Format(reinterpret_cast<PyIntObject*>(self), 2, 0);
} }
Box* intCoerce(BoxedInt* lhs, Box* rhs) {
if (!PyInt_Check(lhs))
raiseExcHelper(TypeError, "descriptor '__coerce__' requires a 'int' object but received a '%s'",
getTypeName(lhs));
if (!PyInt_Check(rhs)) {
return NotImplemented;
}
BoxedInt* rhs_int = static_cast<BoxedInt*>(rhs);
return BoxedTuple::create({ lhs, rhs_int });
}
extern "C" Box* intHex(BoxedInt* self) { extern "C" Box* intHex(BoxedInt* self) {
if (!PyInt_Check(self)) if (!PyInt_Check(self))
raiseExcHelper(TypeError, "descriptor '__hex__' requires a 'int' object but received a '%s'", raiseExcHelper(TypeError, "descriptor '__hex__' requires a 'int' object but received a '%s'",
...@@ -902,6 +1105,14 @@ Box* intFloat(BoxedInt* self) { ...@@ -902,6 +1105,14 @@ Box* intFloat(BoxedInt* self) {
return boxFloat(self->n); return boxFloat(self->n);
} }
Box* intLong(BoxedInt* self) {
if (!PyInt_Check(self))
raiseExcHelper(TypeError, "descriptor '__long__' requires a 'int' object but received a '%s'",
getTypeName(self));
return boxLong(self->n);
}
extern "C" Box* intIndex(BoxedInt* v) { extern "C" Box* intIndex(BoxedInt* v) {
if (PyInt_CheckExact(v)) if (PyInt_CheckExact(v))
return v; return v;
...@@ -1167,6 +1378,23 @@ void setupInt() { ...@@ -1167,6 +1378,23 @@ void setupInt() {
_addFuncIntFloatUnknown("__mul__", (void*)intMulInt, (void*)intMulFloat, (void*)intMul); _addFuncIntFloatUnknown("__mul__", (void*)intMulInt, (void*)intMulFloat, (void*)intMul);
_addFuncIntUnknown("__mod__", BOXED_INT, (void*)intModInt, (void*)intMod); _addFuncIntUnknown("__mod__", BOXED_INT, (void*)intModInt, (void*)intMod);
_addFuncPow("__pow__", BOXED_INT, (void*)intPowFloat, (void*)intPow); _addFuncPow("__pow__", BOXED_INT, (void*)intPowFloat, (void*)intPow);
int_cls->giveAttr("__radd__", new BoxedFunction(FunctionMetadata::create((void*)intRAdd, UNKNOWN, 2)));
int_cls->giveAttr("__rand__", new BoxedFunction(FunctionMetadata::create((void*)intRAnd, UNKNOWN, 2)));
int_cls->giveAttr("__ror__", new BoxedFunction(FunctionMetadata::create((void*)intROr, UNKNOWN, 2)));
int_cls->giveAttr("__rxor__", new BoxedFunction(FunctionMetadata::create((void*)intRXor, UNKNOWN, 2)));
int_cls->giveAttr("__rsub__", new BoxedFunction(FunctionMetadata::create((void*)intRSub, UNKNOWN, 2)));
int_cls->giveAttr("__rmul__", new BoxedFunction(FunctionMetadata::create((void*)intRMul, UNKNOWN, 2)));
int_cls->giveAttr("__rdiv__", new BoxedFunction(FunctionMetadata::create((void*)intRDiv, UNKNOWN, 2)));
int_cls->giveAttr("__rfloordiv__", new BoxedFunction(FunctionMetadata::create((void*)intRFloordiv, UNKNOWN, 2)));
int_cls->giveAttr("__rtruediv__", new BoxedFunction(FunctionMetadata::create((void*)intRTruediv, UNKNOWN, 2)));
int_cls->giveAttr("__rmod__", new BoxedFunction(FunctionMetadata::create((void*)intRMod, UNKNOWN, 2)));
int_cls->giveAttr("__rdivmod__", new BoxedFunction(FunctionMetadata::create((void*)intRDivmod, UNKNOWN, 2)));
int_cls->giveAttr("__rpow__",
new BoxedFunction(FunctionMetadata::create((void*)intRPow, UNKNOWN, 3, false, false), { None }));
int_cls->giveAttr("__rrshift__", new BoxedFunction(FunctionMetadata::create((void*)intRRShift, UNKNOWN, 2)));
int_cls->giveAttr("__rlshift__", new BoxedFunction(FunctionMetadata::create((void*)intRLShift, UNKNOWN, 2)));
// Note: CPython implements int comparisons using tp_compare // Note: CPython implements int comparisons using tp_compare
int_cls->tp_richcompare = int_richcompare; int_cls->tp_richcompare = int_richcompare;
...@@ -1181,6 +1409,9 @@ void setupInt() { ...@@ -1181,6 +1409,9 @@ void setupInt() {
int_cls->tp_hash = (hashfunc)int_hash; int_cls->tp_hash = (hashfunc)int_hash;
int_cls->giveAttr("__divmod__", new BoxedFunction(FunctionMetadata::create((void*)intDivmod, UNKNOWN, 2))); int_cls->giveAttr("__divmod__", new BoxedFunction(FunctionMetadata::create((void*)intDivmod, UNKNOWN, 2)));
int_cls->giveAttr("__coerce__", new BoxedFunction(FunctionMetadata::create((void*)intCoerce, UNKNOWN, 2)));
int_cls->giveAttr("__abs__", new BoxedFunction(FunctionMetadata::create((void*)intAbs, UNKNOWN, 1)));
int_cls->giveAttr("__bin__", new BoxedFunction(FunctionMetadata::create((void*)intBin, STR, 1))); int_cls->giveAttr("__bin__", new BoxedFunction(FunctionMetadata::create((void*)intBin, STR, 1)));
int_cls->giveAttr("__hex__", new BoxedFunction(FunctionMetadata::create((void*)intHex, STR, 1))); int_cls->giveAttr("__hex__", new BoxedFunction(FunctionMetadata::create((void*)intHex, STR, 1)));
int_cls->giveAttr("__oct__", new BoxedFunction(FunctionMetadata::create((void*)intOct, STR, 1))); int_cls->giveAttr("__oct__", new BoxedFunction(FunctionMetadata::create((void*)intOct, STR, 1)));
...@@ -1189,6 +1420,23 @@ void setupInt() { ...@@ -1189,6 +1420,23 @@ void setupInt() {
int_cls->giveAttr("__index__", new BoxedFunction(FunctionMetadata::create((void*)intIndex, BOXED_INT, 1))); int_cls->giveAttr("__index__", new BoxedFunction(FunctionMetadata::create((void*)intIndex, BOXED_INT, 1)));
int_cls->giveAttr("__int__", new BoxedFunction(FunctionMetadata::create((void*)intInt, BOXED_INT, 1))); int_cls->giveAttr("__int__", new BoxedFunction(FunctionMetadata::create((void*)intInt, BOXED_INT, 1)));
int_cls->giveAttr("__float__", new BoxedFunction(FunctionMetadata::create((void*)intFloat, BOXED_FLOAT, 1))); int_cls->giveAttr("__float__", new BoxedFunction(FunctionMetadata::create((void*)intFloat, BOXED_FLOAT, 1)));
int_cls->giveAttr("__long__", new BoxedFunction(FunctionMetadata::create((void*)intLong, LONG, 1)));
int_cls->giveAttr("__doc__",
boxString("int(x=0) -> int or long\n"
"int(x, base=10) -> int or long\n"
"\n"
"Convert a number or string to an integer, or return 0 if no arguments\n"
"are given. If x is floating point, the conversion truncates towards zero.\n"
"If x is outside the integer range, the function returns a long instead.\n"
"\n"
"If x is not a number or if base is given, then x must be a string or\n"
"Unicode object representing an integer literal in the given base. The\n"
"literal can be preceded by '+' or '-' and be surrounded by whitespace.\n"
"The base defaults to 10. Valid bases are 0 and 2-36. Base 0 means to\n"
"interpret the base from the string as an integer literal.\n"
">>> int('0b100', base=0)\n"
"4"));
auto int_new = FunctionMetadata::create((void*)intNew<CXX>, UNKNOWN, 3, false, false, auto int_new = FunctionMetadata::create((void*)intNew<CXX>, UNKNOWN, 3, false, false,
ParamNames({ "", "x", "base" }, "", ""), CXX); ParamNames({ "", "x", "base" }, "", ""), CXX);
......
...@@ -781,11 +781,26 @@ Box* longInt(Box* v) { ...@@ -781,11 +781,26 @@ Box* longInt(Box* v) {
return new BoxedInt(n); return new BoxedInt(n);
} }
Box* longFloat(BoxedLong* v) { Box* longToLong(Box* self) {
if (!PyLong_Check(v)) if (self->cls == long_cls) {
raiseExcHelper(TypeError, "descriptor '__float__' requires a 'long' object but received a '%s'", return self;
getTypeName(v)); } else {
assert(PyLong_Check(self));
BoxedLong* l = new BoxedLong();
mpz_init_set(l->n, static_cast<BoxedLong*>(self)->n);
return l;
}
}
Box* longLong(BoxedLong* self) {
if (!PyLong_Check(self))
raiseExcHelper(TypeError, "descriptor '__long__' requires a 'int' object but received a '%s'",
getTypeName(self));
return longToLong(self);
}
Box* longToFloat(BoxedLong* v) {
double result = PyLong_AsDouble(v); double result = PyLong_AsDouble(v);
if (result == -1.0 && PyErr_Occurred()) if (result == -1.0 && PyErr_Occurred())
...@@ -794,6 +809,14 @@ Box* longFloat(BoxedLong* v) { ...@@ -794,6 +809,14 @@ Box* longFloat(BoxedLong* v) {
return new BoxedFloat(result); return new BoxedFloat(result);
} }
Box* longFloat(BoxedLong* v) {
if (!PyLong_Check(v))
raiseExcHelper(TypeError, "descriptor '__float__' requires a 'long' object but received a '%s'",
getTypeName(v));
return longToFloat(v);
}
Box* longRepr(BoxedLong* v) { Box* longRepr(BoxedLong* v) {
if (!PyLong_Check(v)) if (!PyLong_Check(v))
raiseExcHelper(TypeError, "descriptor '__repr__' requires a 'long' object but received a '%s'", getTypeName(v)); raiseExcHelper(TypeError, "descriptor '__repr__' requires a 'long' object but received a '%s'", getTypeName(v));
...@@ -977,64 +1000,116 @@ static PyObject* long_richcompare(Box* _v1, Box* _v2, int op) noexcept { ...@@ -977,64 +1000,116 @@ static PyObject* long_richcompare(Box* _v1, Box* _v2, int op) noexcept {
} }
} }
Box* longLshift(BoxedLong* v1, Box* _v2) { Box* convertToLong(Box* val) {
if (!PyLong_Check(v1)) if (PyLong_Check(val)) {
return val;
} else if (PyInt_Check(val)) {
BoxedInt* val_int = static_cast<BoxedInt*>(val);
BoxedLong* r = new BoxedLong();
mpz_init_set_si(r->n, val_int->n);
return r;
} else {
return NotImplemented;
}
}
Box* longLShiftLong(BoxedLong* lhs, Box* _rhs) {
Box* rhs = convertToLong(_rhs);
if (rhs == NotImplemented)
return NotImplemented;
BoxedLong* rhs_long = static_cast<BoxedLong*>(rhs);
// if (PyLong_Check(_v2)) {
// BoxedLong* v2 = static_cast<BoxedLong*>(_v2);
if (mpz_sgn(rhs_long->n) < 0)
raiseExcHelper(ValueError, "negative shift count");
uint64_t n = asUnsignedLong(rhs_long);
BoxedLong* r = new BoxedLong();
mpz_init(r->n);
mpz_mul_2exp(r->n, lhs->n, n);
return r;
}
Box* longLShift(BoxedLong* lhs, Box* rhs) {
if (!PyLong_Check(lhs))
raiseExcHelper(TypeError, "descriptor '__lshift__' requires a 'long' object but received a '%s'", raiseExcHelper(TypeError, "descriptor '__lshift__' requires a 'long' object but received a '%s'",
getTypeName(v1)); getTypeName(lhs));
if (PyLong_Check(_v2)) { return longLShiftLong(lhs, rhs);
BoxedLong* v2 = static_cast<BoxedLong*>(_v2); }
if (mpz_sgn(v2->n) < 0) Box* longRLShift(BoxedLong* lhs, Box* _rhs) {
raiseExcHelper(ValueError, "negative shift count"); if (!PyLong_Check(lhs))
raiseExcHelper(TypeError, "descriptor '__rlshift__' requires a 'long' object but received a '%s'",
getTypeName(lhs));
uint64_t n = asUnsignedLong(v2); Box* rhs = convertToLong(_rhs);
BoxedLong* r = new BoxedLong();
mpz_init(r->n);
mpz_mul_2exp(r->n, v1->n, n);
return r;
} else if (PyInt_Check(_v2)) {
BoxedInt* v2 = static_cast<BoxedInt*>(_v2);
if (v2->n < 0)
raiseExcHelper(ValueError, "negative shift count");
BoxedLong* r = new BoxedLong(); if (rhs == NotImplemented)
mpz_init(r->n);
mpz_mul_2exp(r->n, v1->n, v2->n);
return r;
} else {
return NotImplemented; return NotImplemented;
}
BoxedLong* rhs_long = static_cast<BoxedLong*>(rhs);
return longLShiftLong(rhs_long, lhs);
} }
Box* longRshift(BoxedLong* v1, Box* _v2) { Box* longRShiftLong(BoxedLong* lhs, Box* _rhs) {
if (!PyLong_Check(v1)) Box* rhs = convertToLong(_rhs);
if (rhs == NotImplemented)
return NotImplemented;
BoxedLong* rhs_long = static_cast<BoxedLong*>(rhs);
if (mpz_sgn(rhs_long->n) < 0)
raiseExcHelper(ValueError, "negative shift count");
uint64_t n = asUnsignedLong(rhs_long);
BoxedLong* r = new BoxedLong();
mpz_init(r->n);
mpz_div_2exp(r->n, lhs->n, n);
return r;
}
Box* longRShift(BoxedLong* lhs, Box* rhs) {
if (!PyLong_Check(lhs))
raiseExcHelper(TypeError, "descriptor '__rshift__' requires a 'long' object but received a '%s'", raiseExcHelper(TypeError, "descriptor '__rshift__' requires a 'long' object but received a '%s'",
getTypeName(v1)); getTypeName(lhs));
if (PyLong_Check(_v2)) { return longRShiftLong(lhs, rhs);
BoxedLong* v2 = static_cast<BoxedLong*>(_v2); }
Box* longRRShift(BoxedLong* lhs, Box* _rhs) {
if (!PyLong_Check(lhs))
raiseExcHelper(TypeError, "descriptor '__rrshift__' requires a 'long' object but received a '%s'",
getTypeName(lhs));
if (mpz_sgn(v2->n) < 0) Box* rhs = convertToLong(_rhs);
raiseExcHelper(ValueError, "negative shift count");
uint64_t n = asUnsignedLong(v2); if (rhs == NotImplemented)
BoxedLong* r = new BoxedLong(); return NotImplemented;
mpz_init(r->n);
mpz_div_2exp(r->n, v1->n, n);
return r;
} else if (PyInt_Check(_v2)) {
BoxedInt* v2 = static_cast<BoxedInt*>(_v2);
if (v2->n < 0)
raiseExcHelper(ValueError, "negative shift count");
BoxedLong* r = new BoxedLong(); BoxedLong* rhs_long = static_cast<BoxedLong*>(rhs);
mpz_init(r->n);
mpz_div_2exp(r->n, v1->n, v2->n); return longRShiftLong(rhs_long, lhs);
return r; }
} else {
Box* longCoerce(BoxedLong* lhs, Box* _rhs) {
if (!PyLong_Check(lhs))
raiseExcHelper(TypeError, "descriptor '__coerce__' requires a 'long' object but received a '%s'",
getTypeName(lhs));
Box* rhs = convertToLong(_rhs);
if (!PyLong_Check(rhs))
return NotImplemented; return NotImplemented;
}
BoxedLong* rhs_long = static_cast<BoxedLong*>(rhs);
return BoxedTuple::create({ lhs, rhs_long });
} }
Box* longSub(BoxedLong* v1, Box* _v2) { Box* longSub(BoxedLong* v1, Box* _v2) {
...@@ -1175,38 +1250,50 @@ Box* longRMod(BoxedLong* v1, Box* _v2) { ...@@ -1175,38 +1250,50 @@ Box* longRMod(BoxedLong* v1, Box* _v2) {
} }
} }
extern "C" Box* longDivmod(BoxedLong* lhs, Box* _rhs) { Box* longDivmodLong(BoxedLong* lhs, Box* _rhs) {
if (!PyLong_Check(lhs)) if (!PyLong_Check(lhs))
raiseExcHelper(TypeError, "descriptor '__div__' requires a 'long' object but received a '%s'", raiseExcHelper(TypeError, "descriptor '__div__' requires a 'long' object but received a '%s'",
getTypeName(lhs)); getTypeName(lhs));
if (PyLong_Check(_rhs)) { Box* rhs = convertToLong(_rhs);
BoxedLong* rhs = static_cast<BoxedLong*>(_rhs);
if (mpz_sgn(rhs->n) == 0) if (rhs == NotImplemented)
raiseExcHelper(ZeroDivisionError, "long division or modulo by zero"); return NotImplemented;
BoxedLong* q = new BoxedLong(); BoxedLong* rhs_long = static_cast<BoxedLong*>(rhs);
BoxedLong* r = new BoxedLong();
mpz_init(q->n);
mpz_init(r->n);
mpz_fdiv_qr(q->n, r->n, lhs->n, rhs->n);
return BoxedTuple::create({ q, r });
} else if (PyInt_Check(_rhs)) {
BoxedInt* rhs = static_cast<BoxedInt*>(_rhs);
if (rhs->n == 0) if (mpz_sgn(rhs_long->n) == 0)
raiseExcHelper(ZeroDivisionError, "long division or modulo by zero"); raiseExcHelper(ZeroDivisionError, "long division or modulo by zero");
BoxedLong* q = new BoxedLong(); BoxedLong* q = new BoxedLong();
BoxedLong* r = new BoxedLong(); BoxedLong* r = new BoxedLong();
mpz_init(q->n); mpz_init(q->n);
mpz_init_set_si(r->n, rhs->n); mpz_init(r->n);
mpz_fdiv_qr(q->n, r->n, lhs->n, r->n); mpz_fdiv_qr(q->n, r->n, lhs->n, rhs_long->n);
return BoxedTuple::create({ q, r }); return BoxedTuple::create({ q, r });
} else { }
Box* longDivmod(BoxedLong* lhs, Box* rhs) {
if (!PyLong_Check(lhs))
raiseExcHelper(TypeError, "descriptor '__div__' requires a 'long' object but received a '%s'",
getTypeName(lhs));
return longDivmodLong(lhs, rhs);
}
Box* longRDivmod(BoxedLong* lhs, Box* _rhs) {
if (!PyLong_Check(lhs))
raiseExcHelper(TypeError, "descriptor '__div__' requires a 'long' object but received a '%s'",
getTypeName(lhs));
Box* rhs = convertToLong(_rhs);
if (rhs == NotImplemented)
return NotImplemented; return NotImplemented;
}
BoxedLong* rhs_long = static_cast<BoxedLong*>(rhs);
return longDivmodLong(rhs_long, lhs);
} }
Box* longRdiv(BoxedLong* v1, Box* _v2) { Box* longRdiv(BoxedLong* v1, Box* _v2) {
...@@ -1322,32 +1409,26 @@ extern "C" Box* longPowFloat(BoxedLong* lhs, BoxedFloat* rhs) { ...@@ -1322,32 +1409,26 @@ extern "C" Box* longPowFloat(BoxedLong* lhs, BoxedFloat* rhs) {
return boxFloat(pow_float_float(lhs_float, rhs->d)); return boxFloat(pow_float_float(lhs_float, rhs->d));
} }
Box* longPow(BoxedLong* lhs, Box* rhs, Box* mod) { Box* longPowLong(BoxedLong* lhs, Box* _rhs, Box* _mod) {
if (!PyLong_Check(lhs))
raiseExcHelper(TypeError, "descriptor '__pow__' requires a 'long' object but received a '%s'",
getTypeName(lhs));
BoxedLong* mod_long = nullptr; BoxedLong* mod_long = nullptr;
if (mod != None) { if (_mod != None) {
if (PyLong_Check(mod)) { Box* mod = convertToLong(_mod);
mod_long = static_cast<BoxedLong*>(mod);
} else if (PyInt_Check(mod)) { if (mod == NotImplemented)
mod_long = boxLong(static_cast<BoxedInt*>(mod)->n);
} else {
return NotImplemented; return NotImplemented;
}
mod_long = static_cast<BoxedLong*>(mod);
} }
BoxedLong* rhs_long = nullptr; BoxedLong* rhs_long = nullptr;
if (PyLong_Check(rhs)) { Box* rhs = convertToLong(_rhs);
rhs_long = static_cast<BoxedLong*>(rhs);
} else if (PyInt_Check(rhs)) { if (rhs == NotImplemented)
rhs_long = boxLong(static_cast<BoxedInt*>(rhs)->n);
} else {
return NotImplemented; return NotImplemented;
}
if (mod != None) { rhs_long = static_cast<BoxedLong*>(rhs);
if (_mod != None) {
if (mpz_sgn(rhs_long->n) < 0) if (mpz_sgn(rhs_long->n) < 0)
raiseExcHelper(TypeError, "pow() 2nd argument " raiseExcHelper(TypeError, "pow() 2nd argument "
"cannot be negative when 3rd argument specified"); "cannot be negative when 3rd argument specified");
...@@ -1359,12 +1440,12 @@ Box* longPow(BoxedLong* lhs, Box* rhs, Box* mod) { ...@@ -1359,12 +1440,12 @@ Box* longPow(BoxedLong* lhs, Box* rhs, Box* mod) {
mpz_init(r->n); mpz_init(r->n);
if (mpz_sgn(rhs_long->n) == -1) { if (mpz_sgn(rhs_long->n) == -1) {
BoxedFloat* rhs_float = static_cast<BoxedFloat*>(longFloat(rhs_long)); BoxedFloat* rhs_float = static_cast<BoxedFloat*>(longToFloat(rhs_long));
BoxedFloat* lhs_float = static_cast<BoxedFloat*>(longFloat(lhs)); BoxedFloat* lhs_float = static_cast<BoxedFloat*>(longToFloat(lhs));
return boxFloat(pow_float_float(lhs_float->d, rhs_float->d)); return boxFloat(pow_float_float(lhs_float->d, rhs_float->d));
} }
if (mod != None) { if (_mod != None) {
mpz_powm(r->n, lhs->n, rhs_long->n, mod_long->n); mpz_powm(r->n, lhs->n, rhs_long->n, mod_long->n);
if (mpz_sgn(r->n) == 0) if (mpz_sgn(r->n) == 0)
return r; return r;
...@@ -1389,6 +1470,27 @@ Box* longPow(BoxedLong* lhs, Box* rhs, Box* mod) { ...@@ -1389,6 +1470,27 @@ Box* longPow(BoxedLong* lhs, Box* rhs, Box* mod) {
} }
return r; return r;
} }
Box* longPow(BoxedLong* lhs, Box* rhs, Box* mod) {
if (!PyLong_Check(lhs))
raiseExcHelper(TypeError, "descriptor '__pow__' requires a 'long' object but received a '%s'",
getTypeName(lhs));
return longPowLong(lhs, rhs, mod);
}
Box* longRPow(BoxedLong* lhs, Box* _rhs, Box* mod) {
if (!PyLong_Check(lhs))
raiseExcHelper(TypeError, "descriptor '__rpow__' requires a 'long' object but received a '%s'",
getTypeName(lhs));
Box* rhs = convertToLong(_rhs);
if (rhs == NotImplemented)
return NotImplemented;
BoxedLong* rhs_long = static_cast<BoxedLong*>(rhs);
return longPowLong(rhs_long, lhs, mod);
}
extern "C" Box* longInvert(BoxedLong* v) { extern "C" Box* longInvert(BoxedLong* v) {
if (!PyLong_Check(v)) if (!PyLong_Check(v))
...@@ -1517,15 +1619,8 @@ static PyObject* long_pow(PyObject* v, PyObject* w, PyObject* x) noexcept { ...@@ -1517,15 +1619,8 @@ static PyObject* long_pow(PyObject* v, PyObject* w, PyObject* x) noexcept {
} }
} }
static Box* longLong(Box* b, void*) { static Box* longDesc(Box* b, void*) {
if (b->cls == long_cls) { return longToLong(b);
return b;
} else {
assert(PyLong_Check(b));
BoxedLong* l = new BoxedLong();
mpz_init_set(l->n, static_cast<BoxedLong*>(b)->n);
return l;
}
} }
static Box* long0(Box* b, void*) { static Box* long0(Box* b, void*) {
...@@ -1547,6 +1642,8 @@ void setupLong() { ...@@ -1547,6 +1642,8 @@ void setupLong() {
mp_set_memory_functions(customised_allocation, customised_realloc, customised_free); mp_set_memory_functions(customised_allocation, customised_realloc, customised_free);
_addFuncPow("__pow__", UNKNOWN, (void*)longPowFloat, (void*)longPow); _addFuncPow("__pow__", UNKNOWN, (void*)longPowFloat, (void*)longPow);
long_cls->giveAttr(
"__rpow__", new BoxedFunction(FunctionMetadata::create((void*)longRPow, UNKNOWN, 3, false, false), { None }));
auto long_new = FunctionMetadata::create((void*)longNew<CXX>, UNKNOWN, 3, false, false, auto long_new = FunctionMetadata::create((void*)longNew<CXX>, UNKNOWN, 3, false, false,
ParamNames({ "", "x", "base" }, "", ""), CXX); ParamNames({ "", "x", "base" }, "", ""), CXX);
long_new->addVersion((void*)longNew<CAPI>, UNKNOWN, CAPI); long_new->addVersion((void*)longNew<CAPI>, UNKNOWN, CAPI);
...@@ -1565,6 +1662,7 @@ void setupLong() { ...@@ -1565,6 +1662,7 @@ void setupLong() {
long_cls->giveAttr("__rmod__", new BoxedFunction(FunctionMetadata::create((void*)longRMod, UNKNOWN, 2))); long_cls->giveAttr("__rmod__", new BoxedFunction(FunctionMetadata::create((void*)longRMod, UNKNOWN, 2)));
long_cls->giveAttr("__divmod__", new BoxedFunction(FunctionMetadata::create((void*)longDivmod, UNKNOWN, 2))); long_cls->giveAttr("__divmod__", new BoxedFunction(FunctionMetadata::create((void*)longDivmod, UNKNOWN, 2)));
long_cls->giveAttr("__rdivmod__", new BoxedFunction(FunctionMetadata::create((void*)longRDivmod, UNKNOWN, 2)));
long_cls->giveAttr("__sub__", new BoxedFunction(FunctionMetadata::create((void*)longSub, UNKNOWN, 2))); long_cls->giveAttr("__sub__", new BoxedFunction(FunctionMetadata::create((void*)longSub, UNKNOWN, 2)));
long_cls->giveAttr("__rsub__", new BoxedFunction(FunctionMetadata::create((void*)longRsub, UNKNOWN, 2))); long_cls->giveAttr("__rsub__", new BoxedFunction(FunctionMetadata::create((void*)longRsub, UNKNOWN, 2)));
...@@ -1581,8 +1679,11 @@ void setupLong() { ...@@ -1581,8 +1679,11 @@ void setupLong() {
// Note: CPython implements long comparisons using tp_compare // Note: CPython implements long comparisons using tp_compare
long_cls->tp_richcompare = long_richcompare; long_cls->tp_richcompare = long_richcompare;
long_cls->giveAttr("__lshift__", new BoxedFunction(FunctionMetadata::create((void*)longLshift, UNKNOWN, 2))); long_cls->giveAttr("__lshift__", new BoxedFunction(FunctionMetadata::create((void*)longLShift, UNKNOWN, 2)));
long_cls->giveAttr("__rshift__", new BoxedFunction(FunctionMetadata::create((void*)longRshift, UNKNOWN, 2))); long_cls->giveAttr("__rlshift__", new BoxedFunction(FunctionMetadata::create((void*)longRLShift, UNKNOWN, 2)));
long_cls->giveAttr("__rshift__", new BoxedFunction(FunctionMetadata::create((void*)longRShift, UNKNOWN, 2)));
long_cls->giveAttr("__rrshift__", new BoxedFunction(FunctionMetadata::create((void*)longRRShift, UNKNOWN, 2)));
long_cls->giveAttr("__coerce__", new BoxedFunction(FunctionMetadata::create((void*)longCoerce, UNKNOWN, 2)));
long_cls->giveAttr("__int__", new BoxedFunction(FunctionMetadata::create((void*)longInt, UNKNOWN, 1))); long_cls->giveAttr("__int__", new BoxedFunction(FunctionMetadata::create((void*)longInt, UNKNOWN, 1)));
long_cls->giveAttr("__float__", new BoxedFunction(FunctionMetadata::create((void*)longFloat, UNKNOWN, 1))); long_cls->giveAttr("__float__", new BoxedFunction(FunctionMetadata::create((void*)longFloat, UNKNOWN, 1)));
...@@ -1592,25 +1693,35 @@ void setupLong() { ...@@ -1592,25 +1693,35 @@ void setupLong() {
long_cls->giveAttr("__hex__", new BoxedFunction(FunctionMetadata::create((void*)longHex, STR, 1))); long_cls->giveAttr("__hex__", new BoxedFunction(FunctionMetadata::create((void*)longHex, STR, 1)));
long_cls->giveAttr("__oct__", new BoxedFunction(FunctionMetadata::create((void*)longOct, STR, 1))); long_cls->giveAttr("__oct__", new BoxedFunction(FunctionMetadata::create((void*)longOct, STR, 1)));
long_cls->giveAttr("__abs__", new BoxedFunction(FunctionMetadata::create((void*)longAbs, UNKNOWN, 1)));
long_cls->giveAttr("__invert__", new BoxedFunction(FunctionMetadata::create((void*)longInvert, UNKNOWN, 1))); long_cls->giveAttr("__invert__", new BoxedFunction(FunctionMetadata::create((void*)longInvert, UNKNOWN, 1)));
long_cls->giveAttr("__neg__", new BoxedFunction(FunctionMetadata::create((void*)longNeg, UNKNOWN, 1))); long_cls->giveAttr("__neg__", new BoxedFunction(FunctionMetadata::create((void*)longNeg, UNKNOWN, 1)));
long_cls->giveAttr("__pos__", new BoxedFunction(FunctionMetadata::create((void*)longPos, UNKNOWN, 1))); long_cls->giveAttr("__pos__", new BoxedFunction(FunctionMetadata::create((void*)longPos, UNKNOWN, 1)));
long_cls->giveAttr("__nonzero__", new BoxedFunction(FunctionMetadata::create((void*)longNonzero, BOXED_BOOL, 1))); long_cls->giveAttr("__nonzero__", new BoxedFunction(FunctionMetadata::create((void*)longNonzero, BOXED_BOOL, 1)));
long_cls->giveAttr("__hash__", new BoxedFunction(FunctionMetadata::create((void*)longHash, BOXED_INT, 1))); long_cls->giveAttr("__hash__", new BoxedFunction(FunctionMetadata::create((void*)longHash, BOXED_INT, 1)));
long_cls->giveAttr("__long__", new BoxedFunction(FunctionMetadata::create((void*)longLong, UNKNOWN, 1)));
long_cls->giveAttr("__trunc__", new BoxedFunction(FunctionMetadata::create((void*)longTrunc, UNKNOWN, 1))); long_cls->giveAttr("__trunc__", new BoxedFunction(FunctionMetadata::create((void*)longTrunc, UNKNOWN, 1)));
long_cls->giveAttr("__index__", new BoxedFunction(FunctionMetadata::create((void*)longIndex, LONG, 1))); long_cls->giveAttr("__index__", new BoxedFunction(FunctionMetadata::create((void*)longIndex, LONG, 1)));
long_cls->giveAttr("bit_length", new BoxedFunction(FunctionMetadata::create((void*)longBitLength, LONG, 1))); long_cls->giveAttr("bit_length", new BoxedFunction(FunctionMetadata::create((void*)longBitLength, LONG, 1)));
long_cls->giveAttr("real", new (pyston_getset_cls) BoxedGetsetDescriptor(longLong, NULL, NULL)); long_cls->giveAttr("real", new (pyston_getset_cls) BoxedGetsetDescriptor(longDesc, NULL, NULL));
long_cls->giveAttr("imag", new (pyston_getset_cls) BoxedGetsetDescriptor(long0, NULL, NULL)); long_cls->giveAttr("imag", new (pyston_getset_cls) BoxedGetsetDescriptor(long0, NULL, NULL));
long_cls->giveAttr("conjugate", new BoxedFunction(FunctionMetadata::create((void*)longLong, UNKNOWN, 1))); long_cls->giveAttr("conjugate", new BoxedFunction(FunctionMetadata::create((void*)longDesc, UNKNOWN, 1)));
long_cls->giveAttr("numerator", new (pyston_getset_cls) BoxedGetsetDescriptor(longLong, NULL, NULL)); long_cls->giveAttr("numerator", new (pyston_getset_cls) BoxedGetsetDescriptor(longDesc, NULL, NULL));
long_cls->giveAttr("denominator", new (pyston_getset_cls) BoxedGetsetDescriptor(long1, NULL, NULL)); long_cls->giveAttr("denominator", new (pyston_getset_cls) BoxedGetsetDescriptor(long1, NULL, NULL));
long_cls->giveAttr("__getnewargs__", new BoxedFunction(FunctionMetadata::create((void*)long_getnewargs, UNKNOWN, 1, long_cls->giveAttr("__getnewargs__", new BoxedFunction(FunctionMetadata::create((void*)long_getnewargs, UNKNOWN, 1,
ParamNames::empty(), CAPI))); ParamNames::empty(), CAPI)));
long_cls->giveAttr("__doc__", boxString("long.bit_length() -> int or long\n"
"\n"
"Number of bits necessary to represent self in binary.\n"
">>> bin(37L)\n"
"'0b100101'\n"
">>> (37L).bit_length()\n"
"6"));
add_operators(long_cls); add_operators(long_cls);
long_cls->freeze(); long_cls->freeze();
......
...@@ -51,8 +51,8 @@ Box* longSub(BoxedLong* lhs, Box* rhs); ...@@ -51,8 +51,8 @@ Box* longSub(BoxedLong* lhs, Box* rhs);
Box* longMul(BoxedLong* lhs, Box* rhs); Box* longMul(BoxedLong* lhs, Box* rhs);
Box* longDiv(BoxedLong* lhs, Box* rhs); Box* longDiv(BoxedLong* lhs, Box* rhs);
Box* longPow(BoxedLong* lhs, Box* rhs, Box* mod = None); Box* longPow(BoxedLong* lhs, Box* rhs, Box* mod = None);
Box* longLshift(BoxedLong* lhs, Box* rhs); Box* longLShiftLong(BoxedLong* lhs, Box* _rhs);
Box* longRshift(BoxedLong* lhs, Box* rhs); Box* longRShiftLong(BoxedLong* lhs, Box* _rhs);
Box* longHex(BoxedLong* v); Box* longHex(BoxedLong* v);
Box* longOct(BoxedLong* v); Box* longOct(BoxedLong* v);
......
...@@ -111,3 +111,29 @@ print sys.float_info ...@@ -111,3 +111,29 @@ print sys.float_info
if 1: if 1:
x = -2.0 x = -2.0
print(float.__long__(sys.float_info.max))
print(float.__int__(sys.float_info.max))
data = ["-1.0", "0.0", "1.0",
"5.0", "-5.0",
"5", "5L", "0L", "5+5j",
"\"5\"", "None",
]
operations = ["__rpow__",
"__ridv__",
"__divmod__", "__rdivmod__",
"__rtruediv__",
"__coerce__"
]
for x in data:
for y in data:
for operation in operations:
try:
print(eval("float.{op}({arg1}, {arg2})".format(op=operation,
arg1=x,
arg2=y)))
except Exception as e:
print(e.message)
...@@ -178,3 +178,53 @@ if sys.version_info >= (2, 7, 6): ...@@ -178,3 +178,53 @@ if sys.version_info >= (2, 7, 6):
print(e.message) print(e.message)
else: else:
print("int() missing string argument") print("int() missing string argument")
pow_test_data = [42, 3, 3L, 4.5, "x", 0, -42, None]
for rhs in pow_test_data:
for lhs in pow_test_data:
for mod in pow_test_data:
try:
print(int.__rpow__(rhs, lhs, mod))
except Exception as e:
print(e.message)
unary_test_data = [-42, -0, 0, 42, max_int, min_int]
for i in unary_test_data:
print(int.__abs__(i))
print(int.__long__(i))
print(int.__float__(i))
data = ["-1", "0", "1",
"5", "-5",
"5.0", "5L", "0L", "5+5j", "0.0",
"\"5\"", "None",
]
operations = ["__radd__",
"__rand__",
"__ror__",
"__rxor__",
"__rsub__",
"__rmul__",
"__rdiv__",
"__rfloordiv__",
"__rpow__",
"__rmod__",
"__rdivmod__",
"__rtruediv__",
"__rrshift__",
"__rlshift__",
"__coerce__",
]
for x in data:
for y in data:
for operation in operations:
try:
print(eval("int.{op}({arg1}, {arg2})".format(op=operation,
arg1=x,
arg2=y)))
except Exception as e:
print(e.message)
...@@ -162,3 +162,43 @@ for i in range(-10, 10): ...@@ -162,3 +162,43 @@ for i in range(-10, 10):
for i in xrange(100): for i in xrange(100):
for j in xrange(100): for j in xrange(100):
print i, j, hash((1 << i) - (1 << j)) print i, j, hash((1 << i) - (1 << j))
pow_test_data = [42L, 3, 4.5, "x", 0, -42, None]
for rhs in pow_test_data:
for lhs in pow_test_data:
for mod in pow_test_data:
try:
print(long.__rpow__(rhs, lhs, mod))
except Exception as e:
print(e.message)
unary_test_data = [-42, -0, 0, 42]
for i in unary_test_data:
print(int.__abs__(i))
print(int.__long__(i))
data = ["-1L", "0L", "1L",
"42L", "-42L",
"42.0", "5", "0", "5+5j", "0.0",
"\"42\"", "None",
]
operations = ["__rpow__",
"__rshift__",
"__lshift__",
"__rrshift__",
"__rlshift__",
"__coerce__",
]
for x in data:
for y in data:
for operation in operations:
try:
print(eval("long.{op}({arg1}, {arg2})".format(op=operation,
arg1=x,
arg2=y)))
except Exception as e:
print(e.message)
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