Commit ceb3eb50 authored by Marius Wachtler's avatar Marius Wachtler

fill in a few frequently accessed numeric and rich comparison slots

parent 631bd896
......@@ -108,5 +108,6 @@ void setupBool() {
bool_cls->freeze();
bool_cls->tp_hash = (hashfunc)bool_hash;
bool_cls->tp_repr = boolRepr<CAPI>;
bool_as_number.nb_int = int_cls->tp_as_number->nb_int;
}
}
......@@ -792,7 +792,7 @@ template <ExceptionStyle S> Box* floatRepr(BoxedFloat* self) noexcept(S == CAPI)
return callCAPIFromStyle<S>(float_str_or_repr, self->d, 0, 'r');
}
Box* floatToInt(BoxedFloat* self) {
Box* float_to_int(BoxedFloat* self) noexcept {
double wholepart; /* integral portion of x, rounded toward 0 */
(void)modf(self->d, &wholepart);
......@@ -823,14 +823,14 @@ Box* floatTrunc(BoxedFloat* self) {
raiseExcHelper(TypeError, "descriptor '__trunc__' requires a 'float' object but received a '%s'",
getTypeName(self));
return floatToInt(self);
return float_to_int(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);
return float_to_int(self);
}
Box* floatLong(BoxedFloat* self) {
......@@ -1021,9 +1021,11 @@ void setupFloat() {
_PyFloat_Init();
float_cls->tp_as_number->nb_power = float_pow;
float_cls->tp_new = (newfunc)floatNewPacked;
float_cls->tp_repr = (reprfunc)floatRepr<CAPI>;
float_cls->tp_str = (reprfunc)floatStr<CAPI>;
float_cls->tp_richcompare = float_richcompare;
float_cls->tp_as_number->nb_int = (unaryfunc)float_to_int;
float_cls->tp_as_number->nb_power = float_pow;
}
}
......@@ -1183,14 +1183,22 @@ extern "C" Box* intTrunc(BoxedInt* self) {
return boxInt(self->n);
}
static PyObject* int_int(BoxedInt* v) noexcept {
if (v->cls == int_cls)
return incref(v);
return boxInt(v->n);
}
static PyObject* int_long(BoxedInt* v) noexcept {
return boxLong(v->n);
}
extern "C" Box* intInt(BoxedInt* self) {
if (!PyInt_Check(self))
raiseExcHelper(TypeError, "descriptor '__int__' requires a 'int' object but received a '%s'",
getTypeName(self));
if (self->cls == int_cls)
return incref(self);
return boxInt(self->n);
return int_int(self);
}
Box* intFloat(BoxedInt* self) {
......@@ -1206,7 +1214,7 @@ Box* intLong(BoxedInt* self) {
raiseExcHelper(TypeError, "descriptor '__long__' requires a 'int' object but received a '%s'",
getTypeName(self));
return boxLong(self->n);
return int_long(self);
}
extern "C" Box* intIndex(BoxedInt* v) {
......@@ -1644,5 +1652,7 @@ void setupInt() {
int_cls->tp_repr = (reprfunc)int_to_decimal_string;
int_cls->tp_new = (newfunc)intNewPacked;
int_as_number.nb_int = (unaryfunc)int_int;
int_as_number.nb_long = (unaryfunc)int_long;
}
}
......@@ -1222,6 +1222,107 @@ Box* listInit(BoxedList* self, Box* container) {
Py_RETURN_NONE;
}
static PyObject* list_richcompare(PyObject* v, PyObject* w, int op) noexcept {
PyListObject* vl, *wl;
Py_ssize_t i;
if (!PyList_Check(v) || !PyList_Check(w)) {
Py_INCREF(Py_NotImplemented);
return Py_NotImplemented;
}
vl = (PyListObject*)v;
wl = (PyListObject*)w;
if (Py_SIZE(vl) != Py_SIZE(wl) && (op == Py_EQ || op == Py_NE)) {
/* Shortcut: if the lengths differ, the lists differ */
PyObject* res;
if (op == Py_EQ)
res = Py_False;
else
res = Py_True;
Py_INCREF(res);
return res;
}
/* Search for the first index where items are different */
for (i = 0; i < Py_SIZE(vl) && i < Py_SIZE(wl); i++) {
int k = PyObject_RichCompareBool(vl->ob_item[i], wl->ob_item[i], Py_EQ);
if (k < 0)
return NULL;
if (!k)
break;
}
if (i >= Py_SIZE(vl) || i >= Py_SIZE(wl)) {
/* No more items to compare -- compare sizes */
Py_ssize_t vs = Py_SIZE(vl);
Py_ssize_t ws = Py_SIZE(wl);
int cmp;
PyObject* res;
switch (op) {
case Py_LT:
cmp = vs < ws;
break;
case Py_LE:
cmp = vs <= ws;
break;
case Py_EQ:
cmp = vs == ws;
break;
case Py_NE:
cmp = vs != ws;
break;
case Py_GT:
cmp = vs > ws;
break;
case Py_GE:
cmp = vs >= ws;
break;
default:
return NULL; /* cannot happen */
}
if (cmp)
res = Py_True;
else
res = Py_False;
Py_INCREF(res);
return res;
}
/* We have an item that differs -- shortcuts for EQ/NE */
if (op == Py_EQ) {
Py_INCREF(Py_False);
return Py_False;
}
if (op == Py_NE) {
Py_INCREF(Py_True);
return Py_True;
}
/* Compare the final item again using the proper operator */
return PyObject_RichCompare(vl->ob_item[i], wl->ob_item[i], op);
}
static int list_init(PyListObject* self, PyObject* args, PyObject* kw) noexcept {
PyObject* arg = NULL;
static char* kwlist[2] = { NULL, NULL };
kwlist[0] = const_cast<char*>("sequence");
if (!PyArg_ParseTupleAndKeywords(args, kw, "|O:list", kwlist, &arg))
return -1;
try {
autoDecref(listInit((BoxedList*)self, arg));
} catch (ExcInfo e) {
setCAPIException(e);
return -1;
}
return 0;
}
extern "C" PyObject* PyList_New(Py_ssize_t size) noexcept {
try {
BoxedList* l = new BoxedList();
......@@ -1239,65 +1340,12 @@ extern "C" PyObject* PyList_New(Py_ssize_t size) noexcept {
}
}
Box* _listCmp(BoxedList* lhs, BoxedList* rhs, AST_TYPE::AST_TYPE op_type) {
int lsz = lhs->size;
int rsz = rhs->size;
bool is_order
= (op_type == AST_TYPE::Lt || op_type == AST_TYPE::LtE || op_type == AST_TYPE::Gt || op_type == AST_TYPE::GtE);
if (lsz != rsz) {
if (op_type == AST_TYPE::Eq)
Py_RETURN_FALSE;
if (op_type == AST_TYPE::NotEq)
Py_RETURN_TRUE;
}
int n = std::min(lsz, rsz);
for (int i = 0; i < n; i++) {
bool identity_eq = lhs->elts->elts[i] == rhs->elts->elts[i];
if (identity_eq)
continue;
int r = PyObject_RichCompareBool(lhs->elts->elts[i], rhs->elts->elts[i], Py_EQ);
if (r == -1)
throwCAPIException();
if (r)
continue;
if (op_type == AST_TYPE::Eq) {
return boxBool(false);
} else if (op_type == AST_TYPE::NotEq) {
return boxBool(true);
} else {
Box* r = compareInternal<NOT_REWRITABLE>(lhs->elts->elts[i], rhs->elts->elts[i], op_type, NULL);
return r;
}
}
if (op_type == AST_TYPE::Lt)
return boxBool(lsz < rsz);
else if (op_type == AST_TYPE::LtE)
return boxBool(lsz <= rsz);
else if (op_type == AST_TYPE::Gt)
return boxBool(lsz > rsz);
else if (op_type == AST_TYPE::GtE)
return boxBool(lsz >= rsz);
else if (op_type == AST_TYPE::Eq)
return boxBool(lsz == rsz);
else if (op_type == AST_TYPE::NotEq)
return boxBool(lsz != rsz);
RELEASE_ASSERT(0, "%d", op_type);
}
Box* listEq(BoxedList* self, Box* rhs) {
if (!PyList_Check(rhs)) {
return incref(NotImplemented);
}
return _listCmp(self, static_cast<BoxedList*>(rhs), AST_TYPE::Eq);
return callCAPIFromStyle<CXX>(list_richcompare, self, rhs, Py_EQ);
}
Box* listNe(BoxedList* self, Box* rhs) {
......@@ -1305,7 +1353,7 @@ Box* listNe(BoxedList* self, Box* rhs) {
return incref(NotImplemented);
}
return _listCmp(self, static_cast<BoxedList*>(rhs), AST_TYPE::NotEq);
return callCAPIFromStyle<CXX>(list_richcompare, self, rhs, Py_NE);
}
Box* listLt(BoxedList* self, Box* rhs) {
......@@ -1313,7 +1361,7 @@ Box* listLt(BoxedList* self, Box* rhs) {
return incref(NotImplemented);
}
return _listCmp(self, static_cast<BoxedList*>(rhs), AST_TYPE::Lt);
return callCAPIFromStyle<CXX>(list_richcompare, self, rhs, Py_LT);
}
Box* listLe(BoxedList* self, Box* rhs) {
......@@ -1321,7 +1369,7 @@ Box* listLe(BoxedList* self, Box* rhs) {
return incref(NotImplemented);
}
return _listCmp(self, static_cast<BoxedList*>(rhs), AST_TYPE::LtE);
return callCAPIFromStyle<CXX>(list_richcompare, self, rhs, Py_LE);
}
Box* listGt(BoxedList* self, Box* rhs) {
......@@ -1329,7 +1377,7 @@ Box* listGt(BoxedList* self, Box* rhs) {
return incref(NotImplemented);
}
return _listCmp(self, static_cast<BoxedList*>(rhs), AST_TYPE::Gt);
return callCAPIFromStyle<CXX>(list_richcompare, self, rhs, Py_GT);
}
Box* listGe(BoxedList* self, Box* rhs) {
......@@ -1337,7 +1385,7 @@ Box* listGe(BoxedList* self, Box* rhs) {
return incref(NotImplemented);
}
return _listCmp(self, static_cast<BoxedList*>(rhs), AST_TYPE::GtE);
return callCAPIFromStyle<CXX>(list_richcompare, self, rhs, Py_GE);
}
extern "C" PyObject* _PyList_Extend(PyListObject* self, PyObject* b) noexcept {
......@@ -1540,6 +1588,8 @@ void setupList() {
list_cls->freeze();
list_cls->tp_iter = listIter;
list_cls->tp_repr = list_repr;
list_cls->tp_init = (initproc)list_init;
list_cls->tp_richcompare = list_richcompare;
list_cls->tp_as_sequence->sq_length = list_length;
list_cls->tp_as_sequence->sq_concat = (binaryfunc)list_concat;
......
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