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)
return PyFloat_FromDouble(mod);
}
static PyObject *
// pyston change: make this not static
PyObject *
float_divmod(PyObject *v, PyObject *w)
{
double vx, wx;
......@@ -987,7 +988,8 @@ float_nonzero(PyFloatObject *v)
return v->ob_fval != 0.0;
}
static int
// pyston change: make not static
int
float_coerce(PyObject **pv, PyObject **pw)
{
if (PyInt_Check(*pw)) {
......@@ -1949,7 +1951,8 @@ PyDoc_STRVAR(float_getformat_doc,
"'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.");
static PyObject *
// pyston change: make not static
PyObject *
float_setformat(PyTypeObject *v, PyObject* args)
{
char* typestr;
......
......@@ -27,11 +27,14 @@
#include "runtime/types.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_fromhex(PyObject* cls, PyObject* arg) 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__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_str(PyObject* v) 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) {
if (rhs_f == -1.0 && PyErr_Occurred()) {
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);
} else {
return NotImplemented;
......@@ -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) {
Box* res = float_pow(lhs, rhs, mod);
if (!res) {
......@@ -653,6 +702,18 @@ extern "C" Box* floatPowInt(BoxedFloat* lhs, BoxedInt* rhs, Box* mod = None) {
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) {
double res;
int err = float_pow_unboxed(lhs, rhs, &res);
......@@ -862,7 +923,10 @@ template <ExceptionStyle S> static BoxedFloat* _floatNew(Box* a) noexcept(S == C
} else if (PyLong_Check(a)) {
double a_f = PyLong_AsDouble(a);
if (a_f == -1.0 && PyErr_Occurred()) {
throwCAPIException();
if (S == CAPI)
return NULL;
else
throwCAPIException();
}
return new BoxedFloat(a_f);
} else if (a->cls == str_cls || a->cls == unicode_cls) {
......@@ -968,11 +1032,7 @@ Box* floatRepr(BoxedFloat* self) {
return float_str_or_repr(self->d, 0, 'r');
}
Box* floatTrunc(BoxedFloat* self) {
if (!PyFloat_Check(self))
raiseExcHelper(TypeError, "descriptor '__trunc__' requires a 'float' object but received a '%s'",
getTypeName(self));
Box* floatToInt(BoxedFloat* self) {
double wholepart; /* integral portion of x, rounded toward 0 */
(void)modf(self->d, &wholepart);
......@@ -998,6 +1058,45 @@ Box* floatTrunc(BoxedFloat* self) {
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) {
if (!PyFloat_Check(self))
raiseExcHelper(TypeError, "descriptor '__hash__' requires a 'float' object but received a '%s'",
......@@ -1577,12 +1676,25 @@ static PyObject* float_getnewargs(PyFloatObject* v) noexcept {
return Py_BuildValue("(d)", v->ob_fval);
}
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 },
{ "is_integer", (PyCFunction)float_is_integer, METH_NOARGS, NULL },
{ "__format__", (PyCFunction)float__format__, METH_VARARGS, NULL } };
PyDoc_STRVAR(float_setformat_doc, "float.__setformat__(typestr, fmt) -> None\n"
"\n"
"You probably don't want to use this function. It exists mainly to be\n"
"used in Python's test suite.\n"
"\n"
"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() {
static PyNumberMethods float_as_number;
......@@ -1600,6 +1712,7 @@ void setupFloat() {
float_cls->giveAttr("__rfloordiv__",
new BoxedFunction(FunctionMetadata::create((void*)floatRFloorDiv, BOXED_FLOAT, 2)));
_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("__rmod__", BOXED_FLOAT, (void*)floatRModFloat, (void*)floatRModInt, (void*)floatRMod);
......@@ -1607,8 +1720,11 @@ void setupFloat() {
float_cls->giveAttr("__rmul__", float_cls->getattr(internStringMortal("__mul__")));
_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("__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);
float_new->addVersion((void*)floatNew<CAPI>, UNKNOWN, CAPI);
......@@ -1632,8 +1748,11 @@ void setupFloat() {
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("__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("__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("real", new (pyston_getset_cls) BoxedGetsetDescriptor(floatConjugate, NULL, NULL));
......@@ -1641,6 +1760,9 @@ void setupFloat() {
float_cls->giveAttr("conjugate",
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__",
new BoxedBuiltinFunctionOrMethod(FunctionMetadata::create((void*)floatGetFormat, STR, 1),
"__getformat__", floatGetFormatDoc));
......
......@@ -149,9 +149,17 @@ Box* getFrame(int depth) {
return BoxedFrame::boxFrame(std::move(it));
}
extern "C" int PyFrame_GetLineNumber(PyFrameObject* f) noexcept {
BoxedInt* lineno = (BoxedInt*)BoxedFrame::lineno((Box*)f, NULL);
return lineno->n;
extern "C" int PyFrame_GetLineNumber(PyFrameObject* _f) noexcept {
// TODO remove this when we are able to introspect exited frames:
// 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 {
......
......@@ -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) {
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 rtn = 1, curpow = lhs;
......@@ -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) {
assert(PyInt_Check(lhs));
assert(PyInt_Check(rhs));
......@@ -441,6 +464,18 @@ extern "C" Box* intAnd(BoxedInt* lhs, Box* rhs) {
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) {
assert(PyInt_Check(lhs));
assert(PyInt_Check(rhs));
......@@ -458,6 +493,17 @@ extern "C" Box* intOr(BoxedInt* lhs, Box* rhs) {
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) {
assert(PyInt_Check(lhs));
assert(PyInt_Check(rhs));
......@@ -475,6 +521,18 @@ extern "C" Box* intXor(BoxedInt* lhs, Box* rhs) {
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) {
assert(PyInt_Check(lhs));
assert(PyInt_Check(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) {
assert(PyInt_Check(lhs));
assert(PyInt_Check(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) {
assert(PyInt_Check(lhs));
assert(PyInt_Check(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) {
assert(PyInt_Check(lhs));
assert(PyInt_Check(rhs));
......@@ -581,7 +675,7 @@ extern "C" Box* intLShiftInt(BoxedInt* lhs, BoxedInt* rhs) {
if ((res >> rhs->n) == lhs->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) {
......@@ -590,7 +684,7 @@ extern "C" Box* intLShift(BoxedInt* lhs, Box* rhs) {
getTypeName(lhs));
if (rhs->cls == long_cls)
return longLshift(boxLong(lhs->n), rhs);
return longLShiftLong(boxLong(lhs->n), rhs);
if (!PyInt_Check(rhs)) {
return NotImplemented;
......@@ -599,6 +693,19 @@ extern "C" Box* intLShift(BoxedInt* lhs, Box* rhs) {
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) {
assert(PyInt_Check(lhs));
assert(PyInt_Check(rhs));
......@@ -616,6 +723,18 @@ extern "C" Box* intMod(BoxedInt* lhs, Box* rhs) {
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) {
if (!PyInt_Check(lhs))
raiseExcHelper(TypeError, "descriptor '__divmod__' requires a 'int' object but received a '%s'",
......@@ -637,6 +756,16 @@ extern "C" Box* intDivmod(BoxedInt* lhs, Box* rhs) {
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) {
assert(PyInt_Check(lhs));
......@@ -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) {
std::vector<ConcreteCompilerType*> v_ifu{ BOXED_INT, BOXED_FLOAT, UNKNOWN };
std::vector<ConcreteCompilerType*> v_uuu{ UNKNOWN, UNKNOWN, UNKNOWN };
......@@ -704,17 +844,10 @@ extern "C" Box* intPow(BoxedInt* lhs, Box* rhs, Box* mod) {
return NotImplemented;
BoxedInt* rhs_int = static_cast<BoxedInt*>(rhs);
BoxedInt* mod_int = static_cast<BoxedInt*>(mod);
if (mod != None) {
if (rhs_int->n < 0)
raiseExcHelper(TypeError, "pow() 2nd argument "
"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);
......@@ -723,8 +856,29 @@ extern "C" Box* intPow(BoxedInt* lhs, Box* rhs, Box* mod) {
return rtn;
}
extern "C" Box* intRShiftInt(BoxedInt* lhs, BoxedInt* rhs) {
assert(PyInt_Check(lhs));
Box* intRPow(BoxedInt* lhs, Box* rhs, Box* mod) {
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));
if (rhs->n < 0)
......@@ -739,7 +893,7 @@ extern "C" Box* intRShift(BoxedInt* lhs, Box* rhs) {
getTypeName(lhs));
if (rhs->cls == long_cls)
return longRshift(boxLong(lhs->n), rhs);
return longRShiftLong(boxLong(lhs->n), rhs);
if (!PyInt_Check(rhs)) {
return NotImplemented;
......@@ -748,6 +902,18 @@ extern "C" Box* intRShift(BoxedInt* lhs, Box* rhs) {
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) {
assert(PyInt_Check(lhs));
assert(PyInt_Check(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) {
if (!PyInt_Check(v))
raiseExcHelper(TypeError, "descriptor '__invert__' requires a 'int' object but received a '%s'",
......@@ -836,6 +1015,16 @@ extern "C" Box* intHash(BoxedInt* self) {
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) {
if (!PyInt_Check(self))
raiseExcHelper(TypeError, "descriptor '__bin__' requires a 'int' object but received a '%s'",
......@@ -844,6 +1033,20 @@ extern "C" Box* intBin(BoxedInt* self) {
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) {
if (!PyInt_Check(self))
raiseExcHelper(TypeError, "descriptor '__hex__' requires a 'int' object but received a '%s'",
......@@ -902,6 +1105,14 @@ Box* intFloat(BoxedInt* self) {
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) {
if (PyInt_CheckExact(v))
return v;
......@@ -1167,6 +1378,23 @@ void setupInt() {
_addFuncIntFloatUnknown("__mul__", (void*)intMulInt, (void*)intMulFloat, (void*)intMul);
_addFuncIntUnknown("__mod__", BOXED_INT, (void*)intModInt, (void*)intMod);
_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
int_cls->tp_richcompare = int_richcompare;
......@@ -1181,6 +1409,9 @@ void setupInt() {
int_cls->tp_hash = (hashfunc)int_hash;
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("__hex__", new BoxedFunction(FunctionMetadata::create((void*)intHex, STR, 1)));
int_cls->giveAttr("__oct__", new BoxedFunction(FunctionMetadata::create((void*)intOct, STR, 1)));
......@@ -1189,6 +1420,23 @@ void setupInt() {
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("__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,
ParamNames({ "", "x", "base" }, "", ""), CXX);
......
......@@ -781,11 +781,26 @@ Box* longInt(Box* v) {
return new BoxedInt(n);
}
Box* longFloat(BoxedLong* v) {
if (!PyLong_Check(v))
raiseExcHelper(TypeError, "descriptor '__float__' requires a 'long' object but received a '%s'",
getTypeName(v));
Box* longToLong(Box* self) {
if (self->cls == long_cls) {
return self;
} 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);
if (result == -1.0 && PyErr_Occurred())
......@@ -794,6 +809,14 @@ Box* longFloat(BoxedLong* v) {
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) {
if (!PyLong_Check(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 {
}
}
Box* longLshift(BoxedLong* v1, Box* _v2) {
if (!PyLong_Check(v1))
Box* convertToLong(Box* val) {
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'",
getTypeName(v1));
getTypeName(lhs));
if (PyLong_Check(_v2)) {
BoxedLong* v2 = static_cast<BoxedLong*>(_v2);
return longLShiftLong(lhs, rhs);
}
if (mpz_sgn(v2->n) < 0)
raiseExcHelper(ValueError, "negative shift count");
Box* longRLShift(BoxedLong* lhs, Box* _rhs) {
if (!PyLong_Check(lhs))
raiseExcHelper(TypeError, "descriptor '__rlshift__' requires a 'long' object but received a '%s'",
getTypeName(lhs));
uint64_t n = asUnsignedLong(v2);
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");
Box* rhs = convertToLong(_rhs);
BoxedLong* r = new BoxedLong();
mpz_init(r->n);
mpz_mul_2exp(r->n, v1->n, v2->n);
return r;
} else {
if (rhs == NotImplemented)
return NotImplemented;
}
BoxedLong* rhs_long = static_cast<BoxedLong*>(rhs);
return longLShiftLong(rhs_long, lhs);
}
Box* longRshift(BoxedLong* v1, Box* _v2) {
if (!PyLong_Check(v1))
Box* longRShiftLong(BoxedLong* lhs, Box* _rhs) {
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'",
getTypeName(v1));
getTypeName(lhs));
if (PyLong_Check(_v2)) {
BoxedLong* v2 = static_cast<BoxedLong*>(_v2);
return longRShiftLong(lhs, rhs);
}
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)
raiseExcHelper(ValueError, "negative shift count");
Box* rhs = convertToLong(_rhs);
uint64_t n = asUnsignedLong(v2);
BoxedLong* r = new BoxedLong();
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");
if (rhs == NotImplemented)
return NotImplemented;
BoxedLong* r = new BoxedLong();
mpz_init(r->n);
mpz_div_2exp(r->n, v1->n, v2->n);
return r;
} else {
BoxedLong* rhs_long = static_cast<BoxedLong*>(rhs);
return longRShiftLong(rhs_long, lhs);
}
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;
}
BoxedLong* rhs_long = static_cast<BoxedLong*>(rhs);
return BoxedTuple::create({ lhs, rhs_long });
}
Box* longSub(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))
raiseExcHelper(TypeError, "descriptor '__div__' requires a 'long' object but received a '%s'",
getTypeName(lhs));
if (PyLong_Check(_rhs)) {
BoxedLong* rhs = static_cast<BoxedLong*>(_rhs);
Box* rhs = convertToLong(_rhs);
if (mpz_sgn(rhs->n) == 0)
raiseExcHelper(ZeroDivisionError, "long division or modulo by zero");
if (rhs == NotImplemented)
return NotImplemented;
BoxedLong* q = new BoxedLong();
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);
BoxedLong* rhs_long = static_cast<BoxedLong*>(rhs);
if (rhs->n == 0)
raiseExcHelper(ZeroDivisionError, "long division or modulo by zero");
if (mpz_sgn(rhs_long->n) == 0)
raiseExcHelper(ZeroDivisionError, "long division or modulo by zero");
BoxedLong* q = new BoxedLong();
BoxedLong* r = new BoxedLong();
mpz_init(q->n);
mpz_init_set_si(r->n, rhs->n);
mpz_fdiv_qr(q->n, r->n, lhs->n, r->n);
return BoxedTuple::create({ q, r });
} else {
BoxedLong* q = new BoxedLong();
BoxedLong* r = new BoxedLong();
mpz_init(q->n);
mpz_init(r->n);
mpz_fdiv_qr(q->n, r->n, lhs->n, rhs_long->n);
return BoxedTuple::create({ q, r });
}
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;
}
BoxedLong* rhs_long = static_cast<BoxedLong*>(rhs);
return longDivmodLong(rhs_long, lhs);
}
Box* longRdiv(BoxedLong* v1, Box* _v2) {
......@@ -1322,32 +1409,26 @@ extern "C" Box* longPowFloat(BoxedLong* lhs, BoxedFloat* rhs) {
return boxFloat(pow_float_float(lhs_float, rhs->d));
}
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));
Box* longPowLong(BoxedLong* lhs, Box* _rhs, Box* _mod) {
BoxedLong* mod_long = nullptr;
if (mod != None) {
if (PyLong_Check(mod)) {
mod_long = static_cast<BoxedLong*>(mod);
} else if (PyInt_Check(mod)) {
mod_long = boxLong(static_cast<BoxedInt*>(mod)->n);
} else {
if (_mod != None) {
Box* mod = convertToLong(_mod);
if (mod == NotImplemented)
return NotImplemented;
}
mod_long = static_cast<BoxedLong*>(mod);
}
BoxedLong* rhs_long = nullptr;
if (PyLong_Check(rhs)) {
rhs_long = static_cast<BoxedLong*>(rhs);
} else if (PyInt_Check(rhs)) {
rhs_long = boxLong(static_cast<BoxedInt*>(rhs)->n);
} else {
Box* rhs = convertToLong(_rhs);
if (rhs == NotImplemented)
return NotImplemented;
}
if (mod != None) {
rhs_long = static_cast<BoxedLong*>(rhs);
if (_mod != None) {
if (mpz_sgn(rhs_long->n) < 0)
raiseExcHelper(TypeError, "pow() 2nd argument "
"cannot be negative when 3rd argument specified");
......@@ -1359,12 +1440,12 @@ Box* longPow(BoxedLong* lhs, Box* rhs, Box* mod) {
mpz_init(r->n);
if (mpz_sgn(rhs_long->n) == -1) {
BoxedFloat* rhs_float = static_cast<BoxedFloat*>(longFloat(rhs_long));
BoxedFloat* lhs_float = static_cast<BoxedFloat*>(longFloat(lhs));
BoxedFloat* rhs_float = static_cast<BoxedFloat*>(longToFloat(rhs_long));
BoxedFloat* lhs_float = static_cast<BoxedFloat*>(longToFloat(lhs));
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);
if (mpz_sgn(r->n) == 0)
return r;
......@@ -1389,6 +1470,27 @@ Box* longPow(BoxedLong* lhs, Box* rhs, Box* mod) {
}
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) {
if (!PyLong_Check(v))
......@@ -1517,15 +1619,8 @@ static PyObject* long_pow(PyObject* v, PyObject* w, PyObject* x) noexcept {
}
}
static Box* longLong(Box* b, void*) {
if (b->cls == long_cls) {
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* longDesc(Box* b, void*) {
return longToLong(b);
}
static Box* long0(Box* b, void*) {
......@@ -1547,6 +1642,8 @@ void setupLong() {
mp_set_memory_functions(customised_allocation, customised_realloc, customised_free);
_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,
ParamNames({ "", "x", "base" }, "", ""), CXX);
long_new->addVersion((void*)longNew<CAPI>, UNKNOWN, CAPI);
......@@ -1565,6 +1662,7 @@ void setupLong() {
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("__rdivmod__", new BoxedFunction(FunctionMetadata::create((void*)longRDivmod, 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)));
......@@ -1581,8 +1679,11 @@ void setupLong() {
// Note: CPython implements long comparisons using tp_compare
long_cls->tp_richcompare = long_richcompare;
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("__lshift__", new BoxedFunction(FunctionMetadata::create((void*)longLShift, 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("__float__", new BoxedFunction(FunctionMetadata::create((void*)longFloat, UNKNOWN, 1)));
......@@ -1592,25 +1693,35 @@ void setupLong() {
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("__abs__", new BoxedFunction(FunctionMetadata::create((void*)longAbs, 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("__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("__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("__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("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("conjugate", new BoxedFunction(FunctionMetadata::create((void*)longLong, UNKNOWN, 1)));
long_cls->giveAttr("numerator", new (pyston_getset_cls) BoxedGetsetDescriptor(longLong, NULL, NULL));
long_cls->giveAttr("conjugate", new BoxedFunction(FunctionMetadata::create((void*)longDesc, UNKNOWN, 1)));
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("__getnewargs__", new BoxedFunction(FunctionMetadata::create((void*)long_getnewargs, UNKNOWN, 1,
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);
long_cls->freeze();
......
......@@ -51,8 +51,8 @@ Box* longSub(BoxedLong* lhs, Box* rhs);
Box* longMul(BoxedLong* lhs, Box* rhs);
Box* longDiv(BoxedLong* lhs, Box* rhs);
Box* longPow(BoxedLong* lhs, Box* rhs, Box* mod = None);
Box* longLshift(BoxedLong* lhs, Box* rhs);
Box* longRshift(BoxedLong* lhs, Box* rhs);
Box* longLShiftLong(BoxedLong* lhs, Box* _rhs);
Box* longRShiftLong(BoxedLong* lhs, Box* _rhs);
Box* longHex(BoxedLong* v);
Box* longOct(BoxedLong* v);
......
......@@ -111,3 +111,29 @@ print sys.float_info
if 1:
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):
print(e.message)
else:
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):
for i in xrange(100):
for j in xrange(100):
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