@@ -4401,7 +4401,6 @@ BIIterSlice_new(BlockIndexObject *bi, PyObject* slice, int8_t reversed) {
4401
4401
if (!bii ) {
4402
4402
return NULL ;
4403
4403
}
4404
-
4405
4404
Py_INCREF (bi );
4406
4405
bii -> bi = bi ;
4407
4406
// we store the slice in case we need to delegate to a different iterator
@@ -4491,6 +4490,135 @@ static PyTypeObject BIIterSliceType = {
4491
4490
};
4492
4491
4493
4492
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
+
4494
4622
//------------------------------------------------------------------------------
4495
4623
4496
4624
// Returns 0 on succes, -1 on error.
@@ -5254,6 +5382,7 @@ PyInit__arraykit(void)
5254
5382
PyType_Ready (& BIIterType ) ||
5255
5383
PyType_Ready (& BIIterSeqType ) ||
5256
5384
PyType_Ready (& BIIterSliceType ) ||
5385
+ PyType_Ready (& BIIterBooleanType ) ||
5257
5386
PyType_Ready (& ArrayGOType ) ||
5258
5387
PyModule_AddObject (m , "BlockIndex" , (PyObject * ) & BlockIndexType ) ||
5259
5388
PyModule_AddObject (m , "ArrayGO" , (PyObject * ) & ArrayGOType ) ||
0 commit comments