Skip to content

Commit 6f3021c

Browse files
committed
preliminary implementation of BIIterBooleanType
1 parent 4f609f8 commit 6f3021c

File tree

1 file changed

+130
-1
lines changed

1 file changed

+130
-1
lines changed

src/_arraykit.c

Lines changed: 130 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4401,7 +4401,6 @@ BIIterSlice_new(BlockIndexObject *bi, PyObject* slice, int8_t reversed) {
44014401
if (!bii) {
44024402
return NULL;
44034403
}
4404-
44054404
Py_INCREF(bi);
44064405
bii->bi = bi;
44074406
// we store the slice in case we need to delegate to a different iterator
@@ -4491,6 +4490,135 @@ static PyTypeObject BIIterSliceType = {
44914490
};
44924491

44934492

4493+
//------------------------------------------------------------------------------
4494+
// BI Iterator Boolean array selection
4495+
static PyTypeObject BIIterBooleanType;
4496+
4497+
typedef struct BIIterBooleanObject {
4498+
PyObject_VAR_HEAD
4499+
BlockIndexObject *bi;
4500+
int8_t reversed;
4501+
PyObject* array;
4502+
Py_ssize_t pos; // current index, mutated in-place
4503+
Py_ssize_t len;
4504+
} BIIterBooleanObject;
4505+
4506+
static PyObject *
4507+
BIIterBoolean_new(BlockIndexObject *bi, PyObject* array, int8_t reversed) {
4508+
BIIterBooleanObject *bii = PyObject_New(BIIterBooleanObject, &BIIterBooleanType);
4509+
if (!bii) {
4510+
return NULL;
4511+
}
4512+
Py_INCREF(bi);
4513+
bii->bi = bi;
4514+
// we store the slice in case we need to delegate to a different iterator
4515+
Py_INCREF(array);
4516+
bii->array = array;
4517+
4518+
if (PyArray_Check(array)) {
4519+
PyArrayObject *a = (PyArrayObject *)array;
4520+
if (PyArray_NDIM(a) != 1) {
4521+
PyErr_SetString(PyExc_TypeError, "Arrays must be 1-dimensional");
4522+
goto error;
4523+
}
4524+
if (PyArray_TYPE(a) != NPY_BOOL) {
4525+
PyErr_SetString(PyExc_TypeError, "Arrays must be Boolean");
4526+
goto error;
4527+
}
4528+
if ((bii->len = PyArray_SIZE(a)) != bi->bir_count ) {
4529+
PyErr_SetString(PyExc_TypeError, "Arrays must match length");
4530+
goto error;
4531+
}
4532+
}
4533+
else {
4534+
PyErr_SetString(PyExc_TypeError, "Input type not supported");
4535+
goto error;
4536+
}
4537+
4538+
// always initialize bii->pos to a valid index
4539+
if ((bii->reversed = reversed)) {
4540+
bii->pos = bii->len - 1;
4541+
}
4542+
else {
4543+
bii->pos = 0;
4544+
}
4545+
return (PyObject *)bii;
4546+
error:
4547+
Py_DECREF(bii->bi);
4548+
Py_DECREF(bii->array);
4549+
return NULL;
4550+
}
4551+
4552+
static void
4553+
BIIterBoolean_dealloc(BIIterBooleanObject *self) {
4554+
Py_DECREF(self->bi);
4555+
Py_DECREF(self->array);
4556+
Py_TYPE(self)->tp_free((PyObject *)self);
4557+
}
4558+
4559+
static BIIterBooleanObject *
4560+
BIIterBoolean_iter(BIIterBooleanObject *self) {
4561+
Py_INCREF(self);
4562+
return self;
4563+
}
4564+
4565+
static PyObject *
4566+
BIIterBoolean_iternext(BIIterBooleanObject *self) {
4567+
npy_bool v = 0;
4568+
Py_ssize_t i = -1;
4569+
PyArrayObject* a = (PyArrayObject*) self->array;
4570+
4571+
if (!self->reversed) {
4572+
while (self->pos < self->len) {
4573+
v = *(npy_bool*)PyArray_GETPTR1(a, self->pos);
4574+
if (v) {
4575+
i = self->pos;
4576+
self->pos++;
4577+
break;
4578+
}
4579+
self->pos++;
4580+
}
4581+
}
4582+
else { // reversed
4583+
while (self->pos >= 0) {
4584+
v = *(npy_bool*)PyArray_GETPTR1(a, self->pos);
4585+
if (v) {
4586+
i = self->pos;
4587+
self->pos--;
4588+
break;
4589+
}
4590+
self->pos--;
4591+
}
4592+
}
4593+
if (i != -1) {
4594+
return AK_BI_item(self->bi, i); // return new ref
4595+
}
4596+
return NULL; // no True remain
4597+
}
4598+
4599+
static PyObject *
4600+
BIIterBoolean_reversed(BIIterBooleanObject *self) {
4601+
return BIIterBoolean_new(self->bi, self->array, !self->reversed);
4602+
}
4603+
4604+
// NOTE: no length hint given as we would have to traverse whole array and count True... not sure it is worht it.
4605+
static PyMethodDef BIiterBoolean_methods[] = {
4606+
// {"__length_hint__", (PyCFunction)BIIterBoolean_length_hint, METH_NOARGS, NULL},
4607+
{"__reversed__", (PyCFunction)BIIterBoolean_reversed, METH_NOARGS, NULL},
4608+
{NULL},
4609+
};
4610+
4611+
static PyTypeObject BIIterBooleanType = {
4612+
PyVarObject_HEAD_INIT(NULL, 0)
4613+
.tp_basicsize = sizeof(BIIterBooleanObject),
4614+
.tp_dealloc = (destructor) BIIterBoolean_dealloc,
4615+
.tp_iter = (getiterfunc) BIIterBoolean_iter,
4616+
.tp_iternext = (iternextfunc) BIIterBoolean_iternext,
4617+
.tp_methods = BIiterBoolean_methods,
4618+
.tp_name = "arraykit.BlockIndexIteratorBoolean",
4619+
};
4620+
4621+
44944622
//------------------------------------------------------------------------------
44954623

44964624
// Returns 0 on succes, -1 on error.
@@ -5254,6 +5382,7 @@ PyInit__arraykit(void)
52545382
PyType_Ready(&BIIterType) ||
52555383
PyType_Ready(&BIIterSeqType) ||
52565384
PyType_Ready(&BIIterSliceType) ||
5385+
PyType_Ready(&BIIterBooleanType) ||
52575386
PyType_Ready(&ArrayGOType) ||
52585387
PyModule_AddObject(m, "BlockIndex", (PyObject *) &BlockIndexType) ||
52595388
PyModule_AddObject(m, "ArrayGO", (PyObject *) &ArrayGOType) ||

0 commit comments

Comments
 (0)