Generated by Cython 0.29.32

Yellow lines hint at Python interaction.
Click on a line that starts with a "+" to see the C code that Cython generated for it.

Raw output: _bp.c

+0001: # cython: boundscheck=False, wraparound=False, cdivision=True, linetrace=False
  __pyx_t_3 = __Pyx_PyDict_NewPresized(0); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  if (PyDict_SetItem(__pyx_d, __pyx_n_s_test, __pyx_t_3) < 0) __PYX_ERR(0, 1, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
 0002: # ----------------------------------------------------------------------------
 0003: # Copyright (c) 2013--, BP development team.
 0004: #
 0005: # Distributed under the terms of the GPL License.
 0006: #
 0007: # The full license is in the file LICENSE, distributed with this software.
 0008: # ----------------------------------------------------------------------------
 0009: 
 0010: ### NOTE: some doctext strings are copied and pasted from manuscript
 0011: ### http://www.dcc.uchile.cl/~gnavarro/ps/tcs16.2.pdf
 0012: 
 0013: from libc.math cimport ceil, log as ln, pow, log2
+0014: import time
  __pyx_t_1 = __Pyx_Import(__pyx_n_s_time, 0, -1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 14, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  if (PyDict_SetItem(__pyx_d, __pyx_n_s_time, __pyx_t_1) < 0) __PYX_ERR(0, 14, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 0015: #import numpy.testing as npt
+0016: import numpy as np
  __pyx_t_1 = __Pyx_Import(__pyx_n_s_numpy, 0, -1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 16, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  if (PyDict_SetItem(__pyx_d, __pyx_n_s_np, __pyx_t_1) < 0) __PYX_ERR(0, 16, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 0017: cimport numpy as np
 0018: cimport cython
 0019: 
 0020: from bp._binary_tree cimport * #bt_node_from_left, bt_left_child, bt_right_child
 0021: from bp._ba cimport *
 0022: 
+0023: np.import_array()
  __pyx_t_2 = __pyx_f_5numpy_import_array(); if (unlikely(__pyx_t_2 == ((int)-1))) __PYX_ERR(0, 23, __pyx_L1_error)
 0024: 
 0025: cdef extern from "limits.h":
 0026:     int INT_MAX
 0027: 
 0028: 
+0029: DOUBLE = np.float64
  __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_np); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 29, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_float64); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 29, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  if (PyDict_SetItem(__pyx_d, __pyx_n_s_DOUBLE, __pyx_t_3) < 0) __PYX_ERR(0, 29, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+0030: SIZE = np.intp
  __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_n_s_np); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 30, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_n_s_intp); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 30, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  if (PyDict_SetItem(__pyx_d, __pyx_n_s_SIZE, __pyx_t_1) < 0) __PYX_ERR(0, 30, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+0031: BOOL = np.uint8
  __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_np); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 31, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_uint8); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 31, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  if (PyDict_SetItem(__pyx_d, __pyx_n_s_BOOL, __pyx_t_3) < 0) __PYX_ERR(0, 31, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+0032: INT32 = np.int32
  __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_n_s_np); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 32, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_n_s_int32); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 32, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  if (PyDict_SetItem(__pyx_d, __pyx_n_s_INT32, __pyx_t_1) < 0) __PYX_ERR(0, 32, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 0033: 
 0034: 
+0035: cdef inline int min(int a, int b) nogil:
static CYTHON_INLINE int __pyx_f_2bp_3_bp_min(int __pyx_v_a, int __pyx_v_b) {
  int __pyx_r;
/* … */
  /* function exit code */
  __pyx_L0:;
  return __pyx_r;
}
+0036:     if a > b:
  __pyx_t_1 = ((__pyx_v_a > __pyx_v_b) != 0);
  if (__pyx_t_1) {
/* … */
  }
+0037:         return b
    __pyx_r = __pyx_v_b;
    goto __pyx_L0;
 0038:     else:
+0039:         return a
  /*else*/ {
    __pyx_r = __pyx_v_a;
    goto __pyx_L0;
  }
 0040: 
 0041: 
+0042: cdef inline int max(int a, int b) nogil:
static CYTHON_INLINE int __pyx_f_2bp_3_bp_max(int __pyx_v_a, int __pyx_v_b) {
  int __pyx_r;
/* … */
  /* function exit code */
  __pyx_L0:;
  return __pyx_r;
}
+0043:     if a > b:
  __pyx_t_1 = ((__pyx_v_a > __pyx_v_b) != 0);
  if (__pyx_t_1) {
/* … */
  }
+0044:         return a
    __pyx_r = __pyx_v_a;
    goto __pyx_L0;
 0045:     else:
+0046:         return b
  /*else*/ {
    __pyx_r = __pyx_v_b;
    goto __pyx_L0;
  }
 0047: 
 0048: 
+0049: cdef class mM:
struct __pyx_vtabstruct_2bp_3_bp_mM {
  void (*rmm)(struct __pyx_obj_2bp_3_bp_mM *, __Pyx_memviewslice, int);
};
static struct __pyx_vtabstruct_2bp_3_bp_mM *__pyx_vtabptr_2bp_3_bp_mM;

+0050:     def __cinit__(self, BOOL_t[:] B, int B_size):
/* Python wrapper */
static int __pyx_pw_2bp_3_bp_2mM_1__cinit__(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
static int __pyx_pw_2bp_3_bp_2mM_1__cinit__(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
  __Pyx_memviewslice __pyx_v_B = { 0, 0, { 0 }, { 0 }, { 0 } };
  int __pyx_v_B_size;
  int __pyx_r;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("__cinit__ (wrapper)", 0);
  {
    static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_B,&__pyx_n_s_B_size,0};
    PyObject* values[2] = {0,0};
    if (unlikely(__pyx_kwds)) {
      Py_ssize_t kw_args;
      const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args);
      switch (pos_args) {
        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
        CYTHON_FALLTHROUGH;
        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
        CYTHON_FALLTHROUGH;
        case  0: break;
        default: goto __pyx_L5_argtuple_error;
      }
      kw_args = PyDict_Size(__pyx_kwds);
      switch (pos_args) {
        case  0:
        if (likely((values[0] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_B)) != 0)) kw_args--;
        else goto __pyx_L5_argtuple_error;
        CYTHON_FALLTHROUGH;
        case  1:
        if (likely((values[1] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_B_size)) != 0)) kw_args--;
        else {
          __Pyx_RaiseArgtupleInvalid("__cinit__", 1, 2, 2, 1); __PYX_ERR(0, 50, __pyx_L3_error)
        }
      }
      if (unlikely(kw_args > 0)) {
        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "__cinit__") < 0)) __PYX_ERR(0, 50, __pyx_L3_error)
      }
    } else if (PyTuple_GET_SIZE(__pyx_args) != 2) {
      goto __pyx_L5_argtuple_error;
    } else {
      values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
      values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
    }
    __pyx_v_B = __Pyx_PyObject_to_MemoryviewSlice_ds_nn___pyx_t_2bp_3_bp_BOOL_t(values[0], PyBUF_WRITABLE); if (unlikely(!__pyx_v_B.memview)) __PYX_ERR(0, 50, __pyx_L3_error)
    __pyx_v_B_size = __Pyx_PyInt_As_int(values[1]); if (unlikely((__pyx_v_B_size == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 50, __pyx_L3_error)
  }
  goto __pyx_L4_argument_unpacking_done;
  __pyx_L5_argtuple_error:;
  __Pyx_RaiseArgtupleInvalid("__cinit__", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 50, __pyx_L3_error)
  __pyx_L3_error:;
  __Pyx_AddTraceback("bp._bp.mM.__cinit__", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __Pyx_RefNannyFinishContext();
  return -1;
  __pyx_L4_argument_unpacking_done:;
  __pyx_r = __pyx_pf_2bp_3_bp_2mM___cinit__(((struct __pyx_obj_2bp_3_bp_mM *)__pyx_v_self), __pyx_v_B, __pyx_v_B_size);
  int __pyx_lineno = 0;
  const char *__pyx_filename = NULL;
  int __pyx_clineno = 0;

  /* function exit code */
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}

static int __pyx_pf_2bp_3_bp_2mM___cinit__(struct __pyx_obj_2bp_3_bp_mM *__pyx_v_self, __Pyx_memviewslice __pyx_v_B, int __pyx_v_B_size) {
  int __pyx_r;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("__cinit__", 0);
/* … */
  /* function exit code */
  __pyx_r = 0;
  __PYX_XDEC_MEMVIEW(&__pyx_v_B, 1);
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}
+0051:         self.m_idx = 0
  __pyx_v_self->m_idx = 0;
+0052:         self.M_idx = 1
  __pyx_v_self->M_idx = 1;
 0053: 
+0054:         self.rmm(B, B_size)
  ((struct __pyx_vtabstruct_2bp_3_bp_mM *)__pyx_v_self->__pyx_vtab)->rmm(__pyx_v_self, __pyx_v_B, __pyx_v_B_size);
 0055: 
+0056:     cdef void rmm(self, BOOL_t[:] B, int B_size) nogil:
static void __pyx_f_2bp_3_bp_2mM_rmm(struct __pyx_obj_2bp_3_bp_mM *__pyx_v_self, __Pyx_memviewslice __pyx_v_B, int __pyx_v_B_size) {
  int __pyx_v_i;
  int __pyx_v_j;
  int __pyx_v_lvl;
  int __pyx_v_pos;
  int __pyx_v_offset;
  int __pyx_v_lower_limit;
  int __pyx_v_upper_limit;
  int __pyx_v_min_;
  int __pyx_v_max_;
  int __pyx_v_excess;
  int __pyx_v_r;
  int __pyx_v_num_curr_nodes;
  __pyx_t_2bp_3_bp_SIZE_t __pyx_v_node;
  __pyx_t_2bp_3_bp_SIZE_t __pyx_v_lchild;
  __pyx_t_2bp_3_bp_SIZE_t __pyx_v_rchild;
  #ifdef WITH_THREAD
  PyGILState_STATE __pyx_gilstate_save = __Pyx_PyGILState_Ensure();
  #endif
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("rmm", 0);
  #ifdef WITH_THREAD
  __Pyx_PyGILState_Release(__pyx_gilstate_save);
  #endif
/* … */
  /* function exit code */
  goto __pyx_L0;
  __pyx_L1_error:;
  __Pyx_XDECREF(__pyx_t_1);
  __Pyx_XDECREF(__pyx_t_2);
  __Pyx_XDECREF(__pyx_t_3);
  __Pyx_XDECREF(__pyx_t_4);
  __PYX_XDEC_MEMVIEW(&__pyx_t_5, 0);
  __PYX_XDEC_MEMVIEW(&__pyx_t_6, 0);
  __Pyx_WriteUnraisable("bp._bp.mM.rmm", __pyx_clineno, __pyx_lineno, __pyx_filename, 1, 1);
  __pyx_L0:;
  #ifdef WITH_THREAD
  __Pyx_PyGILState_Release(__pyx_gilstate_save);
  #endif
}
+0057:         """Construct the rmM tree based off of Navarro and Sadakane
  /*try:*/ {
/* … */
  /*finally:*/ {
    /*normal exit:*/{
      #ifdef WITH_THREAD
      __pyx_gilstate_save = __Pyx_PyGILState_Ensure();
      #endif
      goto __pyx_L5;
    }
    __pyx_L4_error: {
      #ifdef WITH_THREAD
      __pyx_gilstate_save = __Pyx_PyGILState_Ensure();
      #endif
      goto __pyx_L1_error;
    }
    __pyx_L5:;
  }
 0058: 
 0059:         http://www.dcc.uchile.cl/~gnavarro/ps/talg12.pdf
 0060:         """
 0061:         cdef int i, j, lvl, pos  # for loop support
 0062:         cdef int offset  # tip offset in binary tree for a given parenthesis
 0063:         cdef int lower_limit  # the lower limit of the bucket a parenthesis is in
 0064:         cdef int upper_limit  # the upper limit of the bucket a parenthesis is in
+0065:         cdef int min_ = 0 # m, absolute minimum for a blokc
    __pyx_v_min_ = 0;
+0066:         cdef int max_ = 0 # M, absolute maximum for a block
    __pyx_v_max_ = 0;
+0067:         cdef int excess = 0 # e, absolute excess
    __pyx_v_excess = 0;
 0068:         cdef int vbar
+0069:         cdef int r = 0
    __pyx_v_r = 0;
 0070: 
 0071:         # build tip info
+0072:         self.b = <int>ceil(ln(<double> B_size) * ln(ln(<double> B_size)))
    __pyx_v_self->b = ((int)ceil((log(((double)__pyx_v_B_size)) * log(log(((double)__pyx_v_B_size))))));
 0073: 
 0074:         # determine the number of nodes and height of the binary tree
+0075:         self.n_tip = <int>ceil(B_size / <double> self.b)
    __pyx_v_self->n_tip = ((int)ceil((__pyx_v_B_size / ((double)__pyx_v_self->b))));
+0076:         self.height = <int>ceil(log2(self.n_tip))
    __pyx_v_self->height = ((int)ceil(log2(__pyx_v_self->n_tip)));
+0077:         self.n_internal = <int>(pow(2, self.height)) - 1
    __pyx_v_self->n_internal = (((int)pow(2.0, __pyx_v_self->height)) - 1);
+0078:         self.n_total = self.n_tip + self.n_internal
    __pyx_v_self->n_total = (__pyx_v_self->n_tip + __pyx_v_self->n_internal);
 0079: 
+0080:         with gil:
    {
        #ifdef WITH_THREAD
        PyGILState_STATE __pyx_gilstate_save = __Pyx_PyGILState_Ensure();
        #endif
        /*try:*/ {
/* … */
        /*finally:*/ {
          /*normal exit:*/{
            #ifdef WITH_THREAD
            __Pyx_PyGILState_Release(__pyx_gilstate_save);
            #endif
            goto __pyx_L8;
          }
          __pyx_L7_error: {
            #ifdef WITH_THREAD
            __Pyx_PyGILState_Release(__pyx_gilstate_save);
            #endif
            goto __pyx_L4_error;
          }
          __pyx_L8:;
        }
    }
 0081:             # creation of a memoryview directly or via numpy requires the GIL:
 0082:             # http://stackoverflow.com/a/22238012
+0083:             self.mM = np.zeros((self.n_total, 2), dtype=SIZE)
          __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_np); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 83, __pyx_L7_error)
          __Pyx_GOTREF(__pyx_t_1);
          __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_zeros); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 83, __pyx_L7_error)
          __Pyx_GOTREF(__pyx_t_2);
          __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
          __pyx_t_1 = __Pyx_PyInt_From_int(__pyx_v_self->n_total); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 83, __pyx_L7_error)
          __Pyx_GOTREF(__pyx_t_1);
          __pyx_t_3 = PyTuple_New(2); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 83, __pyx_L7_error)
          __Pyx_GOTREF(__pyx_t_3);
          __Pyx_GIVEREF(__pyx_t_1);
          PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_1);
          __Pyx_INCREF(__pyx_int_2);
          __Pyx_GIVEREF(__pyx_int_2);
          PyTuple_SET_ITEM(__pyx_t_3, 1, __pyx_int_2);
          __pyx_t_1 = 0;
          __pyx_t_1 = PyTuple_New(1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 83, __pyx_L7_error)
          __Pyx_GOTREF(__pyx_t_1);
          __Pyx_GIVEREF(__pyx_t_3);
          PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_t_3);
          __pyx_t_3 = 0;
          __pyx_t_3 = __Pyx_PyDict_NewPresized(1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 83, __pyx_L7_error)
          __Pyx_GOTREF(__pyx_t_3);
          __Pyx_GetModuleGlobalName(__pyx_t_4, __pyx_n_s_SIZE); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 83, __pyx_L7_error)
          __Pyx_GOTREF(__pyx_t_4);
          if (PyDict_SetItem(__pyx_t_3, __pyx_n_s_dtype, __pyx_t_4) < 0) __PYX_ERR(0, 83, __pyx_L7_error)
          __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
          __pyx_t_4 = __Pyx_PyObject_Call(__pyx_t_2, __pyx_t_1, __pyx_t_3); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 83, __pyx_L7_error)
          __Pyx_GOTREF(__pyx_t_4);
          __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
          __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
          __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
          __pyx_t_5 = __Pyx_PyObject_to_MemoryviewSlice_d_dc_nn___pyx_t_2bp_3_bp_SIZE_t(__pyx_t_4, PyBUF_WRITABLE); if (unlikely(!__pyx_t_5.memview)) __PYX_ERR(0, 83, __pyx_L7_error)
          __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
          __PYX_XDEC_MEMVIEW(&__pyx_v_self->mM, 0);
          __pyx_v_self->mM = __pyx_t_5;
          __pyx_t_5.memview = NULL;
          __pyx_t_5.data = NULL;
+0084:             self.r = np.zeros(self.n_total, dtype=SIZE)
          __Pyx_GetModuleGlobalName(__pyx_t_4, __pyx_n_s_np); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 84, __pyx_L7_error)
          __Pyx_GOTREF(__pyx_t_4);
          __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_t_4, __pyx_n_s_zeros); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 84, __pyx_L7_error)
          __Pyx_GOTREF(__pyx_t_3);
          __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
          __pyx_t_4 = __Pyx_PyInt_From_int(__pyx_v_self->n_total); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 84, __pyx_L7_error)
          __Pyx_GOTREF(__pyx_t_4);
          __pyx_t_1 = PyTuple_New(1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 84, __pyx_L7_error)
          __Pyx_GOTREF(__pyx_t_1);
          __Pyx_GIVEREF(__pyx_t_4);
          PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_t_4);
          __pyx_t_4 = 0;
          __pyx_t_4 = __Pyx_PyDict_NewPresized(1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 84, __pyx_L7_error)
          __Pyx_GOTREF(__pyx_t_4);
          __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_SIZE); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 84, __pyx_L7_error)
          __Pyx_GOTREF(__pyx_t_2);
          if (PyDict_SetItem(__pyx_t_4, __pyx_n_s_dtype, __pyx_t_2) < 0) __PYX_ERR(0, 84, __pyx_L7_error)
          __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
          __pyx_t_2 = __Pyx_PyObject_Call(__pyx_t_3, __pyx_t_1, __pyx_t_4); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 84, __pyx_L7_error)
          __Pyx_GOTREF(__pyx_t_2);
          __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
          __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
          __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
          __pyx_t_6 = __Pyx_PyObject_to_MemoryviewSlice_ds_nn___pyx_t_2bp_3_bp_SIZE_t(__pyx_t_2, PyBUF_WRITABLE); if (unlikely(!__pyx_t_6.memview)) __PYX_ERR(0, 84, __pyx_L7_error)
          __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
          __PYX_XDEC_MEMVIEW(&__pyx_v_self->r, 0);
          __pyx_v_self->r = __pyx_t_6;
          __pyx_t_6.memview = NULL;
          __pyx_t_6.data = NULL;
        }
 0085: 
 0086:         # annoying, cannot do step in range if step is not known at runtime
 0087:         # see https://github.com/cython/cython/pull/520
 0088:         # for i in range(0, B_size, b):
 0089:         # as a result, doing a custom range using a while loop
 0090:         # compute for tips of rmM tree
+0091:         i = 0
    __pyx_v_i = 0;
+0092:         while i < B_size:
    while (1) {
      __pyx_t_7 = ((__pyx_v_i < __pyx_v_B_size) != 0);
      if (!__pyx_t_7) break;
+0093:             offset = i // self.b
      __pyx_v_offset = (__pyx_v_i / __pyx_v_self->b);
+0094:             lower_limit = i
      __pyx_v_lower_limit = __pyx_v_i;
+0095:             upper_limit = min(i + self.b, B_size)
      __pyx_v_upper_limit = __pyx_f_2bp_3_bp_min((__pyx_v_i + __pyx_v_self->b), __pyx_v_B_size);
+0096:             min_ = INT_MAX
      __pyx_v_min_ = INT_MAX;
+0097:             max_ = 0
      __pyx_v_max_ = 0;
 0098: 
+0099:             self.r[offset + self.n_internal] = r
      if (unlikely(!__pyx_v_self->r.memview)) {PyErr_SetString(PyExc_AttributeError,"Memoryview is not initialized");__PYX_ERR(0, 99, __pyx_L4_error)}
      __pyx_t_8 = (__pyx_v_offset + __pyx_v_self->n_internal);
      *((__pyx_t_2bp_3_bp_SIZE_t *) ( /* dim=0 */ (__pyx_v_self->r.data + __pyx_t_8 * __pyx_v_self->r.strides[0]) )) = __pyx_v_r;
+0100:             for j in range(lower_limit, upper_limit):
      __pyx_t_9 = __pyx_v_upper_limit;
      __pyx_t_10 = __pyx_t_9;
      for (__pyx_t_11 = __pyx_v_lower_limit; __pyx_t_11 < __pyx_t_10; __pyx_t_11+=1) {
        __pyx_v_j = __pyx_t_11;
 0101:                 # G function, a +-1 method where if B[j] == 1 we +1, and if
 0102:                 # B[j] == 0 we -1
+0103:                 excess += -1 + (2 * B[j])
        __pyx_t_8 = __pyx_v_j;
        __pyx_v_excess = (__pyx_v_excess + (-1L + (2 * (*((__pyx_t_2bp_3_bp_BOOL_t *) ( /* dim=0 */ (__pyx_v_B.data + __pyx_t_8 * __pyx_v_B.strides[0]) ))))));
+0104:                 r += B[j]
        __pyx_t_8 = __pyx_v_j;
        __pyx_v_r = (__pyx_v_r + (*((__pyx_t_2bp_3_bp_BOOL_t *) ( /* dim=0 */ (__pyx_v_B.data + __pyx_t_8 * __pyx_v_B.strides[0]) ))));
 0105: 
+0106:                 if excess < min_:
        __pyx_t_7 = ((__pyx_v_excess < __pyx_v_min_) != 0);
        if (__pyx_t_7) {
/* … */
        }
+0107:                     min_ = excess
          __pyx_v_min_ = __pyx_v_excess;
 0108: 
+0109:                 if excess > max_:
        __pyx_t_7 = ((__pyx_v_excess > __pyx_v_max_) != 0);
        if (__pyx_t_7) {
/* … */
        }
      }
+0110:                     max_ = excess
          __pyx_v_max_ = __pyx_v_excess;
 0111: 
 0112:                 # at the left bound of the bucket
 0113: 
+0114:             self.mM[offset + self.n_internal, self.m_idx] = min_
      if (unlikely(!__pyx_v_self->mM.memview)) {PyErr_SetString(PyExc_AttributeError,"Memoryview is not initialized");__PYX_ERR(0, 114, __pyx_L4_error)}
      __pyx_t_8 = (__pyx_v_offset + __pyx_v_self->n_internal);
      __pyx_t_12 = __pyx_v_self->m_idx;
      *((__pyx_t_2bp_3_bp_SIZE_t *) ( /* dim=1 */ ((char *) (((__pyx_t_2bp_3_bp_SIZE_t *) ( /* dim=0 */ (__pyx_v_self->mM.data + __pyx_t_8 * __pyx_v_self->mM.strides[0]) )) + __pyx_t_12)) )) = __pyx_v_min_;
+0115:             self.mM[offset + self.n_internal, self.M_idx] = max_
      if (unlikely(!__pyx_v_self->mM.memview)) {PyErr_SetString(PyExc_AttributeError,"Memoryview is not initialized");__PYX_ERR(0, 115, __pyx_L4_error)}
      __pyx_t_12 = (__pyx_v_offset + __pyx_v_self->n_internal);
      __pyx_t_8 = __pyx_v_self->M_idx;
      *((__pyx_t_2bp_3_bp_SIZE_t *) ( /* dim=1 */ ((char *) (((__pyx_t_2bp_3_bp_SIZE_t *) ( /* dim=0 */ (__pyx_v_self->mM.data + __pyx_t_12 * __pyx_v_self->mM.strides[0]) )) + __pyx_t_8)) )) = __pyx_v_max_;
 0116: 
+0117:             i += self.b
      __pyx_v_i = (__pyx_v_i + __pyx_v_self->b);
    }
 0118: 
 0119:         # compute for internal nodes of rmM tree in reverse level order starting 
 0120:         # at the level above the tips
+0121:         for lvl in range(self.height - 1, -1, -1):
    for (__pyx_t_9 = (__pyx_v_self->height - 1); __pyx_t_9 > -1; __pyx_t_9-=1) {
      __pyx_v_lvl = __pyx_t_9;
+0122:             num_curr_nodes = <int>pow(2, lvl)
      __pyx_v_num_curr_nodes = ((int)pow(2.0, __pyx_v_lvl));
 0123: 
 0124:             # for each node in the level
+0125:             for pos in range(num_curr_nodes):
      __pyx_t_10 = __pyx_v_num_curr_nodes;
      __pyx_t_11 = __pyx_t_10;
      for (__pyx_t_13 = 0; __pyx_t_13 < __pyx_t_11; __pyx_t_13+=1) {
        __pyx_v_pos = __pyx_t_13;
 0126:                 # obtain the node, and the index to its children
+0127:                 node = bt_node_from_left(pos, lvl)
        __pyx_v_node = __pyx_f_2bp_12_binary_tree_bt_node_from_left(__pyx_v_pos, __pyx_v_lvl);
+0128:                 lchild = bt_left_child(node)
        __pyx_v_lchild = __pyx_f_2bp_12_binary_tree_bt_left_child(__pyx_v_node);
+0129:                 rchild = bt_right_child(node)
        __pyx_v_rchild = __pyx_f_2bp_12_binary_tree_bt_right_child(__pyx_v_node);
 0130: 
+0131:                 if lchild >= self.n_total:
        __pyx_t_7 = ((__pyx_v_lchild >= __pyx_v_self->n_total) != 0);
        if (__pyx_t_7) {
/* … */
        }
+0132:                     continue
          goto __pyx_L17_continue;
 0133: 
+0134:                 elif rchild >= self.n_total:
        __pyx_t_7 = ((__pyx_v_rchild >= __pyx_v_self->n_total) != 0);
        if (__pyx_t_7) {
/* … */
          goto __pyx_L19;
        }
+0135:                     self.mM[node, self.m_idx] = self.mM[lchild, self.m_idx]
          if (unlikely(!__pyx_v_self->mM.memview)) {PyErr_SetString(PyExc_AttributeError,"Memoryview is not initialized");__PYX_ERR(0, 135, __pyx_L4_error)}
          __pyx_t_8 = __pyx_v_lchild;
          __pyx_t_12 = __pyx_v_self->m_idx;
          if (unlikely(!__pyx_v_self->mM.memview)) {PyErr_SetString(PyExc_AttributeError,"Memoryview is not initialized");__PYX_ERR(0, 135, __pyx_L4_error)}
          __pyx_t_14 = __pyx_v_node;
          __pyx_t_15 = __pyx_v_self->m_idx;
          *((__pyx_t_2bp_3_bp_SIZE_t *) ( /* dim=1 */ ((char *) (((__pyx_t_2bp_3_bp_SIZE_t *) ( /* dim=0 */ (__pyx_v_self->mM.data + __pyx_t_14 * __pyx_v_self->mM.strides[0]) )) + __pyx_t_15)) )) = (*((__pyx_t_2bp_3_bp_SIZE_t *) ( /* dim=1 */ ((char *) (((__pyx_t_2bp_3_bp_SIZE_t *) ( /* dim=0 */ (__pyx_v_self->mM.data + __pyx_t_8 * __pyx_v_self->mM.strides[0]) )) + __pyx_t_12)) )));
+0136:                     self.mM[node, self.M_idx] = self.mM[lchild, self.M_idx]
          if (unlikely(!__pyx_v_self->mM.memview)) {PyErr_SetString(PyExc_AttributeError,"Memoryview is not initialized");__PYX_ERR(0, 136, __pyx_L4_error)}
          __pyx_t_12 = __pyx_v_lchild;
          __pyx_t_8 = __pyx_v_self->M_idx;
          if (unlikely(!__pyx_v_self->mM.memview)) {PyErr_SetString(PyExc_AttributeError,"Memoryview is not initialized");__PYX_ERR(0, 136, __pyx_L4_error)}
          __pyx_t_15 = __pyx_v_node;
          __pyx_t_14 = __pyx_v_self->M_idx;
          *((__pyx_t_2bp_3_bp_SIZE_t *) ( /* dim=1 */ ((char *) (((__pyx_t_2bp_3_bp_SIZE_t *) ( /* dim=0 */ (__pyx_v_self->mM.data + __pyx_t_15 * __pyx_v_self->mM.strides[0]) )) + __pyx_t_14)) )) = (*((__pyx_t_2bp_3_bp_SIZE_t *) ( /* dim=1 */ ((char *) (((__pyx_t_2bp_3_bp_SIZE_t *) ( /* dim=0 */ (__pyx_v_self->mM.data + __pyx_t_12 * __pyx_v_self->mM.strides[0]) )) + __pyx_t_8)) )));
 0137:                 else:
+0138:                     self.mM[node, self.m_idx] = min(self.mM[lchild, self.m_idx],
        /*else*/ {
          if (unlikely(!__pyx_v_self->mM.memview)) {PyErr_SetString(PyExc_AttributeError,"Memoryview is not initialized");__PYX_ERR(0, 138, __pyx_L4_error)}
          __pyx_t_8 = __pyx_v_lchild;
          __pyx_t_12 = __pyx_v_self->m_idx;
/* … */
          if (unlikely(!__pyx_v_self->mM.memview)) {PyErr_SetString(PyExc_AttributeError,"Memoryview is not initialized");__PYX_ERR(0, 138, __pyx_L4_error)}
          __pyx_t_16 = __pyx_v_node;
          __pyx_t_17 = __pyx_v_self->m_idx;
          *((__pyx_t_2bp_3_bp_SIZE_t *) ( /* dim=1 */ ((char *) (((__pyx_t_2bp_3_bp_SIZE_t *) ( /* dim=0 */ (__pyx_v_self->mM.data + __pyx_t_16 * __pyx_v_self->mM.strides[0]) )) + __pyx_t_17)) )) = __pyx_f_2bp_3_bp_min((*((__pyx_t_2bp_3_bp_SIZE_t *) ( /* dim=1 */ ((char *) (((__pyx_t_2bp_3_bp_SIZE_t *) ( /* dim=0 */ (__pyx_v_self->mM.data + __pyx_t_8 * __pyx_v_self->mM.strides[0]) )) + __pyx_t_12)) ))), (*((__pyx_t_2bp_3_bp_SIZE_t *) ( /* dim=1 */ ((char *) (((__pyx_t_2bp_3_bp_SIZE_t *) ( /* dim=0 */ (__pyx_v_self->mM.data + __pyx_t_14 * __pyx_v_self->mM.strides[0]) )) + __pyx_t_15)) ))));
+0139:                                                     self.mM[rchild, self.m_idx])
          if (unlikely(!__pyx_v_self->mM.memview)) {PyErr_SetString(PyExc_AttributeError,"Memoryview is not initialized");__PYX_ERR(0, 139, __pyx_L4_error)}
          __pyx_t_14 = __pyx_v_rchild;
          __pyx_t_15 = __pyx_v_self->m_idx;
+0140:                     self.mM[node, self.M_idx] = max(self.mM[lchild, self.M_idx],
          if (unlikely(!__pyx_v_self->mM.memview)) {PyErr_SetString(PyExc_AttributeError,"Memoryview is not initialized");__PYX_ERR(0, 140, __pyx_L4_error)}
          __pyx_t_15 = __pyx_v_lchild;
          __pyx_t_14 = __pyx_v_self->M_idx;
/* … */
          if (unlikely(!__pyx_v_self->mM.memview)) {PyErr_SetString(PyExc_AttributeError,"Memoryview is not initialized");__PYX_ERR(0, 140, __pyx_L4_error)}
          __pyx_t_17 = __pyx_v_node;
          __pyx_t_16 = __pyx_v_self->M_idx;
          *((__pyx_t_2bp_3_bp_SIZE_t *) ( /* dim=1 */ ((char *) (((__pyx_t_2bp_3_bp_SIZE_t *) ( /* dim=0 */ (__pyx_v_self->mM.data + __pyx_t_17 * __pyx_v_self->mM.strides[0]) )) + __pyx_t_16)) )) = __pyx_f_2bp_3_bp_max((*((__pyx_t_2bp_3_bp_SIZE_t *) ( /* dim=1 */ ((char *) (((__pyx_t_2bp_3_bp_SIZE_t *) ( /* dim=0 */ (__pyx_v_self->mM.data + __pyx_t_15 * __pyx_v_self->mM.strides[0]) )) + __pyx_t_14)) ))), (*((__pyx_t_2bp_3_bp_SIZE_t *) ( /* dim=1 */ ((char *) (((__pyx_t_2bp_3_bp_SIZE_t *) ( /* dim=0 */ (__pyx_v_self->mM.data + __pyx_t_12 * __pyx_v_self->mM.strides[0]) )) + __pyx_t_8)) ))));
        }
        __pyx_L19:;
+0141:                                                     self.mM[rchild, self.M_idx])
          if (unlikely(!__pyx_v_self->mM.memview)) {PyErr_SetString(PyExc_AttributeError,"Memoryview is not initialized");__PYX_ERR(0, 141, __pyx_L4_error)}
          __pyx_t_12 = __pyx_v_rchild;
          __pyx_t_8 = __pyx_v_self->M_idx;
 0142: 
+0143:                 self.r[node] = self.r[lchild]
        if (unlikely(!__pyx_v_self->r.memview)) {PyErr_SetString(PyExc_AttributeError,"Memoryview is not initialized");__PYX_ERR(0, 143, __pyx_L4_error)}
        __pyx_t_8 = __pyx_v_lchild;
        if (unlikely(!__pyx_v_self->r.memview)) {PyErr_SetString(PyExc_AttributeError,"Memoryview is not initialized");__PYX_ERR(0, 143, __pyx_L4_error)}
        __pyx_t_12 = __pyx_v_node;
        *((__pyx_t_2bp_3_bp_SIZE_t *) ( /* dim=0 */ (__pyx_v_self->r.data + __pyx_t_12 * __pyx_v_self->r.strides[0]) )) = (*((__pyx_t_2bp_3_bp_SIZE_t *) ( /* dim=0 */ (__pyx_v_self->r.data + __pyx_t_8 * __pyx_v_self->r.strides[0]) )));
        __pyx_L17_continue:;
      }
    }
  }
 0144: 
 0145: 
 0146: @cython.final
+0147: cdef class BP:
struct __pyx_vtabstruct_2bp_3_bp_BP {
  __pyx_t_2bp_3_bp_SIZE_t (*rank)(struct __pyx_obj_2bp_3_bp_BP *, __pyx_t_2bp_3_bp_SIZE_t, __pyx_t_2bp_3_bp_SIZE_t);
  __pyx_t_2bp_3_bp_SIZE_t (*select)(struct __pyx_obj_2bp_3_bp_BP *, __pyx_t_2bp_3_bp_SIZE_t, __pyx_t_2bp_3_bp_SIZE_t);
  __pyx_t_2bp_3_bp_SIZE_t (*_excess)(struct __pyx_obj_2bp_3_bp_BP *, __pyx_t_2bp_3_bp_SIZE_t);
  __pyx_t_2bp_3_bp_SIZE_t (*excess)(struct __pyx_obj_2bp_3_bp_BP *, __pyx_t_2bp_3_bp_SIZE_t);
  __pyx_t_2bp_3_bp_SIZE_t (*fwdsearch)(struct __pyx_obj_2bp_3_bp_BP *, __pyx_t_2bp_3_bp_SIZE_t, int);
  __pyx_t_2bp_3_bp_SIZE_t (*bwdsearch)(struct __pyx_obj_2bp_3_bp_BP *, __pyx_t_2bp_3_bp_SIZE_t, int);
  __pyx_t_2bp_3_bp_SIZE_t (*close)(struct __pyx_obj_2bp_3_bp_BP *, __pyx_t_2bp_3_bp_SIZE_t, int __pyx_skip_dispatch);
  __pyx_t_2bp_3_bp_SIZE_t (*open)(struct __pyx_obj_2bp_3_bp_BP *, __pyx_t_2bp_3_bp_SIZE_t);
  __pyx_t_2bp_3_bp_BOOL_t (*isleaf)(struct __pyx_obj_2bp_3_bp_BP *, __pyx_t_2bp_3_bp_SIZE_t, int __pyx_skip_dispatch);
  __pyx_t_2bp_3_bp_SIZE_t (*enclose)(struct __pyx_obj_2bp_3_bp_BP *, __pyx_t_2bp_3_bp_SIZE_t);
  struct __pyx_obj_2bp_3_bp_BP *(*_mask_from_self)(struct __pyx_obj_2bp_3_bp_BP *, struct BIT_ARRAY *, PyArrayObject *);
  __pyx_t_2bp_3_bp_SIZE_t (*nsibling)(struct __pyx_obj_2bp_3_bp_BP *, __pyx_t_2bp_3_bp_SIZE_t, int __pyx_skip_dispatch);
  __pyx_t_2bp_3_bp_SIZE_t (*psibling)(struct __pyx_obj_2bp_3_bp_BP *, __pyx_t_2bp_3_bp_SIZE_t, int __pyx_skip_dispatch);
  __pyx_t_2bp_3_bp_SIZE_t (*lchild)(struct __pyx_obj_2bp_3_bp_BP *, __pyx_t_2bp_3_bp_SIZE_t, int __pyx_skip_dispatch);
  __pyx_t_2bp_3_bp_SIZE_t (*fchild)(struct __pyx_obj_2bp_3_bp_BP *, __pyx_t_2bp_3_bp_SIZE_t, int __pyx_skip_dispatch);
  __pyx_t_2bp_3_bp_SIZE_t (*parent)(struct __pyx_obj_2bp_3_bp_BP *, __pyx_t_2bp_3_bp_SIZE_t, int __pyx_skip_dispatch);
  __pyx_t_2bp_3_bp_SIZE_t (*depth)(struct __pyx_obj_2bp_3_bp_BP *, __pyx_t_2bp_3_bp_SIZE_t, int __pyx_skip_dispatch);
  __pyx_t_2bp_3_bp_SIZE_t (*root)(struct __pyx_obj_2bp_3_bp_BP *, int __pyx_skip_dispatch);
  int (*scan_block_forward)(struct __pyx_obj_2bp_3_bp_BP *, int, int, int, int);
  int (*scan_block_backward)(struct __pyx_obj_2bp_3_bp_BP *, int, int, int, int);
  void (*_set_edges)(struct __pyx_obj_2bp_3_bp_BP *, PyArrayObject *);
  PyObject *(*name)(struct __pyx_obj_2bp_3_bp_BP *, __pyx_t_2bp_3_bp_SIZE_t, int __pyx_skip_dispatch);
  __pyx_t_2bp_3_bp_DOUBLE_t (*length)(struct __pyx_obj_2bp_3_bp_BP *, __pyx_t_2bp_3_bp_SIZE_t, int __pyx_skip_dispatch);
  __pyx_t_2bp_3_bp_INT32_t (*edge)(struct __pyx_obj_2bp_3_bp_BP *, __pyx_t_2bp_3_bp_SIZE_t, int __pyx_skip_dispatch);
  __pyx_t_2bp_3_bp_SIZE_t (*edge_from_number)(struct __pyx_obj_2bp_3_bp_BP *, __pyx_t_2bp_3_bp_INT32_t, int __pyx_skip_dispatch);
  __pyx_t_2bp_3_bp_SIZE_t (*rmq)(struct __pyx_obj_2bp_3_bp_BP *, __pyx_t_2bp_3_bp_SIZE_t, __pyx_t_2bp_3_bp_SIZE_t, int __pyx_skip_dispatch);
  __pyx_t_2bp_3_bp_SIZE_t (*rMq)(struct __pyx_obj_2bp_3_bp_BP *, __pyx_t_2bp_3_bp_SIZE_t, __pyx_t_2bp_3_bp_SIZE_t, int __pyx_skip_dispatch);
  __pyx_t_2bp_3_bp_SIZE_t (*postorderselect)(struct __pyx_obj_2bp_3_bp_BP *, __pyx_t_2bp_3_bp_SIZE_t, int __pyx_skip_dispatch);
  __pyx_t_2bp_3_bp_SIZE_t (*postorder)(struct __pyx_obj_2bp_3_bp_BP *, __pyx_t_2bp_3_bp_SIZE_t, int __pyx_skip_dispatch);
  __pyx_t_2bp_3_bp_SIZE_t (*preorderselect)(struct __pyx_obj_2bp_3_bp_BP *, __pyx_t_2bp_3_bp_SIZE_t, int __pyx_skip_dispatch);
  __pyx_t_2bp_3_bp_SIZE_t (*preorder)(struct __pyx_obj_2bp_3_bp_BP *, __pyx_t_2bp_3_bp_SIZE_t, int __pyx_skip_dispatch);
  __pyx_t_2bp_3_bp_BOOL_t (*isancestor)(struct __pyx_obj_2bp_3_bp_BP *, __pyx_t_2bp_3_bp_SIZE_t, __pyx_t_2bp_3_bp_SIZE_t, int __pyx_skip_dispatch);
  __pyx_t_2bp_3_bp_SIZE_t (*levelancestor)(struct __pyx_obj_2bp_3_bp_BP *, __pyx_t_2bp_3_bp_SIZE_t, __pyx_t_2bp_3_bp_SIZE_t, int __pyx_skip_dispatch);
  __pyx_t_2bp_3_bp_SIZE_t (*subtree)(struct __pyx_obj_2bp_3_bp_BP *, __pyx_t_2bp_3_bp_SIZE_t, int __pyx_skip_dispatch);
  struct __pyx_obj_2bp_3_bp_BP *(*shear)(struct __pyx_obj_2bp_3_bp_BP *, PyObject *, int __pyx_skip_dispatch);
  struct __pyx_obj_2bp_3_bp_BP *(*collapse)(struct __pyx_obj_2bp_3_bp_BP *, int __pyx_skip_dispatch);
  __pyx_t_2bp_3_bp_SIZE_t (*ntips)(struct __pyx_obj_2bp_3_bp_BP *, int __pyx_skip_dispatch);
  __pyx_t_2bp_3_bp_SIZE_t (*levelnext)(struct __pyx_obj_2bp_3_bp_BP *, __pyx_t_2bp_3_bp_SIZE_t, int __pyx_skip_dispatch);
  __pyx_t_2bp_3_bp_SIZE_t (*height)(struct __pyx_obj_2bp_3_bp_BP *, __pyx_t_2bp_3_bp_SIZE_t, int __pyx_skip_dispatch);
  __pyx_t_2bp_3_bp_SIZE_t (*deepestnode)(struct __pyx_obj_2bp_3_bp_BP *, __pyx_t_2bp_3_bp_SIZE_t, int __pyx_skip_dispatch);
  __pyx_t_2bp_3_bp_SIZE_t (*lca)(struct __pyx_obj_2bp_3_bp_BP *, __pyx_t_2bp_3_bp_SIZE_t, __pyx_t_2bp_3_bp_SIZE_t, int __pyx_skip_dispatch);
};
static struct __pyx_vtabstruct_2bp_3_bp_BP *__pyx_vtabptr_2bp_3_bp_BP;
static CYTHON_INLINE __pyx_t_2bp_3_bp_SIZE_t __pyx_f_2bp_3_bp_2BP_rank(struct __pyx_obj_2bp_3_bp_BP *, __pyx_t_2bp_3_bp_SIZE_t, __pyx_t_2bp_3_bp_SIZE_t);
static CYTHON_INLINE __pyx_t_2bp_3_bp_SIZE_t __pyx_f_2bp_3_bp_2BP_select(struct __pyx_obj_2bp_3_bp_BP *, __pyx_t_2bp_3_bp_SIZE_t, __pyx_t_2bp_3_bp_SIZE_t);
static __pyx_t_2bp_3_bp_SIZE_t __pyx_f_2bp_3_bp_2BP__excess(struct __pyx_obj_2bp_3_bp_BP *, __pyx_t_2bp_3_bp_SIZE_t);
static __pyx_t_2bp_3_bp_SIZE_t __pyx_f_2bp_3_bp_2BP_excess(struct __pyx_obj_2bp_3_bp_BP *, __pyx_t_2bp_3_bp_SIZE_t);
static __pyx_t_2bp_3_bp_SIZE_t __pyx_f_2bp_3_bp_2BP_fwdsearch(struct __pyx_obj_2bp_3_bp_BP *, __pyx_t_2bp_3_bp_SIZE_t, int);
static __pyx_t_2bp_3_bp_SIZE_t __pyx_f_2bp_3_bp_2BP_bwdsearch(struct __pyx_obj_2bp_3_bp_BP *, __pyx_t_2bp_3_bp_SIZE_t, int);
static CYTHON_INLINE __pyx_t_2bp_3_bp_SIZE_t __pyx_f_2bp_3_bp_2BP_close(struct __pyx_obj_2bp_3_bp_BP *, __pyx_t_2bp_3_bp_SIZE_t, int __pyx_skip_dispatch);
static CYTHON_INLINE __pyx_t_2bp_3_bp_SIZE_t __pyx_f_2bp_3_bp_2BP_open(struct __pyx_obj_2bp_3_bp_BP *, __pyx_t_2bp_3_bp_SIZE_t);
static CYTHON_INLINE __pyx_t_2bp_3_bp_BOOL_t __pyx_f_2bp_3_bp_2BP_isleaf(struct __pyx_obj_2bp_3_bp_BP *, __pyx_t_2bp_3_bp_SIZE_t, int __pyx_skip_dispatch);
static CYTHON_INLINE __pyx_t_2bp_3_bp_SIZE_t __pyx_f_2bp_3_bp_2BP_enclose(struct __pyx_obj_2bp_3_bp_BP *, __pyx_t_2bp_3_bp_SIZE_t);
static struct __pyx_obj_2bp_3_bp_BP *__pyx_f_2bp_3_bp_2BP__mask_from_self(struct __pyx_obj_2bp_3_bp_BP *, struct BIT_ARRAY *, PyArrayObject *);
static __pyx_t_2bp_3_bp_SIZE_t __pyx_f_2bp_3_bp_2BP_nsibling(struct __pyx_obj_2bp_3_bp_BP *, __pyx_t_2bp_3_bp_SIZE_t, int __pyx_skip_dispatch);
static __pyx_t_2bp_3_bp_SIZE_t __pyx_f_2bp_3_bp_2BP_psibling(struct __pyx_obj_2bp_3_bp_BP *, __pyx_t_2bp_3_bp_SIZE_t, int __pyx_skip_dispatch);
static __pyx_t_2bp_3_bp_SIZE_t __pyx_f_2bp_3_bp_2BP_lchild(struct __pyx_obj_2bp_3_bp_BP *, __pyx_t_2bp_3_bp_SIZE_t, int __pyx_skip_dispatch);
static __pyx_t_2bp_3_bp_SIZE_t __pyx_f_2bp_3_bp_2BP_fchild(struct __pyx_obj_2bp_3_bp_BP *, __pyx_t_2bp_3_bp_SIZE_t, int __pyx_skip_dispatch);
static __pyx_t_2bp_3_bp_SIZE_t __pyx_f_2bp_3_bp_2BP_parent(struct __pyx_obj_2bp_3_bp_BP *, __pyx_t_2bp_3_bp_SIZE_t, int __pyx_skip_dispatch);
static __pyx_t_2bp_3_bp_SIZE_t __pyx_f_2bp_3_bp_2BP_depth(struct __pyx_obj_2bp_3_bp_BP *, __pyx_t_2bp_3_bp_SIZE_t, int __pyx_skip_dispatch);
static __pyx_t_2bp_3_bp_SIZE_t __pyx_f_2bp_3_bp_2BP_root(struct __pyx_obj_2bp_3_bp_BP *, int __pyx_skip_dispatch);
static int __pyx_f_2bp_3_bp_2BP_scan_block_forward(struct __pyx_obj_2bp_3_bp_BP *, int, int, int, int);
static int __pyx_f_2bp_3_bp_2BP_scan_block_backward(struct __pyx_obj_2bp_3_bp_BP *, int, int, int, int);
static void __pyx_f_2bp_3_bp_2BP__set_edges(struct __pyx_obj_2bp_3_bp_BP *, PyArrayObject *);
static CYTHON_INLINE PyObject *__pyx_f_2bp_3_bp_2BP_name(struct __pyx_obj_2bp_3_bp_BP *, __pyx_t_2bp_3_bp_SIZE_t, int __pyx_skip_dispatch);
static CYTHON_INLINE __pyx_t_2bp_3_bp_DOUBLE_t __pyx_f_2bp_3_bp_2BP_length(struct __pyx_obj_2bp_3_bp_BP *, __pyx_t_2bp_3_bp_SIZE_t, int __pyx_skip_dispatch);
static CYTHON_INLINE __pyx_t_2bp_3_bp_INT32_t __pyx_f_2bp_3_bp_2BP_edge(struct __pyx_obj_2bp_3_bp_BP *, __pyx_t_2bp_3_bp_SIZE_t, int __pyx_skip_dispatch);
static __pyx_t_2bp_3_bp_SIZE_t __pyx_f_2bp_3_bp_2BP_edge_from_number(struct __pyx_obj_2bp_3_bp_BP *, __pyx_t_2bp_3_bp_INT32_t, int __pyx_skip_dispatch);
static __pyx_t_2bp_3_bp_SIZE_t __pyx_f_2bp_3_bp_2BP_rmq(struct __pyx_obj_2bp_3_bp_BP *, __pyx_t_2bp_3_bp_SIZE_t, __pyx_t_2bp_3_bp_SIZE_t, int __pyx_skip_dispatch);
static __pyx_t_2bp_3_bp_SIZE_t __pyx_f_2bp_3_bp_2BP_rMq(struct __pyx_obj_2bp_3_bp_BP *, __pyx_t_2bp_3_bp_SIZE_t, __pyx_t_2bp_3_bp_SIZE_t, int __pyx_skip_dispatch);
static __pyx_t_2bp_3_bp_SIZE_t __pyx_f_2bp_3_bp_2BP_postorderselect(struct __pyx_obj_2bp_3_bp_BP *, __pyx_t_2bp_3_bp_SIZE_t, int __pyx_skip_dispatch);
static __pyx_t_2bp_3_bp_SIZE_t __pyx_f_2bp_3_bp_2BP_postorder(struct __pyx_obj_2bp_3_bp_BP *, __pyx_t_2bp_3_bp_SIZE_t, int __pyx_skip_dispatch);
static __pyx_t_2bp_3_bp_SIZE_t __pyx_f_2bp_3_bp_2BP_preorderselect(struct __pyx_obj_2bp_3_bp_BP *, __pyx_t_2bp_3_bp_SIZE_t, int __pyx_skip_dispatch);
static __pyx_t_2bp_3_bp_SIZE_t __pyx_f_2bp_3_bp_2BP_preorder(struct __pyx_obj_2bp_3_bp_BP *, __pyx_t_2bp_3_bp_SIZE_t, int __pyx_skip_dispatch);
static __pyx_t_2bp_3_bp_BOOL_t __pyx_f_2bp_3_bp_2BP_isancestor(struct __pyx_obj_2bp_3_bp_BP *, __pyx_t_2bp_3_bp_SIZE_t, __pyx_t_2bp_3_bp_SIZE_t, int __pyx_skip_dispatch);
static __pyx_t_2bp_3_bp_SIZE_t __pyx_f_2bp_3_bp_2BP_levelancestor(struct __pyx_obj_2bp_3_bp_BP *, __pyx_t_2bp_3_bp_SIZE_t, __pyx_t_2bp_3_bp_SIZE_t, int __pyx_skip_dispatch);
static __pyx_t_2bp_3_bp_SIZE_t __pyx_f_2bp_3_bp_2BP_subtree(struct __pyx_obj_2bp_3_bp_BP *, __pyx_t_2bp_3_bp_SIZE_t, int __pyx_skip_dispatch);
static struct __pyx_obj_2bp_3_bp_BP *__pyx_f_2bp_3_bp_2BP_shear(struct __pyx_obj_2bp_3_bp_BP *, PyObject *, int __pyx_skip_dispatch);
static struct __pyx_obj_2bp_3_bp_BP *__pyx_f_2bp_3_bp_2BP_collapse(struct __pyx_obj_2bp_3_bp_BP *, int __pyx_skip_dispatch);
static __pyx_t_2bp_3_bp_SIZE_t __pyx_f_2bp_3_bp_2BP_ntips(struct __pyx_obj_2bp_3_bp_BP *, int __pyx_skip_dispatch);
static __pyx_t_2bp_3_bp_SIZE_t __pyx_f_2bp_3_bp_2BP_levelnext(struct __pyx_obj_2bp_3_bp_BP *, __pyx_t_2bp_3_bp_SIZE_t, int __pyx_skip_dispatch);
static __pyx_t_2bp_3_bp_SIZE_t __pyx_f_2bp_3_bp_2BP_height(struct __pyx_obj_2bp_3_bp_BP *, __pyx_t_2bp_3_bp_SIZE_t, int __pyx_skip_dispatch);
static __pyx_t_2bp_3_bp_SIZE_t __pyx_f_2bp_3_bp_2BP_deepestnode(struct __pyx_obj_2bp_3_bp_BP *, __pyx_t_2bp_3_bp_SIZE_t, int __pyx_skip_dispatch);
static __pyx_t_2bp_3_bp_SIZE_t __pyx_f_2bp_3_bp_2BP_lca(struct __pyx_obj_2bp_3_bp_BP *, __pyx_t_2bp_3_bp_SIZE_t, __pyx_t_2bp_3_bp_SIZE_t, int __pyx_skip_dispatch);

 0148:     """A balanced parentheses succinct data structure tree representation
 0149: 
 0150:     The basis for this implementation is the data structure described by
 0151:     Cordova and Navarro [1]. In some instances, some docstring text was copied
 0152:     verbatim from the manuscript. This does not implement the bucket-based
 0153:     trees, although that would be a very interesting next step. 
 0154: 
 0155:     A node in this data structure is represented by 2 bits, an open parenthesis
 0156:     and a close parenthesis. The implementation uses a numpy uint8 type where
 0157:     an open parenthesis is a 1 and a close is a 0. In general, operations on
 0158:     this tree are best suited for passing in the opening parenthesis index, so
 0159:     for instance, if you'd like to use BP.isleaf to determine if a node is a 
 0160:     leaf, the operation is defined only for using the opening parenthesis. At 
 0161:     this time, there is some ambiguity over what methods can handle a closing
 0162:     parenthesis.
 0163: 
 0164:     Node attributes, such as names, are stored external to this data structure.
 0165: 
 0166:     The motivator for this data structure is pure performance both in space and
 0167:     time. As such, there is minimal sanity checking. It is advised to use this
 0168:     structure with care, and ideally within a framework which can assure 
 0169:     sanity. 
 0170: 
 0171:     References
 0172:     ----------
 0173:     [1] http://www.dcc.uchile.cl/~gnavarro/ps/tcs16.2.pdf
 0174:     """
 0175: 
+0176:     def __cinit__(self, np.ndarray[BOOL_t, ndim=1] B,
/* Python wrapper */
static int __pyx_pw_2bp_3_bp_2BP_1__cinit__(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
static int __pyx_pw_2bp_3_bp_2BP_1__cinit__(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
  PyArrayObject *__pyx_v_B = 0;
  PyArrayObject *__pyx_v_lengths = 0;
  PyArrayObject *__pyx_v_names = 0;
  PyArrayObject *__pyx_v_edges = 0;
  int __pyx_r;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("__cinit__ (wrapper)", 0);
  {
    static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_B,&__pyx_n_s_lengths,&__pyx_n_s_names,&__pyx_n_s_edges,0};
    PyObject* values[4] = {0,0,0,0};
/* … */
  /* function exit code */
  goto __pyx_L0;
  __pyx_L1_error:;
  __pyx_r = -1;
  __pyx_L0:;
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}

static int __pyx_pf_2bp_3_bp_2BP___cinit__(struct __pyx_obj_2bp_3_bp_BP *__pyx_v_self, PyArrayObject *__pyx_v_B, PyArrayObject *__pyx_v_lengths, PyArrayObject *__pyx_v_names, PyArrayObject *__pyx_v_edges) {
  __pyx_t_2bp_3_bp_SIZE_t __pyx_v_i;
  __Pyx_memviewslice __pyx_v__e_index = { 0, 0, { 0 }, { 0 }, { 0 } };
  __Pyx_memviewslice __pyx_v__k_index_0 = { 0, 0, { 0 }, { 0 }, { 0 } };
  __Pyx_memviewslice __pyx_v__k_index_1 = { 0, 0, { 0 }, { 0 }, { 0 } };
  __Pyx_memviewslice __pyx_v__r_index_0 = { 0, 0, { 0 }, { 0 }, { 0 } };
  __Pyx_memviewslice __pyx_v__r_index_1 = { 0, 0, { 0 }, { 0 }, { 0 } };
  __Pyx_LocalBuf_ND __pyx_pybuffernd_B;
  __Pyx_Buffer __pyx_pybuffer_B;
  __Pyx_LocalBuf_ND __pyx_pybuffernd_edges;
  __Pyx_Buffer __pyx_pybuffer_edges;
  __Pyx_LocalBuf_ND __pyx_pybuffernd_lengths;
  __Pyx_Buffer __pyx_pybuffer_lengths;
  __Pyx_LocalBuf_ND __pyx_pybuffernd_names;
  __Pyx_Buffer __pyx_pybuffer_names;
  int __pyx_r;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("__cinit__", 0);
  __pyx_pybuffer_B.pybuffer.buf = NULL;
  __pyx_pybuffer_B.refcount = 0;
  __pyx_pybuffernd_B.data = NULL;
  __pyx_pybuffernd_B.rcbuffer = &__pyx_pybuffer_B;
  __pyx_pybuffer_lengths.pybuffer.buf = NULL;
  __pyx_pybuffer_lengths.refcount = 0;
  __pyx_pybuffernd_lengths.data = NULL;
  __pyx_pybuffernd_lengths.rcbuffer = &__pyx_pybuffer_lengths;
  __pyx_pybuffer_names.pybuffer.buf = NULL;
  __pyx_pybuffer_names.refcount = 0;
  __pyx_pybuffernd_names.data = NULL;
  __pyx_pybuffernd_names.rcbuffer = &__pyx_pybuffer_names;
  __pyx_pybuffer_edges.pybuffer.buf = NULL;
  __pyx_pybuffer_edges.refcount = 0;
  __pyx_pybuffernd_edges.data = NULL;
  __pyx_pybuffernd_edges.rcbuffer = &__pyx_pybuffer_edges;
  {
    __Pyx_BufFmt_StackElem __pyx_stack[1];
    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_B.rcbuffer->pybuffer, (PyObject*)__pyx_v_B, &__Pyx_TypeInfo_nn___pyx_t_2bp_3_bp_BOOL_t, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) __PYX_ERR(0, 176, __pyx_L1_error)
  }
  __pyx_pybuffernd_B.diminfo[0].strides = __pyx_pybuffernd_B.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_B.diminfo[0].shape = __pyx_pybuffernd_B.rcbuffer->pybuffer.shape[0];
  {
    __Pyx_BufFmt_StackElem __pyx_stack[1];
    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_lengths.rcbuffer->pybuffer, (PyObject*)__pyx_v_lengths, &__Pyx_TypeInfo_nn___pyx_t_2bp_3_bp_DOUBLE_t, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) __PYX_ERR(0, 176, __pyx_L1_error)
  }
  __pyx_pybuffernd_lengths.diminfo[0].strides = __pyx_pybuffernd_lengths.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_lengths.diminfo[0].shape = __pyx_pybuffernd_lengths.rcbuffer->pybuffer.shape[0];
  {
    __Pyx_BufFmt_StackElem __pyx_stack[1];
    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_names.rcbuffer->pybuffer, (PyObject*)__pyx_v_names, &__Pyx_TypeInfo_object, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) __PYX_ERR(0, 176, __pyx_L1_error)
  }
  __pyx_pybuffernd_names.diminfo[0].strides = __pyx_pybuffernd_names.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_names.diminfo[0].shape = __pyx_pybuffernd_names.rcbuffer->pybuffer.shape[0];
  {
    __Pyx_BufFmt_StackElem __pyx_stack[1];
    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_edges.rcbuffer->pybuffer, (PyObject*)__pyx_v_edges, &__Pyx_TypeInfo_nn___pyx_t_2bp_3_bp_INT32_t, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) __PYX_ERR(0, 176, __pyx_L1_error)
  }
  __pyx_pybuffernd_edges.diminfo[0].strides = __pyx_pybuffernd_edges.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_edges.diminfo[0].shape = __pyx_pybuffernd_edges.rcbuffer->pybuffer.shape[0];
/* … */
  /* function exit code */
  __pyx_r = 0;
  goto __pyx_L0;
  __pyx_L1_error:;
  __Pyx_XDECREF(__pyx_t_1);
  __Pyx_XDECREF(__pyx_t_2);
  __Pyx_XDECREF(__pyx_t_3);
  __Pyx_XDECREF(__pyx_t_9);
  __PYX_XDEC_MEMVIEW(&__pyx_t_10, 1);
  __Pyx_XDECREF(__pyx_t_11);
  { PyObject *__pyx_type, *__pyx_value, *__pyx_tb;
    __Pyx_PyThreadState_declare
    __Pyx_PyThreadState_assign
    __Pyx_ErrFetch(&__pyx_type, &__pyx_value, &__pyx_tb);
    __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_B.rcbuffer->pybuffer);
    __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_edges.rcbuffer->pybuffer);
    __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_lengths.rcbuffer->pybuffer);
    __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_names.rcbuffer->pybuffer);
  __Pyx_ErrRestore(__pyx_type, __pyx_value, __pyx_tb);}
  __Pyx_AddTraceback("bp._bp.BP.__cinit__", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __pyx_r = -1;
  goto __pyx_L2;
  __pyx_L0:;
  __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_B.rcbuffer->pybuffer);
  __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_edges.rcbuffer->pybuffer);
  __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_lengths.rcbuffer->pybuffer);
  __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_names.rcbuffer->pybuffer);
  __pyx_L2:;
  __PYX_XDEC_MEMVIEW(&__pyx_v__e_index, 1);
  __PYX_XDEC_MEMVIEW(&__pyx_v__k_index_0, 1);
  __PYX_XDEC_MEMVIEW(&__pyx_v__k_index_1, 1);
  __PYX_XDEC_MEMVIEW(&__pyx_v__r_index_0, 1);
  __PYX_XDEC_MEMVIEW(&__pyx_v__r_index_1, 1);
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}
+0177:                   np.ndarray[DOUBLE_t, ndim=1] lengths=None,
    values[1] = (PyObject *)((PyArrayObject *)Py_None);
+0178:                   np.ndarray[object, ndim=1] names=None,
    values[2] = (PyObject *)((PyArrayObject *)Py_None);
+0179:                   np.ndarray[INT32_t, ndim=1] edges=None):
    values[3] = (PyObject *)((PyArrayObject *)Py_None);
    if (unlikely(__pyx_kwds)) {
      Py_ssize_t kw_args;
      const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args);
      switch (pos_args) {
        case  4: values[3] = PyTuple_GET_ITEM(__pyx_args, 3);
        CYTHON_FALLTHROUGH;
        case  3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2);
        CYTHON_FALLTHROUGH;
        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
        CYTHON_FALLTHROUGH;
        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
        CYTHON_FALLTHROUGH;
        case  0: break;
        default: goto __pyx_L5_argtuple_error;
      }
      kw_args = PyDict_Size(__pyx_kwds);
      switch (pos_args) {
        case  0:
        if (likely((values[0] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_B)) != 0)) kw_args--;
        else goto __pyx_L5_argtuple_error;
        CYTHON_FALLTHROUGH;
        case  1:
        if (kw_args > 0) {
          PyObject* value = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_lengths);
          if (value) { values[1] = value; kw_args--; }
        }
        CYTHON_FALLTHROUGH;
        case  2:
        if (kw_args > 0) {
          PyObject* value = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_names);
          if (value) { values[2] = value; kw_args--; }
        }
        CYTHON_FALLTHROUGH;
        case  3:
        if (kw_args > 0) {
          PyObject* value = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_edges);
          if (value) { values[3] = value; kw_args--; }
        }
      }
      if (unlikely(kw_args > 0)) {
        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "__cinit__") < 0)) __PYX_ERR(0, 176, __pyx_L3_error)
      }
    } else {
      switch (PyTuple_GET_SIZE(__pyx_args)) {
        case  4: values[3] = PyTuple_GET_ITEM(__pyx_args, 3);
        CYTHON_FALLTHROUGH;
        case  3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2);
        CYTHON_FALLTHROUGH;
        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
        CYTHON_FALLTHROUGH;
        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
        break;
        default: goto __pyx_L5_argtuple_error;
      }
    }
    __pyx_v_B = ((PyArrayObject *)values[0]);
    __pyx_v_lengths = ((PyArrayObject *)values[1]);
    __pyx_v_names = ((PyArrayObject *)values[2]);
    __pyx_v_edges = ((PyArrayObject *)values[3]);
  }
  goto __pyx_L4_argument_unpacking_done;
  __pyx_L5_argtuple_error:;
  __Pyx_RaiseArgtupleInvalid("__cinit__", 0, 1, 4, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 176, __pyx_L3_error)
  __pyx_L3_error:;
  __Pyx_AddTraceback("bp._bp.BP.__cinit__", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __Pyx_RefNannyFinishContext();
  return -1;
  __pyx_L4_argument_unpacking_done:;
  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_B), __pyx_ptype_5numpy_ndarray, 1, "B", 0))) __PYX_ERR(0, 176, __pyx_L1_error)
  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_lengths), __pyx_ptype_5numpy_ndarray, 1, "lengths", 0))) __PYX_ERR(0, 177, __pyx_L1_error)
  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_names), __pyx_ptype_5numpy_ndarray, 1, "names", 0))) __PYX_ERR(0, 178, __pyx_L1_error)
  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_edges), __pyx_ptype_5numpy_ndarray, 1, "edges", 0))) __PYX_ERR(0, 179, __pyx_L1_error)
  __pyx_r = __pyx_pf_2bp_3_bp_2BP___cinit__(((struct __pyx_obj_2bp_3_bp_BP *)__pyx_v_self), __pyx_v_B, __pyx_v_lengths, __pyx_v_names, __pyx_v_edges);
 0180:         cdef SIZE_t i
 0181:         cdef SIZE_t size
 0182:         cdef SIZE_t[:] _e_index
 0183:         cdef SIZE_t[:] _k_index_0
 0184:         cdef SIZE_t[:] _k_index_1
 0185:         cdef SIZE_t[:] _r_index_0
 0186:         cdef SIZE_t[:] _r_index_1
 0187:         cdef np.ndarray[object, ndim=1] _names
 0188:         cdef np.ndarray[DOUBLE_t, ndim=1] _lengths
 0189:         cdef np.ndarray[INT32_t, ndim=1] _edges
 0190:         cdef np.ndarray[SIZE_t, ndim=1] _edge_lookup
 0191: 
 0192:         # the tree is only valid if it is balanaced
+0193:         assert B.sum() == (float(B.size) / 2)
  #ifndef CYTHON_WITHOUT_ASSERTIONS
  if (unlikely(!Py_OptimizeFlag)) {
    __pyx_t_2 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_B), __pyx_n_s_sum); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 193, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __pyx_t_3 = NULL;
    if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_2))) {
      __pyx_t_3 = PyMethod_GET_SELF(__pyx_t_2);
      if (likely(__pyx_t_3)) {
        PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_2);
        __Pyx_INCREF(__pyx_t_3);
        __Pyx_INCREF(function);
        __Pyx_DECREF_SET(__pyx_t_2, function);
      }
    }
    __pyx_t_1 = (__pyx_t_3) ? __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_t_3) : __Pyx_PyObject_CallNoArg(__pyx_t_2);
    __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0;
    if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 193, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    __pyx_t_2 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_B), __pyx_n_s_size); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 193, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __pyx_t_4 = __Pyx_PyObject_AsDouble(__pyx_t_2); if (unlikely(__pyx_t_4 == ((double)((double)-1)) && PyErr_Occurred())) __PYX_ERR(0, 193, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    __pyx_t_2 = PyFloat_FromDouble((__pyx_t_4 / 2.0)); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 193, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __pyx_t_3 = PyObject_RichCompare(__pyx_t_1, __pyx_t_2, Py_EQ); __Pyx_XGOTREF(__pyx_t_3); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 193, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    __pyx_t_5 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_5 < 0)) __PYX_ERR(0, 193, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
    if (unlikely(!__pyx_t_5)) {
      PyErr_SetNone(PyExc_AssertionError);
      __PYX_ERR(0, 193, __pyx_L1_error)
    }
  }
  #endif
+0194:         self.B = B
  __Pyx_INCREF(((PyObject *)__pyx_v_B));
  __Pyx_GIVEREF(((PyObject *)__pyx_v_B));
  __Pyx_GOTREF(__pyx_v_self->B);
  __Pyx_DECREF(((PyObject *)__pyx_v_self->B));
  __pyx_v_self->B = ((PyArrayObject *)__pyx_v_B);
+0195:         self._b_ptr = &B[0]
  __pyx_t_6 = 0;
  __pyx_v_self->_b_ptr = (&(*__Pyx_BufPtrStrided1d(__pyx_t_2bp_3_bp_BOOL_t *, __pyx_pybuffernd_B.rcbuffer->pybuffer.buf, __pyx_t_6, __pyx_pybuffernd_B.diminfo[0].strides)));
+0196:         self.size = B.size
  __pyx_t_3 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_B), __pyx_n_s_size); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 196, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __pyx_t_7 = __Pyx_PyInt_As_Py_intptr_t(__pyx_t_3); if (unlikely((__pyx_t_7 == ((npy_intp)-1)) && PyErr_Occurred())) __PYX_ERR(0, 196, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  __pyx_v_self->size = __pyx_t_7;
 0197: 
+0198:         self._rmm = mM(B, B.size)
  __pyx_t_3 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_B), __pyx_n_s_size); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 198, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __pyx_t_2 = PyTuple_New(2); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 198, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __Pyx_INCREF(((PyObject *)__pyx_v_B));
  __Pyx_GIVEREF(((PyObject *)__pyx_v_B));
  PyTuple_SET_ITEM(__pyx_t_2, 0, ((PyObject *)__pyx_v_B));
  __Pyx_GIVEREF(__pyx_t_3);
  PyTuple_SET_ITEM(__pyx_t_2, 1, __pyx_t_3);
  __pyx_t_3 = 0;
  __pyx_t_3 = __Pyx_PyObject_Call(((PyObject *)__pyx_ptype_2bp_3_bp_mM), __pyx_t_2, NULL); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 198, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __Pyx_GIVEREF(__pyx_t_3);
  __Pyx_GOTREF(__pyx_v_self->_rmm);
  __Pyx_DECREF(((PyObject *)__pyx_v_self->_rmm));
  __pyx_v_self->_rmm = ((struct __pyx_obj_2bp_3_bp_mM *)__pyx_t_3);
  __pyx_t_3 = 0;
 0199: 
+0200:         if names is not None:
  __pyx_t_5 = (((PyObject *)__pyx_v_names) != Py_None);
  __pyx_t_8 = (__pyx_t_5 != 0);
  if (__pyx_t_8) {
/* … */
    goto __pyx_L3;
  }
+0201:             self._names = names
    __Pyx_INCREF(((PyObject *)__pyx_v_names));
    __Pyx_GIVEREF(((PyObject *)__pyx_v_names));
    __Pyx_GOTREF(__pyx_v_self->_names);
    __Pyx_DECREF(((PyObject *)__pyx_v_self->_names));
    __pyx_v_self->_names = ((PyArrayObject *)__pyx_v_names);
 0202:         else:
+0203:             self._names = np.full(self.B.size, None, dtype=object)
  /*else*/ {
    __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_n_s_np); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 203, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_3);
    __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_n_s_full); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 203, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
    __pyx_t_3 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self->B), __pyx_n_s_size); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 203, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_3);
    __pyx_t_1 = PyTuple_New(2); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 203, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
    __Pyx_GIVEREF(__pyx_t_3);
    PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_t_3);
    __Pyx_INCREF(Py_None);
    __Pyx_GIVEREF(Py_None);
    PyTuple_SET_ITEM(__pyx_t_1, 1, Py_None);
    __pyx_t_3 = 0;
    __pyx_t_3 = __Pyx_PyDict_NewPresized(1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 203, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_3);
    if (PyDict_SetItem(__pyx_t_3, __pyx_n_s_dtype, __pyx_builtin_object) < 0) __PYX_ERR(0, 203, __pyx_L1_error)
    __pyx_t_9 = __Pyx_PyObject_Call(__pyx_t_2, __pyx_t_1, __pyx_t_3); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 203, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_9);
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
    if (!(likely(((__pyx_t_9) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_9, __pyx_ptype_5numpy_ndarray))))) __PYX_ERR(0, 203, __pyx_L1_error)
    __Pyx_GIVEREF(__pyx_t_9);
    __Pyx_GOTREF(__pyx_v_self->_names);
    __Pyx_DECREF(((PyObject *)__pyx_v_self->_names));
    __pyx_v_self->_names = ((PyArrayObject *)__pyx_t_9);
    __pyx_t_9 = 0;
  }
  __pyx_L3:;
 0204: 
+0205:         if lengths is not None:
  __pyx_t_8 = (((PyObject *)__pyx_v_lengths) != Py_None);
  __pyx_t_5 = (__pyx_t_8 != 0);
  if (__pyx_t_5) {
/* … */
    goto __pyx_L4;
  }
+0206:             self._lengths = lengths
    __Pyx_INCREF(((PyObject *)__pyx_v_lengths));
    __Pyx_GIVEREF(((PyObject *)__pyx_v_lengths));
    __Pyx_GOTREF(__pyx_v_self->_lengths);
    __Pyx_DECREF(((PyObject *)__pyx_v_self->_lengths));
    __pyx_v_self->_lengths = ((PyArrayObject *)__pyx_v_lengths);
 0207:         else:
+0208:             self._lengths = np.zeros(self.B.size, dtype=DOUBLE)
  /*else*/ {
    __Pyx_GetModuleGlobalName(__pyx_t_9, __pyx_n_s_np); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 208, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_9);
    __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_t_9, __pyx_n_s_zeros); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 208, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_3);
    __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
    __pyx_t_9 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self->B), __pyx_n_s_size); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 208, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_9);
    __pyx_t_1 = PyTuple_New(1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 208, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
    __Pyx_GIVEREF(__pyx_t_9);
    PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_t_9);
    __pyx_t_9 = 0;
    __pyx_t_9 = __Pyx_PyDict_NewPresized(1); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 208, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_9);
    __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_DOUBLE); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 208, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    if (PyDict_SetItem(__pyx_t_9, __pyx_n_s_dtype, __pyx_t_2) < 0) __PYX_ERR(0, 208, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    __pyx_t_2 = __Pyx_PyObject_Call(__pyx_t_3, __pyx_t_1, __pyx_t_9); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 208, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
    __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
    if (!(likely(((__pyx_t_2) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_2, __pyx_ptype_5numpy_ndarray))))) __PYX_ERR(0, 208, __pyx_L1_error)
    __Pyx_GIVEREF(__pyx_t_2);
    __Pyx_GOTREF(__pyx_v_self->_lengths);
    __Pyx_DECREF(((PyObject *)__pyx_v_self->_lengths));
    __pyx_v_self->_lengths = ((PyArrayObject *)__pyx_t_2);
    __pyx_t_2 = 0;
  }
  __pyx_L4:;
 0209: 
+0210:         if edges is not None:
  __pyx_t_5 = (((PyObject *)__pyx_v_edges) != Py_None);
  __pyx_t_8 = (__pyx_t_5 != 0);
  if (__pyx_t_8) {
/* … */
    goto __pyx_L5;
  }
+0211:             self._set_edges(edges)
    __pyx_f_2bp_3_bp_2BP__set_edges(__pyx_v_self, ((PyArrayObject *)__pyx_v_edges));
 0212:         else:
+0213:             self._edges = np.full(self.B.size, 0, dtype=INT32)
  /*else*/ {
    __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_np); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 213, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __pyx_t_9 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_full); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 213, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_9);
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    __pyx_t_2 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self->B), __pyx_n_s_size); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 213, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __pyx_t_1 = PyTuple_New(2); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 213, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
    __Pyx_GIVEREF(__pyx_t_2);
    PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_t_2);
    __Pyx_INCREF(__pyx_int_0);
    __Pyx_GIVEREF(__pyx_int_0);
    PyTuple_SET_ITEM(__pyx_t_1, 1, __pyx_int_0);
    __pyx_t_2 = 0;
    __pyx_t_2 = __Pyx_PyDict_NewPresized(1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 213, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_n_s_INT32); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 213, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_3);
    if (PyDict_SetItem(__pyx_t_2, __pyx_n_s_dtype, __pyx_t_3) < 0) __PYX_ERR(0, 213, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
    __pyx_t_3 = __Pyx_PyObject_Call(__pyx_t_9, __pyx_t_1, __pyx_t_2); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 213, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_3);
    __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    if (!(likely(((__pyx_t_3) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_3, __pyx_ptype_5numpy_ndarray))))) __PYX_ERR(0, 213, __pyx_L1_error)
    __Pyx_GIVEREF(__pyx_t_3);
    __Pyx_GOTREF(__pyx_v_self->_edges);
    __Pyx_DECREF(((PyObject *)__pyx_v_self->_edges));
    __pyx_v_self->_edges = ((PyArrayObject *)__pyx_t_3);
    __pyx_t_3 = 0;
+0214:             self._edge_lookup = None
    __Pyx_INCREF(Py_None);
    __Pyx_GIVEREF(Py_None);
    __Pyx_GOTREF(__pyx_v_self->_edge_lookup);
    __Pyx_DECREF(((PyObject *)__pyx_v_self->_edge_lookup));
    __pyx_v_self->_edge_lookup = ((PyArrayObject *)Py_None);
  }
  __pyx_L5:;
 0215: 
 0216:         # precursor for select index cache
+0217:         _r_index_0 = np.cumsum((1 - B), dtype=SIZE)
  __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_n_s_np); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 217, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_n_s_cumsum); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 217, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  __pyx_t_3 = PyNumber_Subtract(__pyx_int_1, ((PyObject *)__pyx_v_B)); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 217, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __pyx_t_1 = PyTuple_New(1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 217, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __Pyx_GIVEREF(__pyx_t_3);
  PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_t_3);
  __pyx_t_3 = 0;
  __pyx_t_3 = __Pyx_PyDict_NewPresized(1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 217, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __Pyx_GetModuleGlobalName(__pyx_t_9, __pyx_n_s_SIZE); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 217, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_9);
  if (PyDict_SetItem(__pyx_t_3, __pyx_n_s_dtype, __pyx_t_9) < 0) __PYX_ERR(0, 217, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
  __pyx_t_9 = __Pyx_PyObject_Call(__pyx_t_2, __pyx_t_1, __pyx_t_3); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 217, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_9);
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  __pyx_t_10 = __Pyx_PyObject_to_MemoryviewSlice_ds_nn___pyx_t_2bp_3_bp_SIZE_t(__pyx_t_9, PyBUF_WRITABLE); if (unlikely(!__pyx_t_10.memview)) __PYX_ERR(0, 217, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
  __pyx_v__r_index_0 = __pyx_t_10;
  __pyx_t_10.memview = NULL;
  __pyx_t_10.data = NULL;
+0218:         _r_index_1 = np.cumsum(B, dtype=SIZE)
  __Pyx_GetModuleGlobalName(__pyx_t_9, __pyx_n_s_np); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 218, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_9);
  __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_t_9, __pyx_n_s_cumsum); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 218, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
  __pyx_t_9 = PyTuple_New(1); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 218, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_9);
  __Pyx_INCREF(((PyObject *)__pyx_v_B));
  __Pyx_GIVEREF(((PyObject *)__pyx_v_B));
  PyTuple_SET_ITEM(__pyx_t_9, 0, ((PyObject *)__pyx_v_B));
  __pyx_t_1 = __Pyx_PyDict_NewPresized(1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 218, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_SIZE); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 218, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  if (PyDict_SetItem(__pyx_t_1, __pyx_n_s_dtype, __pyx_t_2) < 0) __PYX_ERR(0, 218, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __pyx_t_2 = __Pyx_PyObject_Call(__pyx_t_3, __pyx_t_9, __pyx_t_1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 218, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_t_10 = __Pyx_PyObject_to_MemoryviewSlice_ds_nn___pyx_t_2bp_3_bp_SIZE_t(__pyx_t_2, PyBUF_WRITABLE); if (unlikely(!__pyx_t_10.memview)) __PYX_ERR(0, 218, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __pyx_v__r_index_1 = __pyx_t_10;
  __pyx_t_10.memview = NULL;
  __pyx_t_10.data = NULL;
 0219: 
 0220:         # construct a select index. These operations are performed frequently,
 0221:         # and easy to cache at a relatively minor memory expense. It cannot be
 0222:         # assumed that open and close will be same length so can't stack
 0223:         #TODO: leverage rmmtree, and calculate select on the fly
+0224:         _k_index_0 = np.unique(_r_index_0,
  __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_np); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 224, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_9 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_unique); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 224, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_9);
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_t_1 = __pyx_memoryview_fromslice(__pyx_v__r_index_0, 1, (PyObject *(*)(char *)) __pyx_memview_get_nn___pyx_t_2bp_3_bp_SIZE_t, (int (*)(char *, PyObject *)) __pyx_memview_set_nn___pyx_t_2bp_3_bp_SIZE_t, 0);; if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 224, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 224, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __Pyx_GIVEREF(__pyx_t_1);
  PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_1);
  __pyx_t_1 = 0;
/* … */
  __pyx_t_11 = __Pyx_PyObject_Call(__pyx_t_9, __pyx_t_3, __pyx_t_1); if (unlikely(!__pyx_t_11)) __PYX_ERR(0, 224, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_11);
  __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+0225:                                return_index=True)[1].astype(SIZE)
  __pyx_t_1 = __Pyx_PyDict_NewPresized(1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 225, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  if (PyDict_SetItem(__pyx_t_1, __pyx_n_s_return_index, Py_True) < 0) __PYX_ERR(0, 225, __pyx_L1_error)
/* … */
  __pyx_t_1 = __Pyx_GetItemInt(__pyx_t_11, 1, long, 1, __Pyx_PyInt_From_long, 0, 0, 0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 225, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __Pyx_DECREF(__pyx_t_11); __pyx_t_11 = 0;
  __pyx_t_11 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_astype); if (unlikely(!__pyx_t_11)) __PYX_ERR(0, 225, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_11);
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_SIZE); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 225, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_3 = NULL;
  if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_11))) {
    __pyx_t_3 = PyMethod_GET_SELF(__pyx_t_11);
    if (likely(__pyx_t_3)) {
      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_11);
      __Pyx_INCREF(__pyx_t_3);
      __Pyx_INCREF(function);
      __Pyx_DECREF_SET(__pyx_t_11, function);
    }
  }
  __pyx_t_2 = (__pyx_t_3) ? __Pyx_PyObject_Call2Args(__pyx_t_11, __pyx_t_3, __pyx_t_1) : __Pyx_PyObject_CallOneArg(__pyx_t_11, __pyx_t_1);
  __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0;
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 225, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __Pyx_DECREF(__pyx_t_11); __pyx_t_11 = 0;
  __pyx_t_10 = __Pyx_PyObject_to_MemoryviewSlice_ds_nn___pyx_t_2bp_3_bp_SIZE_t(__pyx_t_2, PyBUF_WRITABLE); if (unlikely(!__pyx_t_10.memview)) __PYX_ERR(0, 225, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __pyx_v__k_index_0 = __pyx_t_10;
  __pyx_t_10.memview = NULL;
  __pyx_t_10.data = NULL;
+0226:         self._k_index_0 = _k_index_0
  __PYX_XDEC_MEMVIEW(&__pyx_v_self->_k_index_0, 0);
  __PYX_INC_MEMVIEW(&__pyx_v__k_index_0, 0);
  __pyx_v_self->_k_index_0 = __pyx_v__k_index_0;
+0227:         _k_index_1 = np.unique(_r_index_1,
  __Pyx_GetModuleGlobalName(__pyx_t_11, __pyx_n_s_np); if (unlikely(!__pyx_t_11)) __PYX_ERR(0, 227, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_11);
  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_11, __pyx_n_s_unique); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 227, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __Pyx_DECREF(__pyx_t_11); __pyx_t_11 = 0;
  __pyx_t_11 = __pyx_memoryview_fromslice(__pyx_v__r_index_1, 1, (PyObject *(*)(char *)) __pyx_memview_get_nn___pyx_t_2bp_3_bp_SIZE_t, (int (*)(char *, PyObject *)) __pyx_memview_set_nn___pyx_t_2bp_3_bp_SIZE_t, 0);; if (unlikely(!__pyx_t_11)) __PYX_ERR(0, 227, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_11);
  __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 227, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __Pyx_GIVEREF(__pyx_t_11);
  PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_11);
  __pyx_t_11 = 0;
/* … */
  __pyx_t_9 = __Pyx_PyObject_Call(__pyx_t_1, __pyx_t_3, __pyx_t_11); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 227, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_9);
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  __Pyx_DECREF(__pyx_t_11); __pyx_t_11 = 0;
+0228:                                return_index=True)[1].astype(SIZE)
  __pyx_t_11 = __Pyx_PyDict_NewPresized(1); if (unlikely(!__pyx_t_11)) __PYX_ERR(0, 228, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_11);
  if (PyDict_SetItem(__pyx_t_11, __pyx_n_s_return_index, Py_True) < 0) __PYX_ERR(0, 228, __pyx_L1_error)
/* … */
  __pyx_t_11 = __Pyx_GetItemInt(__pyx_t_9, 1, long, 1, __Pyx_PyInt_From_long, 0, 0, 0); if (unlikely(!__pyx_t_11)) __PYX_ERR(0, 228, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_11);
  __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
  __pyx_t_9 = __Pyx_PyObject_GetAttrStr(__pyx_t_11, __pyx_n_s_astype); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 228, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_9);
  __Pyx_DECREF(__pyx_t_11); __pyx_t_11 = 0;
  __Pyx_GetModuleGlobalName(__pyx_t_11, __pyx_n_s_SIZE); if (unlikely(!__pyx_t_11)) __PYX_ERR(0, 228, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_11);
  __pyx_t_3 = NULL;
  if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_9))) {
    __pyx_t_3 = PyMethod_GET_SELF(__pyx_t_9);
    if (likely(__pyx_t_3)) {
      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_9);
      __Pyx_INCREF(__pyx_t_3);
      __Pyx_INCREF(function);
      __Pyx_DECREF_SET(__pyx_t_9, function);
    }
  }
  __pyx_t_2 = (__pyx_t_3) ? __Pyx_PyObject_Call2Args(__pyx_t_9, __pyx_t_3, __pyx_t_11) : __Pyx_PyObject_CallOneArg(__pyx_t_9, __pyx_t_11);
  __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0;
  __Pyx_DECREF(__pyx_t_11); __pyx_t_11 = 0;
  if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 228, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
  __pyx_t_10 = __Pyx_PyObject_to_MemoryviewSlice_ds_nn___pyx_t_2bp_3_bp_SIZE_t(__pyx_t_2, PyBUF_WRITABLE); if (unlikely(!__pyx_t_10.memview)) __PYX_ERR(0, 228, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __pyx_v__k_index_1 = __pyx_t_10;
  __pyx_t_10.memview = NULL;
  __pyx_t_10.data = NULL;
+0229:         self._k_index_1 = _k_index_1
  __PYX_XDEC_MEMVIEW(&__pyx_v_self->_k_index_1, 0);
  __PYX_INC_MEMVIEW(&__pyx_v__k_index_1, 0);
  __pyx_v_self->_k_index_1 = __pyx_v__k_index_1;
 0230: 
 0231:         # construct an excess index. These operations are performed a lot, and
 0232:         # similarly can to rank and select, can be cached at a minimal expense.
 0233:         #TODO: leverage rmm tree, and calculate excess on the fly
+0234:         _e_index = np.empty(B.size, dtype=SIZE)
  __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_np); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 234, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __pyx_t_9 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_empty); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 234, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_9);
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_B), __pyx_n_s_size); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 234, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __pyx_t_11 = PyTuple_New(1); if (unlikely(!__pyx_t_11)) __PYX_ERR(0, 234, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_11);
  __Pyx_GIVEREF(__pyx_t_2);
  PyTuple_SET_ITEM(__pyx_t_11, 0, __pyx_t_2);
  __pyx_t_2 = 0;
  __pyx_t_2 = __Pyx_PyDict_NewPresized(1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 234, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_n_s_SIZE); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 234, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  if (PyDict_SetItem(__pyx_t_2, __pyx_n_s_dtype, __pyx_t_3) < 0) __PYX_ERR(0, 234, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  __pyx_t_3 = __Pyx_PyObject_Call(__pyx_t_9, __pyx_t_11, __pyx_t_2); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 234, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
  __Pyx_DECREF(__pyx_t_11); __pyx_t_11 = 0;
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __pyx_t_10 = __Pyx_PyObject_to_MemoryviewSlice_ds_nn___pyx_t_2bp_3_bp_SIZE_t(__pyx_t_3, PyBUF_WRITABLE); if (unlikely(!__pyx_t_10.memview)) __PYX_ERR(0, 234, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  __pyx_v__e_index = __pyx_t_10;
  __pyx_t_10.memview = NULL;
  __pyx_t_10.data = NULL;
+0235:         for i in range(B.size):
  __pyx_t_3 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_B), __pyx_n_s_size); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 235, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __pyx_t_12 = __Pyx_PyInt_As_long(__pyx_t_3); if (unlikely((__pyx_t_12 == (long)-1) && PyErr_Occurred())) __PYX_ERR(0, 235, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  __pyx_t_13 = __pyx_t_12;
  for (__pyx_t_7 = 0; __pyx_t_7 < __pyx_t_13; __pyx_t_7+=1) {
    __pyx_v_i = __pyx_t_7;
+0236:             _e_index[i] = self._excess(i)
    __pyx_t_6 = __pyx_v_i;
    *((__pyx_t_2bp_3_bp_SIZE_t *) ( /* dim=0 */ (__pyx_v__e_index.data + __pyx_t_6 * __pyx_v__e_index.strides[0]) )) = __pyx_f_2bp_3_bp_2BP__excess(__pyx_v_self, __pyx_v_i);
  }
+0237:         self._e_index = _e_index
  __PYX_XDEC_MEMVIEW(&__pyx_v_self->_e_index, 0);
  __PYX_INC_MEMVIEW(&__pyx_v__e_index, 0);
  __pyx_v_self->_e_index = __pyx_v__e_index;
 0238: 
+0239:     def write(self, object fname):
/* Python wrapper */
static PyObject *__pyx_pw_2bp_3_bp_2BP_3write(PyObject *__pyx_v_self, PyObject *__pyx_v_fname); /*proto*/
static PyObject *__pyx_pw_2bp_3_bp_2BP_3write(PyObject *__pyx_v_self, PyObject *__pyx_v_fname) {
  PyObject *__pyx_r = 0;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("write (wrapper)", 0);
  __pyx_r = __pyx_pf_2bp_3_bp_2BP_2write(((struct __pyx_obj_2bp_3_bp_BP *)__pyx_v_self), ((PyObject *)__pyx_v_fname));

  /* function exit code */
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}

static PyObject *__pyx_pf_2bp_3_bp_2BP_2write(struct __pyx_obj_2bp_3_bp_BP *__pyx_v_self, PyObject *__pyx_v_fname) {
  PyObject *__pyx_r = NULL;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("write", 0);
/* … */
  /* function exit code */
  __pyx_r = Py_None; __Pyx_INCREF(Py_None);
  goto __pyx_L0;
  __pyx_L1_error:;
  __Pyx_XDECREF(__pyx_t_1);
  __Pyx_XDECREF(__pyx_t_2);
  __Pyx_XDECREF(__pyx_t_3);
  __Pyx_XDECREF(__pyx_t_4);
  __Pyx_AddTraceback("bp._bp.BP.write", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __pyx_r = NULL;
  __pyx_L0:;
  __Pyx_XGIVEREF(__pyx_r);
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}
+0240:         np.savez_compressed(fname, names=self._names, lengths=self._lengths,
  __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_np); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 240, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_savez_compressed); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 240, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_t_1 = PyTuple_New(1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 240, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __Pyx_INCREF(__pyx_v_fname);
  __Pyx_GIVEREF(__pyx_v_fname);
  PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_v_fname);
  __pyx_t_3 = __Pyx_PyDict_NewPresized(3); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 240, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  if (PyDict_SetItem(__pyx_t_3, __pyx_n_s_names, ((PyObject *)__pyx_v_self->_names)) < 0) __PYX_ERR(0, 240, __pyx_L1_error)
  if (PyDict_SetItem(__pyx_t_3, __pyx_n_s_lengths, ((PyObject *)__pyx_v_self->_lengths)) < 0) __PYX_ERR(0, 240, __pyx_L1_error)
/* … */
  __pyx_t_4 = __Pyx_PyObject_Call(__pyx_t_2, __pyx_t_1, __pyx_t_3); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 240, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+0241:                             B=self.B)
  if (PyDict_SetItem(__pyx_t_3, __pyx_n_s_B, ((PyObject *)__pyx_v_self->B)) < 0) __PYX_ERR(0, 240, __pyx_L1_error)
 0242: 
+0243:     @staticmethod
  __pyx_t_3 = __Pyx_PyObject_CallOneArg(__pyx_builtin_staticmethod, __pyx_t_1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 243, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  if (PyDict_SetItem((PyObject *)__pyx_ptype_2bp_3_bp_BP->tp_dict, __pyx_n_s_read, __pyx_t_3) < 0) __PYX_ERR(0, 244, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  PyType_Modified(__pyx_ptype_2bp_3_bp_BP);
+0244:     def read(object fname):
/* Python wrapper */
static PyObject *__pyx_pw_2bp_3_bp_2BP_5read(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
static PyMethodDef __pyx_mdef_2bp_3_bp_2BP_5read = {"read", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_2bp_3_bp_2BP_5read, METH_VARARGS|METH_KEYWORDS, 0};
static PyObject *__pyx_pw_2bp_3_bp_2BP_5read(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
  PyObject *__pyx_v_fname = 0;
  PyObject *__pyx_r = 0;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("read (wrapper)", 0);
  {
    static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_fname,0};
    PyObject* values[1] = {0};
    if (unlikely(__pyx_kwds)) {
      Py_ssize_t kw_args;
      const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args);
      switch (pos_args) {
        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
        CYTHON_FALLTHROUGH;
        case  0: break;
        default: goto __pyx_L5_argtuple_error;
      }
      kw_args = PyDict_Size(__pyx_kwds);
      switch (pos_args) {
        case  0:
        if (likely((values[0] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_fname)) != 0)) kw_args--;
        else goto __pyx_L5_argtuple_error;
      }
      if (unlikely(kw_args > 0)) {
        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "read") < 0)) __PYX_ERR(0, 244, __pyx_L3_error)
      }
    } else if (PyTuple_GET_SIZE(__pyx_args) != 1) {
      goto __pyx_L5_argtuple_error;
    } else {
      values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
    }
    __pyx_v_fname = values[0];
  }
  goto __pyx_L4_argument_unpacking_done;
  __pyx_L5_argtuple_error:;
  __Pyx_RaiseArgtupleInvalid("read", 1, 1, 1, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 244, __pyx_L3_error)
  __pyx_L3_error:;
  __Pyx_AddTraceback("bp._bp.BP.read", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __Pyx_RefNannyFinishContext();
  return NULL;
  __pyx_L4_argument_unpacking_done:;
  __pyx_r = __pyx_pf_2bp_3_bp_2BP_4read(__pyx_v_fname);
  int __pyx_lineno = 0;
  const char *__pyx_filename = NULL;
  int __pyx_clineno = 0;

  /* function exit code */
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}

static PyObject *__pyx_pf_2bp_3_bp_2BP_4read(PyObject *__pyx_v_fname) {
  PyObject *__pyx_v_data = NULL;
  struct __pyx_obj_2bp_3_bp_BP *__pyx_v_bp = NULL;
  PyObject *__pyx_r = NULL;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("read", 0);
/* … */
  /* function exit code */
  __pyx_L1_error:;
  __Pyx_XDECREF(__pyx_t_1);
  __Pyx_XDECREF(__pyx_t_2);
  __Pyx_XDECREF(__pyx_t_3);
  __Pyx_AddTraceback("bp._bp.BP.read", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __pyx_r = NULL;
  __pyx_L0:;
  __Pyx_XDECREF(__pyx_v_data);
  __Pyx_XDECREF((PyObject *)__pyx_v_bp);
  __Pyx_XGIVEREF(__pyx_r);
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}
/* … */
  __pyx_tuple__25 = PyTuple_Pack(3, __pyx_n_s_fname, __pyx_n_s_data, __pyx_n_s_bp); if (unlikely(!__pyx_tuple__25)) __PYX_ERR(0, 244, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_tuple__25);
  __Pyx_GIVEREF(__pyx_tuple__25);
/* … */
  __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_2bp_3_bp_2BP_5read, NULL, __pyx_n_s_bp__bp); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 244, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  if (PyDict_SetItem((PyObject *)__pyx_ptype_2bp_3_bp_BP->tp_dict, __pyx_n_s_read, __pyx_t_1) < 0) __PYX_ERR(0, 244, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  PyType_Modified(__pyx_ptype_2bp_3_bp_BP);
/* … */
  __Pyx_GetNameInClass(__pyx_t_1, (PyObject *)__pyx_ptype_2bp_3_bp_BP, __pyx_n_s_read); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 244, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_codeobj__26 = (PyObject*)__Pyx_PyCode_New(1, 0, 3, 0, CO_OPTIMIZED|CO_NEWLOCALS, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__25, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_bp__bp_pyx, __pyx_n_s_read, 244, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__26)) __PYX_ERR(0, 244, __pyx_L1_error)
+0245:         data = np.load(fname)
  __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_np); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 245, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_load); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 245, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __pyx_t_2 = NULL;
  if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
    __pyx_t_2 = PyMethod_GET_SELF(__pyx_t_3);
    if (likely(__pyx_t_2)) {
      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
      __Pyx_INCREF(__pyx_t_2);
      __Pyx_INCREF(function);
      __Pyx_DECREF_SET(__pyx_t_3, function);
    }
  }
  __pyx_t_1 = (__pyx_t_2) ? __Pyx_PyObject_Call2Args(__pyx_t_3, __pyx_t_2, __pyx_v_fname) : __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_v_fname);
  __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
  if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 245, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  __pyx_v_data = __pyx_t_1;
  __pyx_t_1 = 0;
+0246:         bp = BP(data['B'], names=data['names'], lengths=data['lengths'])
  __pyx_t_1 = __Pyx_PyObject_Dict_GetItem(__pyx_v_data, __pyx_n_s_B); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 246, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 246, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __Pyx_GIVEREF(__pyx_t_1);
  PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_1);
  __pyx_t_1 = 0;
  __pyx_t_1 = __Pyx_PyDict_NewPresized(2); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 246, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_2 = __Pyx_PyObject_Dict_GetItem(__pyx_v_data, __pyx_n_s_names); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 246, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  if (PyDict_SetItem(__pyx_t_1, __pyx_n_s_names, __pyx_t_2) < 0) __PYX_ERR(0, 246, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __pyx_t_2 = __Pyx_PyObject_Dict_GetItem(__pyx_v_data, __pyx_n_s_lengths); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 246, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  if (PyDict_SetItem(__pyx_t_1, __pyx_n_s_lengths, __pyx_t_2) < 0) __PYX_ERR(0, 246, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __pyx_t_2 = __Pyx_PyObject_Call(((PyObject *)__pyx_ptype_2bp_3_bp_BP), __pyx_t_3, __pyx_t_1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 246, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_v_bp = ((struct __pyx_obj_2bp_3_bp_BP *)__pyx_t_2);
  __pyx_t_2 = 0;
+0247:         return bp
  __Pyx_XDECREF(__pyx_r);
  __Pyx_INCREF(((PyObject *)__pyx_v_bp));
  __pyx_r = ((PyObject *)__pyx_v_bp);
  goto __pyx_L0;
 0248: 
+0249:     def set_names(self, np.ndarray[object, ndim=1] names):
/* Python wrapper */
static PyObject *__pyx_pw_2bp_3_bp_2BP_7set_names(PyObject *__pyx_v_self, PyObject *__pyx_v_names); /*proto*/
static PyObject *__pyx_pw_2bp_3_bp_2BP_7set_names(PyObject *__pyx_v_self, PyObject *__pyx_v_names) {
  PyObject *__pyx_r = 0;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("set_names (wrapper)", 0);
  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_names), __pyx_ptype_5numpy_ndarray, 1, "names", 0))) __PYX_ERR(0, 249, __pyx_L1_error)
  __pyx_r = __pyx_pf_2bp_3_bp_2BP_6set_names(((struct __pyx_obj_2bp_3_bp_BP *)__pyx_v_self), ((PyArrayObject *)__pyx_v_names));
  int __pyx_lineno = 0;
  const char *__pyx_filename = NULL;
  int __pyx_clineno = 0;

  /* function exit code */
  goto __pyx_L0;
  __pyx_L1_error:;
  __pyx_r = NULL;
  __pyx_L0:;
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}

static PyObject *__pyx_pf_2bp_3_bp_2BP_6set_names(struct __pyx_obj_2bp_3_bp_BP *__pyx_v_self, PyArrayObject *__pyx_v_names) {
  __Pyx_LocalBuf_ND __pyx_pybuffernd_names;
  __Pyx_Buffer __pyx_pybuffer_names;
  PyObject *__pyx_r = NULL;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("set_names", 0);
  __pyx_pybuffer_names.pybuffer.buf = NULL;
  __pyx_pybuffer_names.refcount = 0;
  __pyx_pybuffernd_names.data = NULL;
  __pyx_pybuffernd_names.rcbuffer = &__pyx_pybuffer_names;
  {
    __Pyx_BufFmt_StackElem __pyx_stack[1];
    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_names.rcbuffer->pybuffer, (PyObject*)__pyx_v_names, &__Pyx_TypeInfo_object, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) __PYX_ERR(0, 249, __pyx_L1_error)
  }
  __pyx_pybuffernd_names.diminfo[0].strides = __pyx_pybuffernd_names.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_names.diminfo[0].shape = __pyx_pybuffernd_names.rcbuffer->pybuffer.shape[0];
/* … */
  /* function exit code */
  __pyx_r = Py_None; __Pyx_INCREF(Py_None);
  goto __pyx_L0;
  __pyx_L1_error:;
  { PyObject *__pyx_type, *__pyx_value, *__pyx_tb;
    __Pyx_PyThreadState_declare
    __Pyx_PyThreadState_assign
    __Pyx_ErrFetch(&__pyx_type, &__pyx_value, &__pyx_tb);
    __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_names.rcbuffer->pybuffer);
  __Pyx_ErrRestore(__pyx_type, __pyx_value, __pyx_tb);}
  __Pyx_AddTraceback("bp._bp.BP.set_names", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __pyx_r = NULL;
  goto __pyx_L2;
  __pyx_L0:;
  __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_names.rcbuffer->pybuffer);
  __pyx_L2:;
  __Pyx_XGIVEREF(__pyx_r);
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}
+0250:         self._names = names
  __Pyx_INCREF(((PyObject *)__pyx_v_names));
  __Pyx_GIVEREF(((PyObject *)__pyx_v_names));
  __Pyx_GOTREF(__pyx_v_self->_names);
  __Pyx_DECREF(((PyObject *)__pyx_v_self->_names));
  __pyx_v_self->_names = ((PyArrayObject *)__pyx_v_names);
 0251: 
+0252:     def set_lengths(self, np.ndarray[DOUBLE_t, ndim=1] lengths):
/* Python wrapper */
static PyObject *__pyx_pw_2bp_3_bp_2BP_9set_lengths(PyObject *__pyx_v_self, PyObject *__pyx_v_lengths); /*proto*/
static PyObject *__pyx_pw_2bp_3_bp_2BP_9set_lengths(PyObject *__pyx_v_self, PyObject *__pyx_v_lengths) {
  PyObject *__pyx_r = 0;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("set_lengths (wrapper)", 0);
  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_lengths), __pyx_ptype_5numpy_ndarray, 1, "lengths", 0))) __PYX_ERR(0, 252, __pyx_L1_error)
  __pyx_r = __pyx_pf_2bp_3_bp_2BP_8set_lengths(((struct __pyx_obj_2bp_3_bp_BP *)__pyx_v_self), ((PyArrayObject *)__pyx_v_lengths));
  int __pyx_lineno = 0;
  const char *__pyx_filename = NULL;
  int __pyx_clineno = 0;

  /* function exit code */
  goto __pyx_L0;
  __pyx_L1_error:;
  __pyx_r = NULL;
  __pyx_L0:;
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}

static PyObject *__pyx_pf_2bp_3_bp_2BP_8set_lengths(struct __pyx_obj_2bp_3_bp_BP *__pyx_v_self, PyArrayObject *__pyx_v_lengths) {
  __Pyx_LocalBuf_ND __pyx_pybuffernd_lengths;
  __Pyx_Buffer __pyx_pybuffer_lengths;
  PyObject *__pyx_r = NULL;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("set_lengths", 0);
  __pyx_pybuffer_lengths.pybuffer.buf = NULL;
  __pyx_pybuffer_lengths.refcount = 0;
  __pyx_pybuffernd_lengths.data = NULL;
  __pyx_pybuffernd_lengths.rcbuffer = &__pyx_pybuffer_lengths;
  {
    __Pyx_BufFmt_StackElem __pyx_stack[1];
    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_lengths.rcbuffer->pybuffer, (PyObject*)__pyx_v_lengths, &__Pyx_TypeInfo_nn___pyx_t_2bp_3_bp_DOUBLE_t, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) __PYX_ERR(0, 252, __pyx_L1_error)
  }
  __pyx_pybuffernd_lengths.diminfo[0].strides = __pyx_pybuffernd_lengths.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_lengths.diminfo[0].shape = __pyx_pybuffernd_lengths.rcbuffer->pybuffer.shape[0];
/* … */
  /* function exit code */
  __pyx_r = Py_None; __Pyx_INCREF(Py_None);
  goto __pyx_L0;
  __pyx_L1_error:;
  { PyObject *__pyx_type, *__pyx_value, *__pyx_tb;
    __Pyx_PyThreadState_declare
    __Pyx_PyThreadState_assign
    __Pyx_ErrFetch(&__pyx_type, &__pyx_value, &__pyx_tb);
    __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_lengths.rcbuffer->pybuffer);
  __Pyx_ErrRestore(__pyx_type, __pyx_value, __pyx_tb);}
  __Pyx_AddTraceback("bp._bp.BP.set_lengths", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __pyx_r = NULL;
  goto __pyx_L2;
  __pyx_L0:;
  __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_lengths.rcbuffer->pybuffer);
  __pyx_L2:;
  __Pyx_XGIVEREF(__pyx_r);
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}
+0253:         self._lengths = lengths
  __Pyx_INCREF(((PyObject *)__pyx_v_lengths));
  __Pyx_GIVEREF(((PyObject *)__pyx_v_lengths));
  __Pyx_GOTREF(__pyx_v_self->_lengths);
  __Pyx_DECREF(((PyObject *)__pyx_v_self->_lengths));
  __pyx_v_self->_lengths = ((PyArrayObject *)__pyx_v_lengths);
 0254: 
+0255:     cdef void _set_edges(self, np.ndarray[INT32_t, ndim=1] edges):
static void __pyx_f_2bp_3_bp_2BP__set_edges(struct __pyx_obj_2bp_3_bp_BP *__pyx_v_self, PyArrayObject *__pyx_v_edges) {
  int __pyx_v_i;
  int __pyx_v_n;
  __pyx_t_2bp_3_bp_INT32_t __pyx_v_edge;
  PyArrayObject *__pyx_v__edge_lookup = 0;
  PyArrayObject *__pyx_v_b = 0;
  __Pyx_LocalBuf_ND __pyx_pybuffernd__edge_lookup;
  __Pyx_Buffer __pyx_pybuffer__edge_lookup;
  __Pyx_LocalBuf_ND __pyx_pybuffernd_b;
  __Pyx_Buffer __pyx_pybuffer_b;
  __Pyx_LocalBuf_ND __pyx_pybuffernd_edges;
  __Pyx_Buffer __pyx_pybuffer_edges;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("_set_edges", 0);
  __pyx_pybuffer__edge_lookup.pybuffer.buf = NULL;
  __pyx_pybuffer__edge_lookup.refcount = 0;
  __pyx_pybuffernd__edge_lookup.data = NULL;
  __pyx_pybuffernd__edge_lookup.rcbuffer = &__pyx_pybuffer__edge_lookup;
  __pyx_pybuffer_b.pybuffer.buf = NULL;
  __pyx_pybuffer_b.refcount = 0;
  __pyx_pybuffernd_b.data = NULL;
  __pyx_pybuffernd_b.rcbuffer = &__pyx_pybuffer_b;
  __pyx_pybuffer_edges.pybuffer.buf = NULL;
  __pyx_pybuffer_edges.refcount = 0;
  __pyx_pybuffernd_edges.data = NULL;
  __pyx_pybuffernd_edges.rcbuffer = &__pyx_pybuffer_edges;
  {
    __Pyx_BufFmt_StackElem __pyx_stack[1];
    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_edges.rcbuffer->pybuffer, (PyObject*)__pyx_v_edges, &__Pyx_TypeInfo_nn___pyx_t_2bp_3_bp_INT32_t, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) __PYX_ERR(0, 255, __pyx_L1_error)
  }
  __pyx_pybuffernd_edges.diminfo[0].strides = __pyx_pybuffernd_edges.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_edges.diminfo[0].shape = __pyx_pybuffernd_edges.rcbuffer->pybuffer.shape[0];
/* … */
  /* function exit code */
  goto __pyx_L0;
  __pyx_L1_error:;
  __Pyx_XDECREF(__pyx_t_1);
  __Pyx_XDECREF(__pyx_t_6);
  __Pyx_XDECREF(__pyx_t_7);
  __Pyx_XDECREF(__pyx_t_8);
  { PyObject *__pyx_type, *__pyx_value, *__pyx_tb;
    __Pyx_PyThreadState_declare
    __Pyx_PyThreadState_assign
    __Pyx_ErrFetch(&__pyx_type, &__pyx_value, &__pyx_tb);
    __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd__edge_lookup.rcbuffer->pybuffer);
    __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_b.rcbuffer->pybuffer);
    __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_edges.rcbuffer->pybuffer);
  __Pyx_ErrRestore(__pyx_type, __pyx_value, __pyx_tb);}
  __Pyx_WriteUnraisable("bp._bp.BP._set_edges", __pyx_clineno, __pyx_lineno, __pyx_filename, 1, 0);
  goto __pyx_L2;
  __pyx_L0:;
  __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd__edge_lookup.rcbuffer->pybuffer);
  __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_b.rcbuffer->pybuffer);
  __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_edges.rcbuffer->pybuffer);
  __pyx_L2:;
  __Pyx_XDECREF((PyObject *)__pyx_v__edge_lookup);
  __Pyx_XDECREF((PyObject *)__pyx_v_b);
  __Pyx_RefNannyFinishContext();
}
 0256:         cdef:
 0257:             int i, n
 0258:             INT32_t edge
 0259:             np.ndarray[SIZE_t, ndim=1] _edge_lookup
 0260:             np.ndarray[BOOL_t, ndim=1] b
 0261: 
+0262:         b = self.B
  __pyx_t_1 = ((PyObject *)__pyx_v_self->B);
  __Pyx_INCREF(__pyx_t_1);
  {
    __Pyx_BufFmt_StackElem __pyx_stack[1];
    __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_b.rcbuffer->pybuffer);
    __pyx_t_2 = __Pyx_GetBufferAndValidate(&__pyx_pybuffernd_b.rcbuffer->pybuffer, (PyObject*)((PyArrayObject *)__pyx_t_1), &__Pyx_TypeInfo_nn___pyx_t_2bp_3_bp_BOOL_t, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack);
    if (unlikely(__pyx_t_2 < 0)) {
      PyErr_Fetch(&__pyx_t_3, &__pyx_t_4, &__pyx_t_5);
      if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_b.rcbuffer->pybuffer, (PyObject*)__pyx_v_b, &__Pyx_TypeInfo_nn___pyx_t_2bp_3_bp_BOOL_t, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {
        Py_XDECREF(__pyx_t_3); Py_XDECREF(__pyx_t_4); Py_XDECREF(__pyx_t_5);
        __Pyx_RaiseBufferFallbackError();
      } else {
        PyErr_Restore(__pyx_t_3, __pyx_t_4, __pyx_t_5);
      }
      __pyx_t_3 = __pyx_t_4 = __pyx_t_5 = 0;
    }
    __pyx_pybuffernd_b.diminfo[0].strides = __pyx_pybuffernd_b.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_b.diminfo[0].shape = __pyx_pybuffernd_b.rcbuffer->pybuffer.shape[0];
    if (unlikely(__pyx_t_2 < 0)) __PYX_ERR(0, 262, __pyx_L1_error)
  }
  __pyx_v_b = ((PyArrayObject *)__pyx_t_1);
  __pyx_t_1 = 0;
+0263:         n = b.size
  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_b), __pyx_n_s_size); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 263, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_2 = __Pyx_PyInt_As_int(__pyx_t_1); if (unlikely((__pyx_t_2 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 263, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_v_n = __pyx_t_2;
 0264: 
+0265:         _edge_lookup = np.full(n, 0, dtype=SIZE)
  __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_np); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 265, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_6 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_full); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 265, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_6);
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_t_1 = __Pyx_PyInt_From_int(__pyx_v_n); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 265, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_7 = PyTuple_New(2); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 265, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_7);
  __Pyx_GIVEREF(__pyx_t_1);
  PyTuple_SET_ITEM(__pyx_t_7, 0, __pyx_t_1);
  __Pyx_INCREF(__pyx_int_0);
  __Pyx_GIVEREF(__pyx_int_0);
  PyTuple_SET_ITEM(__pyx_t_7, 1, __pyx_int_0);
  __pyx_t_1 = 0;
  __pyx_t_1 = __Pyx_PyDict_NewPresized(1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 265, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __Pyx_GetModuleGlobalName(__pyx_t_8, __pyx_n_s_SIZE); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 265, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_8);
  if (PyDict_SetItem(__pyx_t_1, __pyx_n_s_dtype, __pyx_t_8) < 0) __PYX_ERR(0, 265, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
  __pyx_t_8 = __Pyx_PyObject_Call(__pyx_t_6, __pyx_t_7, __pyx_t_1); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 265, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_8);
  __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
  __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  if (!(likely(((__pyx_t_8) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_8, __pyx_ptype_5numpy_ndarray))))) __PYX_ERR(0, 265, __pyx_L1_error)
  __pyx_t_9 = ((PyArrayObject *)__pyx_t_8);
  {
    __Pyx_BufFmt_StackElem __pyx_stack[1];
    __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd__edge_lookup.rcbuffer->pybuffer);
    __pyx_t_2 = __Pyx_GetBufferAndValidate(&__pyx_pybuffernd__edge_lookup.rcbuffer->pybuffer, (PyObject*)__pyx_t_9, &__Pyx_TypeInfo_nn___pyx_t_2bp_3_bp_SIZE_t, PyBUF_FORMAT| PyBUF_STRIDES| PyBUF_WRITABLE, 1, 0, __pyx_stack);
    if (unlikely(__pyx_t_2 < 0)) {
      PyErr_Fetch(&__pyx_t_5, &__pyx_t_4, &__pyx_t_3);
      if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd__edge_lookup.rcbuffer->pybuffer, (PyObject*)__pyx_v__edge_lookup, &__Pyx_TypeInfo_nn___pyx_t_2bp_3_bp_SIZE_t, PyBUF_FORMAT| PyBUF_STRIDES| PyBUF_WRITABLE, 1, 0, __pyx_stack) == -1)) {
        Py_XDECREF(__pyx_t_5); Py_XDECREF(__pyx_t_4); Py_XDECREF(__pyx_t_3);
        __Pyx_RaiseBufferFallbackError();
      } else {
        PyErr_Restore(__pyx_t_5, __pyx_t_4, __pyx_t_3);
      }
      __pyx_t_5 = __pyx_t_4 = __pyx_t_3 = 0;
    }
    __pyx_pybuffernd__edge_lookup.diminfo[0].strides = __pyx_pybuffernd__edge_lookup.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd__edge_lookup.diminfo[0].shape = __pyx_pybuffernd__edge_lookup.rcbuffer->pybuffer.shape[0];
    if (unlikely(__pyx_t_2 < 0)) __PYX_ERR(0, 265, __pyx_L1_error)
  }
  __pyx_t_9 = 0;
  __pyx_v__edge_lookup = ((PyArrayObject *)__pyx_t_8);
  __pyx_t_8 = 0;
+0266:         for i in range(n):
  __pyx_t_2 = __pyx_v_n;
  __pyx_t_10 = __pyx_t_2;
  for (__pyx_t_11 = 0; __pyx_t_11 < __pyx_t_10; __pyx_t_11+=1) {
    __pyx_v_i = __pyx_t_11;
+0267:             if b[i] == 1:
    __pyx_t_12 = __pyx_v_i;
    __pyx_t_13 = (((*__Pyx_BufPtrStrided1d(__pyx_t_2bp_3_bp_BOOL_t *, __pyx_pybuffernd_b.rcbuffer->pybuffer.buf, __pyx_t_12, __pyx_pybuffernd_b.diminfo[0].strides)) == 1) != 0);
    if (__pyx_t_13) {
/* … */
    }
  }
+0268:                 edge = edges[i]
      __pyx_t_12 = __pyx_v_i;
      __pyx_v_edge = (*__Pyx_BufPtrStrided1d(__pyx_t_2bp_3_bp_INT32_t *, __pyx_pybuffernd_edges.rcbuffer->pybuffer.buf, __pyx_t_12, __pyx_pybuffernd_edges.diminfo[0].strides));
+0269:                 _edge_lookup[edge] = i
      __pyx_t_12 = __pyx_v_edge;
      *__Pyx_BufPtrStrided1d(__pyx_t_2bp_3_bp_SIZE_t *, __pyx_pybuffernd__edge_lookup.rcbuffer->pybuffer.buf, __pyx_t_12, __pyx_pybuffernd__edge_lookup.diminfo[0].strides) = __pyx_v_i;
 0270: 
+0271:         self._edge_lookup = _edge_lookup
  __Pyx_INCREF(((PyObject *)__pyx_v__edge_lookup));
  __Pyx_GIVEREF(((PyObject *)__pyx_v__edge_lookup));
  __Pyx_GOTREF(__pyx_v_self->_edge_lookup);
  __Pyx_DECREF(((PyObject *)__pyx_v_self->_edge_lookup));
  __pyx_v_self->_edge_lookup = ((PyArrayObject *)__pyx_v__edge_lookup);
+0272:         self._edges = edges
  __Pyx_INCREF(((PyObject *)__pyx_v_edges));
  __Pyx_GIVEREF(((PyObject *)__pyx_v_edges));
  __Pyx_GOTREF(__pyx_v_self->_edges);
  __Pyx_DECREF(((PyObject *)__pyx_v_self->_edges));
  __pyx_v_self->_edges = ((PyArrayObject *)__pyx_v_edges);
 0273: 
+0274:     def set_edges(self, np.ndarray[INT32_t, ndim=1] edges):
/* Python wrapper */
static PyObject *__pyx_pw_2bp_3_bp_2BP_11set_edges(PyObject *__pyx_v_self, PyObject *__pyx_v_edges); /*proto*/
static PyObject *__pyx_pw_2bp_3_bp_2BP_11set_edges(PyObject *__pyx_v_self, PyObject *__pyx_v_edges) {
  PyObject *__pyx_r = 0;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("set_edges (wrapper)", 0);
  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_edges), __pyx_ptype_5numpy_ndarray, 1, "edges", 0))) __PYX_ERR(0, 274, __pyx_L1_error)
  __pyx_r = __pyx_pf_2bp_3_bp_2BP_10set_edges(((struct __pyx_obj_2bp_3_bp_BP *)__pyx_v_self), ((PyArrayObject *)__pyx_v_edges));
  int __pyx_lineno = 0;
  const char *__pyx_filename = NULL;
  int __pyx_clineno = 0;

  /* function exit code */
  goto __pyx_L0;
  __pyx_L1_error:;
  __pyx_r = NULL;
  __pyx_L0:;
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}

static PyObject *__pyx_pf_2bp_3_bp_2BP_10set_edges(struct __pyx_obj_2bp_3_bp_BP *__pyx_v_self, PyArrayObject *__pyx_v_edges) {
  __Pyx_LocalBuf_ND __pyx_pybuffernd_edges;
  __Pyx_Buffer __pyx_pybuffer_edges;
  PyObject *__pyx_r = NULL;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("set_edges", 0);
  __pyx_pybuffer_edges.pybuffer.buf = NULL;
  __pyx_pybuffer_edges.refcount = 0;
  __pyx_pybuffernd_edges.data = NULL;
  __pyx_pybuffernd_edges.rcbuffer = &__pyx_pybuffer_edges;
  {
    __Pyx_BufFmt_StackElem __pyx_stack[1];
    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_edges.rcbuffer->pybuffer, (PyObject*)__pyx_v_edges, &__Pyx_TypeInfo_nn___pyx_t_2bp_3_bp_INT32_t, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) __PYX_ERR(0, 274, __pyx_L1_error)
  }
  __pyx_pybuffernd_edges.diminfo[0].strides = __pyx_pybuffernd_edges.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_edges.diminfo[0].shape = __pyx_pybuffernd_edges.rcbuffer->pybuffer.shape[0];
/* … */
  /* function exit code */
  __pyx_r = Py_None; __Pyx_INCREF(Py_None);
  goto __pyx_L0;
  __pyx_L1_error:;
  { PyObject *__pyx_type, *__pyx_value, *__pyx_tb;
    __Pyx_PyThreadState_declare
    __Pyx_PyThreadState_assign
    __Pyx_ErrFetch(&__pyx_type, &__pyx_value, &__pyx_tb);
    __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_edges.rcbuffer->pybuffer);
  __Pyx_ErrRestore(__pyx_type, __pyx_value, __pyx_tb);}
  __Pyx_AddTraceback("bp._bp.BP.set_edges", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __pyx_r = NULL;
  goto __pyx_L2;
  __pyx_L0:;
  __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_edges.rcbuffer->pybuffer);
  __pyx_L2:;
  __Pyx_XGIVEREF(__pyx_r);
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}
+0275:         self._set_edges(edges)
  __pyx_f_2bp_3_bp_2BP__set_edges(__pyx_v_self, ((PyArrayObject *)__pyx_v_edges));
 0276: 
+0277:     cpdef inline unicode name(self, SIZE_t i):
static PyObject *__pyx_pw_2bp_3_bp_2BP_13name(PyObject *__pyx_v_self, PyObject *__pyx_arg_i); /*proto*/
static CYTHON_INLINE PyObject *__pyx_f_2bp_3_bp_2BP_name(struct __pyx_obj_2bp_3_bp_BP *__pyx_v_self, __pyx_t_2bp_3_bp_SIZE_t __pyx_v_i, CYTHON_UNUSED int __pyx_skip_dispatch) {
  PyObject *__pyx_r = NULL;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("name", 0);
/* … */
  /* function exit code */
  __pyx_L1_error:;
  __Pyx_XDECREF(__pyx_t_1);
  __Pyx_AddTraceback("bp._bp.BP.name", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __pyx_r = 0;
  __pyx_L0:;
  __Pyx_XGIVEREF(__pyx_r);
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}

/* Python wrapper */
static PyObject *__pyx_pw_2bp_3_bp_2BP_13name(PyObject *__pyx_v_self, PyObject *__pyx_arg_i); /*proto*/
static PyObject *__pyx_pw_2bp_3_bp_2BP_13name(PyObject *__pyx_v_self, PyObject *__pyx_arg_i) {
  __pyx_t_2bp_3_bp_SIZE_t __pyx_v_i;
  PyObject *__pyx_r = 0;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("name (wrapper)", 0);
  assert(__pyx_arg_i); {
    __pyx_v_i = __Pyx_PyInt_As_Py_intptr_t(__pyx_arg_i); if (unlikely((__pyx_v_i == ((npy_intp)-1)) && PyErr_Occurred())) __PYX_ERR(0, 277, __pyx_L3_error)
  }
  goto __pyx_L4_argument_unpacking_done;
  __pyx_L3_error:;
  __Pyx_AddTraceback("bp._bp.BP.name", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __Pyx_RefNannyFinishContext();
  return NULL;
  __pyx_L4_argument_unpacking_done:;
  __pyx_r = __pyx_pf_2bp_3_bp_2BP_12name(((struct __pyx_obj_2bp_3_bp_BP *)__pyx_v_self), ((__pyx_t_2bp_3_bp_SIZE_t)__pyx_v_i));
  int __pyx_lineno = 0;
  const char *__pyx_filename = NULL;
  int __pyx_clineno = 0;

  /* function exit code */
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}

static PyObject *__pyx_pf_2bp_3_bp_2BP_12name(struct __pyx_obj_2bp_3_bp_BP *__pyx_v_self, __pyx_t_2bp_3_bp_SIZE_t __pyx_v_i) {
  PyObject *__pyx_r = NULL;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("name", 0);
  __Pyx_XDECREF(__pyx_r);
  __pyx_t_1 = __pyx_f_2bp_3_bp_2BP_name(__pyx_v_self, __pyx_v_i, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 277, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_r = __pyx_t_1;
  __pyx_t_1 = 0;
  goto __pyx_L0;

  /* function exit code */
  __pyx_L1_error:;
  __Pyx_XDECREF(__pyx_t_1);
  __Pyx_AddTraceback("bp._bp.BP.name", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __pyx_r = NULL;
  __pyx_L0:;
  __Pyx_XGIVEREF(__pyx_r);
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}
+0278:         return self._names[i]
  __Pyx_XDECREF(__pyx_r);
  __pyx_t_1 = __Pyx_GetItemInt(((PyObject *)__pyx_v_self->_names), __pyx_v_i, __pyx_t_2bp_3_bp_SIZE_t, 1, __Pyx_PyInt_From_Py_intptr_t, 0, 0, 0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 278, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  if (!(likely(PyUnicode_CheckExact(__pyx_t_1))||((__pyx_t_1) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "unicode", Py_TYPE(__pyx_t_1)->tp_name), 0))) __PYX_ERR(0, 278, __pyx_L1_error)
  __pyx_r = ((PyObject*)__pyx_t_1);
  __pyx_t_1 = 0;
  goto __pyx_L0;
 0279: 
+0280:     cpdef inline DOUBLE_t length(self, SIZE_t i):
static PyObject *__pyx_pw_2bp_3_bp_2BP_15length(PyObject *__pyx_v_self, PyObject *__pyx_arg_i); /*proto*/
static CYTHON_INLINE __pyx_t_2bp_3_bp_DOUBLE_t __pyx_f_2bp_3_bp_2BP_length(struct __pyx_obj_2bp_3_bp_BP *__pyx_v_self, __pyx_t_2bp_3_bp_SIZE_t __pyx_v_i, CYTHON_UNUSED int __pyx_skip_dispatch) {
  __pyx_t_2bp_3_bp_DOUBLE_t __pyx_r;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("length", 0);
/* … */
  /* function exit code */
  __pyx_L1_error:;
  __Pyx_XDECREF(__pyx_t_1);
  __Pyx_WriteUnraisable("bp._bp.BP.length", __pyx_clineno, __pyx_lineno, __pyx_filename, 1, 0);
  __pyx_r = 0;
  __pyx_L0:;
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}

/* Python wrapper */
static PyObject *__pyx_pw_2bp_3_bp_2BP_15length(PyObject *__pyx_v_self, PyObject *__pyx_arg_i); /*proto*/
static PyObject *__pyx_pw_2bp_3_bp_2BP_15length(PyObject *__pyx_v_self, PyObject *__pyx_arg_i) {
  __pyx_t_2bp_3_bp_SIZE_t __pyx_v_i;
  PyObject *__pyx_r = 0;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("length (wrapper)", 0);
  assert(__pyx_arg_i); {
    __pyx_v_i = __Pyx_PyInt_As_Py_intptr_t(__pyx_arg_i); if (unlikely((__pyx_v_i == ((npy_intp)-1)) && PyErr_Occurred())) __PYX_ERR(0, 280, __pyx_L3_error)
  }
  goto __pyx_L4_argument_unpacking_done;
  __pyx_L3_error:;
  __Pyx_AddTraceback("bp._bp.BP.length", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __Pyx_RefNannyFinishContext();
  return NULL;
  __pyx_L4_argument_unpacking_done:;
  __pyx_r = __pyx_pf_2bp_3_bp_2BP_14length(((struct __pyx_obj_2bp_3_bp_BP *)__pyx_v_self), ((__pyx_t_2bp_3_bp_SIZE_t)__pyx_v_i));
  int __pyx_lineno = 0;
  const char *__pyx_filename = NULL;
  int __pyx_clineno = 0;

  /* function exit code */
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}

static PyObject *__pyx_pf_2bp_3_bp_2BP_14length(struct __pyx_obj_2bp_3_bp_BP *__pyx_v_self, __pyx_t_2bp_3_bp_SIZE_t __pyx_v_i) {
  PyObject *__pyx_r = NULL;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("length", 0);
  __Pyx_XDECREF(__pyx_r);
  __pyx_t_1 = PyFloat_FromDouble(__pyx_f_2bp_3_bp_2BP_length(__pyx_v_self, __pyx_v_i, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 280, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_r = __pyx_t_1;
  __pyx_t_1 = 0;
  goto __pyx_L0;

  /* function exit code */
  __pyx_L1_error:;
  __Pyx_XDECREF(__pyx_t_1);
  __Pyx_AddTraceback("bp._bp.BP.length", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __pyx_r = NULL;
  __pyx_L0:;
  __Pyx_XGIVEREF(__pyx_r);
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}
+0281:         return self._lengths[i]
  __pyx_t_1 = __Pyx_GetItemInt(((PyObject *)__pyx_v_self->_lengths), __pyx_v_i, __pyx_t_2bp_3_bp_SIZE_t, 1, __Pyx_PyInt_From_Py_intptr_t, 0, 0, 0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 281, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_2 = __pyx_PyFloat_AsDouble(__pyx_t_1); if (unlikely((__pyx_t_2 == ((npy_float64)-1)) && PyErr_Occurred())) __PYX_ERR(0, 281, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_r = __pyx_t_2;
  goto __pyx_L0;
 0282: 
+0283:     cpdef inline INT32_t edge(self, SIZE_t i):
static PyObject *__pyx_pw_2bp_3_bp_2BP_17edge(PyObject *__pyx_v_self, PyObject *__pyx_arg_i); /*proto*/
static CYTHON_INLINE __pyx_t_2bp_3_bp_INT32_t __pyx_f_2bp_3_bp_2BP_edge(struct __pyx_obj_2bp_3_bp_BP *__pyx_v_self, __pyx_t_2bp_3_bp_SIZE_t __pyx_v_i, CYTHON_UNUSED int __pyx_skip_dispatch) {
  __pyx_t_2bp_3_bp_INT32_t __pyx_r;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("edge", 0);
/* … */
  /* function exit code */
  __pyx_L1_error:;
  __Pyx_XDECREF(__pyx_t_1);
  __Pyx_WriteUnraisable("bp._bp.BP.edge", __pyx_clineno, __pyx_lineno, __pyx_filename, 1, 0);
  __pyx_r = 0;
  __pyx_L0:;
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}

/* Python wrapper */
static PyObject *__pyx_pw_2bp_3_bp_2BP_17edge(PyObject *__pyx_v_self, PyObject *__pyx_arg_i); /*proto*/
static PyObject *__pyx_pw_2bp_3_bp_2BP_17edge(PyObject *__pyx_v_self, PyObject *__pyx_arg_i) {
  __pyx_t_2bp_3_bp_SIZE_t __pyx_v_i;
  PyObject *__pyx_r = 0;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("edge (wrapper)", 0);
  assert(__pyx_arg_i); {
    __pyx_v_i = __Pyx_PyInt_As_Py_intptr_t(__pyx_arg_i); if (unlikely((__pyx_v_i == ((npy_intp)-1)) && PyErr_Occurred())) __PYX_ERR(0, 283, __pyx_L3_error)
  }
  goto __pyx_L4_argument_unpacking_done;
  __pyx_L3_error:;
  __Pyx_AddTraceback("bp._bp.BP.edge", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __Pyx_RefNannyFinishContext();
  return NULL;
  __pyx_L4_argument_unpacking_done:;
  __pyx_r = __pyx_pf_2bp_3_bp_2BP_16edge(((struct __pyx_obj_2bp_3_bp_BP *)__pyx_v_self), ((__pyx_t_2bp_3_bp_SIZE_t)__pyx_v_i));
  int __pyx_lineno = 0;
  const char *__pyx_filename = NULL;
  int __pyx_clineno = 0;

  /* function exit code */
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}

static PyObject *__pyx_pf_2bp_3_bp_2BP_16edge(struct __pyx_obj_2bp_3_bp_BP *__pyx_v_self, __pyx_t_2bp_3_bp_SIZE_t __pyx_v_i) {
  PyObject *__pyx_r = NULL;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("edge", 0);
  __Pyx_XDECREF(__pyx_r);
  __pyx_t_1 = __Pyx_PyInt_From_npy_int32(__pyx_f_2bp_3_bp_2BP_edge(__pyx_v_self, __pyx_v_i, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 283, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_r = __pyx_t_1;
  __pyx_t_1 = 0;
  goto __pyx_L0;

  /* function exit code */
  __pyx_L1_error:;
  __Pyx_XDECREF(__pyx_t_1);
  __Pyx_AddTraceback("bp._bp.BP.edge", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __pyx_r = NULL;
  __pyx_L0:;
  __Pyx_XGIVEREF(__pyx_r);
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}
+0284:         return self._edges[i]
  __pyx_t_1 = __Pyx_GetItemInt(((PyObject *)__pyx_v_self->_edges), __pyx_v_i, __pyx_t_2bp_3_bp_SIZE_t, 1, __Pyx_PyInt_From_Py_intptr_t, 0, 0, 0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 284, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_2 = __Pyx_PyInt_As_npy_int32(__pyx_t_1); if (unlikely((__pyx_t_2 == ((npy_int32)-1)) && PyErr_Occurred())) __PYX_ERR(0, 284, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_r = __pyx_t_2;
  goto __pyx_L0;
 0285: 
+0286:     cpdef SIZE_t edge_from_number(self, INT32_t n):
static PyObject *__pyx_pw_2bp_3_bp_2BP_19edge_from_number(PyObject *__pyx_v_self, PyObject *__pyx_arg_n); /*proto*/
static __pyx_t_2bp_3_bp_SIZE_t __pyx_f_2bp_3_bp_2BP_edge_from_number(struct __pyx_obj_2bp_3_bp_BP *__pyx_v_self, __pyx_t_2bp_3_bp_INT32_t __pyx_v_n, CYTHON_UNUSED int __pyx_skip_dispatch) {
  __pyx_t_2bp_3_bp_SIZE_t __pyx_r;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("edge_from_number", 0);
/* … */
  /* function exit code */
  __pyx_L1_error:;
  __Pyx_XDECREF(__pyx_t_1);
  __Pyx_WriteUnraisable("bp._bp.BP.edge_from_number", __pyx_clineno, __pyx_lineno, __pyx_filename, 1, 0);
  __pyx_r = 0;
  __pyx_L0:;
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}

/* Python wrapper */
static PyObject *__pyx_pw_2bp_3_bp_2BP_19edge_from_number(PyObject *__pyx_v_self, PyObject *__pyx_arg_n); /*proto*/
static PyObject *__pyx_pw_2bp_3_bp_2BP_19edge_from_number(PyObject *__pyx_v_self, PyObject *__pyx_arg_n) {
  __pyx_t_2bp_3_bp_INT32_t __pyx_v_n;
  PyObject *__pyx_r = 0;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("edge_from_number (wrapper)", 0);
  assert(__pyx_arg_n); {
    __pyx_v_n = __Pyx_PyInt_As_npy_int32(__pyx_arg_n); if (unlikely((__pyx_v_n == ((npy_int32)-1)) && PyErr_Occurred())) __PYX_ERR(0, 286, __pyx_L3_error)
  }
  goto __pyx_L4_argument_unpacking_done;
  __pyx_L3_error:;
  __Pyx_AddTraceback("bp._bp.BP.edge_from_number", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __Pyx_RefNannyFinishContext();
  return NULL;
  __pyx_L4_argument_unpacking_done:;
  __pyx_r = __pyx_pf_2bp_3_bp_2BP_18edge_from_number(((struct __pyx_obj_2bp_3_bp_BP *)__pyx_v_self), ((__pyx_t_2bp_3_bp_INT32_t)__pyx_v_n));
  int __pyx_lineno = 0;
  const char *__pyx_filename = NULL;
  int __pyx_clineno = 0;

  /* function exit code */
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}

static PyObject *__pyx_pf_2bp_3_bp_2BP_18edge_from_number(struct __pyx_obj_2bp_3_bp_BP *__pyx_v_self, __pyx_t_2bp_3_bp_INT32_t __pyx_v_n) {
  PyObject *__pyx_r = NULL;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("edge_from_number", 0);
  __Pyx_XDECREF(__pyx_r);
  __pyx_t_1 = __Pyx_PyInt_From_Py_intptr_t(__pyx_f_2bp_3_bp_2BP_edge_from_number(__pyx_v_self, __pyx_v_n, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 286, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_r = __pyx_t_1;
  __pyx_t_1 = 0;
  goto __pyx_L0;

  /* function exit code */
  __pyx_L1_error:;
  __Pyx_XDECREF(__pyx_t_1);
  __Pyx_AddTraceback("bp._bp.BP.edge_from_number", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __pyx_r = NULL;
  __pyx_L0:;
  __Pyx_XGIVEREF(__pyx_r);
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}
+0287:         return self._edge_lookup[n]
  __pyx_t_1 = __Pyx_GetItemInt(((PyObject *)__pyx_v_self->_edge_lookup), __pyx_v_n, __pyx_t_2bp_3_bp_INT32_t, 1, __Pyx_PyInt_From_npy_int32, 0, 0, 0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 287, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_2 = __Pyx_PyInt_As_Py_intptr_t(__pyx_t_1); if (unlikely((__pyx_t_2 == ((npy_intp)-1)) && PyErr_Occurred())) __PYX_ERR(0, 287, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_r = __pyx_t_2;
  goto __pyx_L0;
 0288: 
+0289:     cdef inline SIZE_t rank(self, SIZE_t t, SIZE_t i) nogil:
static CYTHON_INLINE __pyx_t_2bp_3_bp_SIZE_t __pyx_f_2bp_3_bp_2BP_rank(struct __pyx_obj_2bp_3_bp_BP *__pyx_v_self, __pyx_t_2bp_3_bp_SIZE_t __pyx_v_t, __pyx_t_2bp_3_bp_SIZE_t __pyx_v_i) {
  int __pyx_v_k;
  int __pyx_v_r;
  int __pyx_v_lower_bound;
  int __pyx_v_upper_bound;
  int __pyx_v_j;
  int __pyx_v_node;
  __pyx_t_2bp_3_bp_SIZE_t __pyx_r;
/* … */
  /* function exit code */
  __pyx_L1_error:;
  __Pyx_WriteUnraisable("bp._bp.BP.rank", __pyx_clineno, __pyx_lineno, __pyx_filename, 1, 1);
  __pyx_r = 0;
  __pyx_L0:;
  return __pyx_r;
}
 0290:         """Determine the rank order of the ith bit t
 0291: 
 0292:         Rank is the order of the ith bit observed, from left to right. For
 0293:         t=1, this is a preorder traversal of the tree.
 0294: 
 0295:         Parameters
 0296:         ----------
 0297:         t : SIZE_t
 0298:             The bit value, either 0 or 1 where 0 is a closing parenthesis and
 0299:             1 is an opening.
 0300:         i : SIZE_T
 0301:             The position to evaluate
 0302: 
 0303:         Returns
 0304:         -------
 0305:         SIZE_t
 0306:             The rank order of the position.
 0307:         """
 0308:         cdef int k
+0309:         cdef int r = 0
  __pyx_v_r = 0;
 0310:         cdef int lower_bound
 0311:         cdef int upper_bound
 0312:         cdef int j
 0313:         cdef int node
 0314: 
 0315:         #TODO: add method to mM for determining block from i
+0316:         k = i // self._rmm.b
  __pyx_v_k = (__pyx_v_i / __pyx_v_self->_rmm->b);
 0317: 
+0318:         lower_bound = k * self._rmm.b
  __pyx_v_lower_bound = (__pyx_v_k * __pyx_v_self->_rmm->b);
 0319: 
 0320:         # upper_bound is block boundary or end of tree
+0321:         upper_bound = min((k + 1) * self._rmm.b, self.size)
  __pyx_v_upper_bound = __pyx_f_2bp_3_bp_min(((__pyx_v_k + 1) * __pyx_v_self->_rmm->b), __pyx_v_self->size);
+0322:         upper_bound = min(upper_bound, i + 1)
  __pyx_v_upper_bound = __pyx_f_2bp_3_bp_min(__pyx_v_upper_bound, (__pyx_v_i + 1));
 0323: 
 0324:         # collect rank from within the block
+0325:         for j in range(lower_bound, upper_bound):
  __pyx_t_1 = __pyx_v_upper_bound;
  __pyx_t_2 = __pyx_t_1;
  for (__pyx_t_3 = __pyx_v_lower_bound; __pyx_t_3 < __pyx_t_2; __pyx_t_3+=1) {
    __pyx_v_j = __pyx_t_3;
+0326:             r += self._b_ptr[j]
    __pyx_v_r = (__pyx_v_r + (__pyx_v_self->_b_ptr[__pyx_v_j]));
  }
 0327: 
 0328:         # collect the rank at the left end of the block
+0329:         node = bt_node_from_left(k, self._rmm.height)
  __pyx_v_node = __pyx_f_2bp_12_binary_tree_bt_node_from_left(__pyx_v_k, __pyx_v_self->_rmm->height);
+0330:         r += self._rmm.r[node]
  if (unlikely(!__pyx_v_self->_rmm->r.memview)) {PyErr_SetString(PyExc_AttributeError,"Memoryview is not initialized");__PYX_ERR(0, 330, __pyx_L1_error)}
  __pyx_t_4 = __pyx_v_node;
  __pyx_v_r = (__pyx_v_r + (*((__pyx_t_2bp_3_bp_SIZE_t *) ( /* dim=0 */ (__pyx_v_self->_rmm->r.data + __pyx_t_4 * __pyx_v_self->_rmm->r.strides[0]) ))));
 0331: 
 0332:         # TODO: can this if statement be removed?
+0333:         if t:
  __pyx_t_5 = (__pyx_v_t != 0);
  if (__pyx_t_5) {
/* … */
  }
+0334:             return r
    __pyx_r = __pyx_v_r;
    goto __pyx_L0;
 0335:         else:
+0336:             return (i - r) + 1
  /*else*/ {
    __pyx_r = ((__pyx_v_i - __pyx_v_r) + 1);
    goto __pyx_L0;
  }
 0337: 
+0338:     cdef inline SIZE_t select(self, SIZE_t t, SIZE_t k) nogil:
static CYTHON_INLINE __pyx_t_2bp_3_bp_SIZE_t __pyx_f_2bp_3_bp_2BP_select(struct __pyx_obj_2bp_3_bp_BP *__pyx_v_self, __pyx_t_2bp_3_bp_SIZE_t __pyx_v_t, __pyx_t_2bp_3_bp_SIZE_t __pyx_v_k) {
  __pyx_t_2bp_3_bp_SIZE_t __pyx_r;
/* … */
  /* function exit code */
  __pyx_L1_error:;
  __Pyx_WriteUnraisable("bp._bp.BP.select", __pyx_clineno, __pyx_lineno, __pyx_filename, 1, 1);
  __pyx_r = 0;
  __pyx_L0:;
  return __pyx_r;
}
 0339:         """The position in B of the kth occurrence of the bit t."""
+0340:         if t:
  __pyx_t_1 = (__pyx_v_t != 0);
  if (__pyx_t_1) {
/* … */
  }
+0341:             return self._k_index_1[k]
    if (unlikely(!__pyx_v_self->_k_index_1.memview)) {PyErr_SetString(PyExc_AttributeError,"Memoryview is not initialized");__PYX_ERR(0, 341, __pyx_L1_error)}
    __pyx_t_2 = __pyx_v_k;
    __pyx_r = (*((__pyx_t_2bp_3_bp_SIZE_t *) ( /* dim=0 */ (__pyx_v_self->_k_index_1.data + __pyx_t_2 * __pyx_v_self->_k_index_1.strides[0]) )));
    goto __pyx_L0;
 0342:         else:
+0343:             return self._k_index_0[k]
  /*else*/ {
    if (unlikely(!__pyx_v_self->_k_index_0.memview)) {PyErr_SetString(PyExc_AttributeError,"Memoryview is not initialized");__PYX_ERR(0, 343, __pyx_L1_error)}
    __pyx_t_2 = __pyx_v_k;
    __pyx_r = (*((__pyx_t_2bp_3_bp_SIZE_t *) ( /* dim=0 */ (__pyx_v_self->_k_index_0.data + __pyx_t_2 * __pyx_v_self->_k_index_0.strides[0]) )));
    goto __pyx_L0;
  }
 0344: 
+0345:     cdef SIZE_t _excess(self, SIZE_t i) nogil:
static __pyx_t_2bp_3_bp_SIZE_t __pyx_f_2bp_3_bp_2BP__excess(struct __pyx_obj_2bp_3_bp_BP *__pyx_v_self, __pyx_t_2bp_3_bp_SIZE_t __pyx_v_i) {
  __pyx_t_2bp_3_bp_SIZE_t __pyx_r;
/* … */
  /* function exit code */
  __pyx_L0:;
  return __pyx_r;
}
 0346:         """Actually compute excess"""
+0347:         if i < 0:
  __pyx_t_1 = ((__pyx_v_i < 0) != 0);
  if (__pyx_t_1) {
/* … */
  }
+0348:             return 0  # wasn't stated as needed but appears so given testing
    __pyx_r = 0;
    goto __pyx_L0;
+0349:         return (2 * self.rank(1, i) - i) - 1
  __pyx_r = (((2 * __pyx_f_2bp_3_bp_2BP_rank(__pyx_v_self, 1, __pyx_v_i)) - __pyx_v_i) - 1);
  goto __pyx_L0;
 0350: 
+0351:     cdef SIZE_t excess(self, SIZE_t i) nogil:
static __pyx_t_2bp_3_bp_SIZE_t __pyx_f_2bp_3_bp_2BP_excess(struct __pyx_obj_2bp_3_bp_BP *__pyx_v_self, __pyx_t_2bp_3_bp_SIZE_t __pyx_v_i) {
  __pyx_t_2bp_3_bp_SIZE_t __pyx_r;
/* … */
  /* function exit code */
  __pyx_L1_error:;
  __Pyx_WriteUnraisable("bp._bp.BP.excess", __pyx_clineno, __pyx_lineno, __pyx_filename, 1, 1);
  __pyx_r = 0;
  __pyx_L0:;
  return __pyx_r;
}
 0352:         """the number of opening minus closing parentheses in B[1, i]"""
 0353:         # same as: self.rank(1, i) - self.rank(0, i)
+0354:         return self._e_index[i]
  if (unlikely(!__pyx_v_self->_e_index.memview)) {PyErr_SetString(PyExc_AttributeError,"Memoryview is not initialized");__PYX_ERR(0, 354, __pyx_L1_error)}
  __pyx_t_1 = __pyx_v_i;
  __pyx_r = (*((__pyx_t_2bp_3_bp_SIZE_t *) ( /* dim=0 */ (__pyx_v_self->_e_index.data + __pyx_t_1 * __pyx_v_self->_e_index.strides[0]) )));
  goto __pyx_L0;
 0355: 
+0356:     cpdef inline SIZE_t close(self, SIZE_t i) nogil:
static PyObject *__pyx_pw_2bp_3_bp_2BP_21close(PyObject *__pyx_v_self, PyObject *__pyx_arg_i); /*proto*/
static CYTHON_INLINE __pyx_t_2bp_3_bp_SIZE_t __pyx_f_2bp_3_bp_2BP_close(struct __pyx_obj_2bp_3_bp_BP *__pyx_v_self, __pyx_t_2bp_3_bp_SIZE_t __pyx_v_i, CYTHON_UNUSED int __pyx_skip_dispatch) {
  __pyx_t_2bp_3_bp_SIZE_t __pyx_r;
/* … */
  /* function exit code */
  __pyx_L0:;
  return __pyx_r;
}

/* Python wrapper */
static PyObject *__pyx_pw_2bp_3_bp_2BP_21close(PyObject *__pyx_v_self, PyObject *__pyx_arg_i); /*proto*/
static char __pyx_doc_2bp_3_bp_2BP_20close[] = "The position of the closing parenthesis that matches B[i]";
static PyObject *__pyx_pw_2bp_3_bp_2BP_21close(PyObject *__pyx_v_self, PyObject *__pyx_arg_i) {
  __pyx_t_2bp_3_bp_SIZE_t __pyx_v_i;
  PyObject *__pyx_r = 0;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("close (wrapper)", 0);
  assert(__pyx_arg_i); {
    __pyx_v_i = __Pyx_PyInt_As_Py_intptr_t(__pyx_arg_i); if (unlikely((__pyx_v_i == ((npy_intp)-1)) && PyErr_Occurred())) __PYX_ERR(0, 356, __pyx_L3_error)
  }
  goto __pyx_L4_argument_unpacking_done;
  __pyx_L3_error:;
  __Pyx_AddTraceback("bp._bp.BP.close", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __Pyx_RefNannyFinishContext();
  return NULL;
  __pyx_L4_argument_unpacking_done:;
  __pyx_r = __pyx_pf_2bp_3_bp_2BP_20close(((struct __pyx_obj_2bp_3_bp_BP *)__pyx_v_self), ((__pyx_t_2bp_3_bp_SIZE_t)__pyx_v_i));
  int __pyx_lineno = 0;
  const char *__pyx_filename = NULL;
  int __pyx_clineno = 0;

  /* function exit code */
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}

static PyObject *__pyx_pf_2bp_3_bp_2BP_20close(struct __pyx_obj_2bp_3_bp_BP *__pyx_v_self, __pyx_t_2bp_3_bp_SIZE_t __pyx_v_i) {
  PyObject *__pyx_r = NULL;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("close", 0);
  __Pyx_XDECREF(__pyx_r);
  __pyx_t_1 = __Pyx_PyInt_From_Py_intptr_t(__pyx_f_2bp_3_bp_2BP_close(__pyx_v_self, __pyx_v_i, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 356, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_r = __pyx_t_1;
  __pyx_t_1 = 0;
  goto __pyx_L0;

  /* function exit code */
  __pyx_L1_error:;
  __Pyx_XDECREF(__pyx_t_1);
  __Pyx_AddTraceback("bp._bp.BP.close", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __pyx_r = NULL;
  __pyx_L0:;
  __Pyx_XGIVEREF(__pyx_r);
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}
 0357:         """The position of the closing parenthesis that matches B[i]"""
+0358:         if not self._b_ptr[i]:
  __pyx_t_1 = ((!((__pyx_v_self->_b_ptr[__pyx_v_i]) != 0)) != 0);
  if (__pyx_t_1) {
/* … */
  }
 0359:             # identity: the close of a closed parenthesis is itself
+0360:             return i
    __pyx_r = __pyx_v_i;
    goto __pyx_L0;
 0361: 
+0362:         return self.fwdsearch(i, -1)
  __pyx_r = __pyx_f_2bp_3_bp_2BP_fwdsearch(__pyx_v_self, __pyx_v_i, -1);
  goto __pyx_L0;
 0363: 
+0364:     cdef inline SIZE_t open(self, SIZE_t i) nogil:
static CYTHON_INLINE __pyx_t_2bp_3_bp_SIZE_t __pyx_f_2bp_3_bp_2BP_open(struct __pyx_obj_2bp_3_bp_BP *__pyx_v_self, __pyx_t_2bp_3_bp_SIZE_t __pyx_v_i) {
  __pyx_t_2bp_3_bp_SIZE_t __pyx_r;
/* … */
  /* function exit code */
  __pyx_L0:;
  return __pyx_r;
}
 0365:         """The position of the opening parenthesis that matches B[i]"""
+0366:         if self._b_ptr[i] or i <= 0:
  __pyx_t_2 = ((__pyx_v_self->_b_ptr[__pyx_v_i]) != 0);
  if (!__pyx_t_2) {
  } else {
    __pyx_t_1 = __pyx_t_2;
    goto __pyx_L4_bool_binop_done;
  }
  __pyx_t_2 = ((__pyx_v_i <= 0) != 0);
  __pyx_t_1 = __pyx_t_2;
  __pyx_L4_bool_binop_done:;
  if (__pyx_t_1) {
/* … */
  }
 0367:             # identity: the open of an open parenthesis is itself
 0368:             # the open of 0 is open. A negative index cannot be open, so just return
+0369:             return i
    __pyx_r = __pyx_v_i;
    goto __pyx_L0;
 0370: 
+0371:         return self.bwdsearch(i, 0) + 1
  __pyx_r = (__pyx_f_2bp_3_bp_2BP_bwdsearch(__pyx_v_self, __pyx_v_i, 0) + 1);
  goto __pyx_L0;
 0372: 
+0373:     cdef inline SIZE_t enclose(self, SIZE_t i) nogil:
static CYTHON_INLINE __pyx_t_2bp_3_bp_SIZE_t __pyx_f_2bp_3_bp_2BP_enclose(struct __pyx_obj_2bp_3_bp_BP *__pyx_v_self, __pyx_t_2bp_3_bp_SIZE_t __pyx_v_i) {
  __pyx_t_2bp_3_bp_SIZE_t __pyx_r;
/* … */
  /* function exit code */
  __pyx_L0:;
  return __pyx_r;
}
 0374:         """The opening parenthesis of the smallest matching pair that contains position i"""
+0375:         if self._b_ptr[i]:
  __pyx_t_1 = ((__pyx_v_self->_b_ptr[__pyx_v_i]) != 0);
  if (__pyx_t_1) {
/* … */
  }
+0376:             return self.bwdsearch(i, -2) + 1
    __pyx_r = (__pyx_f_2bp_3_bp_2BP_bwdsearch(__pyx_v_self, __pyx_v_i, -2) + 1);
    goto __pyx_L0;
 0377:         else:
+0378:             return self.bwdsearch(i - 1, -2) + 1
  /*else*/ {
    __pyx_r = (__pyx_f_2bp_3_bp_2BP_bwdsearch(__pyx_v_self, (__pyx_v_i - 1), -2) + 1);
    goto __pyx_L0;
  }
 0379: 
+0380:     cpdef SIZE_t rmq(self, SIZE_t i, SIZE_t j) nogil:
static PyObject *__pyx_pw_2bp_3_bp_2BP_23rmq(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
static __pyx_t_2bp_3_bp_SIZE_t __pyx_f_2bp_3_bp_2BP_rmq(struct __pyx_obj_2bp_3_bp_BP *__pyx_v_self, __pyx_t_2bp_3_bp_SIZE_t __pyx_v_i, __pyx_t_2bp_3_bp_SIZE_t __pyx_v_j, CYTHON_UNUSED int __pyx_skip_dispatch) {
  __pyx_t_2bp_3_bp_SIZE_t __pyx_v_k;
  __pyx_t_2bp_3_bp_SIZE_t __pyx_v_min_k;
  __pyx_t_2bp_3_bp_SIZE_t __pyx_v_min_v;
  __pyx_t_2bp_3_bp_SIZE_t __pyx_v_obs_v;
  __pyx_t_2bp_3_bp_SIZE_t __pyx_r;
/* … */
  /* function exit code */
  __pyx_L0:;
  return __pyx_r;
}

/* Python wrapper */
static PyObject *__pyx_pw_2bp_3_bp_2BP_23rmq(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
static char __pyx_doc_2bp_3_bp_2BP_22rmq[] = "The leftmost minimum excess in i -> j";
static PyObject *__pyx_pw_2bp_3_bp_2BP_23rmq(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
  __pyx_t_2bp_3_bp_SIZE_t __pyx_v_i;
  __pyx_t_2bp_3_bp_SIZE_t __pyx_v_j;
  PyObject *__pyx_r = 0;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("rmq (wrapper)", 0);
  {
    static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_i,&__pyx_n_s_j,0};
    PyObject* values[2] = {0,0};
    if (unlikely(__pyx_kwds)) {
      Py_ssize_t kw_args;
      const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args);
      switch (pos_args) {
        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
        CYTHON_FALLTHROUGH;
        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
        CYTHON_FALLTHROUGH;
        case  0: break;
        default: goto __pyx_L5_argtuple_error;
      }
      kw_args = PyDict_Size(__pyx_kwds);
      switch (pos_args) {
        case  0:
        if (likely((values[0] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_i)) != 0)) kw_args--;
        else goto __pyx_L5_argtuple_error;
        CYTHON_FALLTHROUGH;
        case  1:
        if (likely((values[1] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_j)) != 0)) kw_args--;
        else {
          __Pyx_RaiseArgtupleInvalid("rmq", 1, 2, 2, 1); __PYX_ERR(0, 380, __pyx_L3_error)
        }
      }
      if (unlikely(kw_args > 0)) {
        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "rmq") < 0)) __PYX_ERR(0, 380, __pyx_L3_error)
      }
    } else if (PyTuple_GET_SIZE(__pyx_args) != 2) {
      goto __pyx_L5_argtuple_error;
    } else {
      values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
      values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
    }
    __pyx_v_i = __Pyx_PyInt_As_Py_intptr_t(values[0]); if (unlikely((__pyx_v_i == ((npy_intp)-1)) && PyErr_Occurred())) __PYX_ERR(0, 380, __pyx_L3_error)
    __pyx_v_j = __Pyx_PyInt_As_Py_intptr_t(values[1]); if (unlikely((__pyx_v_j == ((npy_intp)-1)) && PyErr_Occurred())) __PYX_ERR(0, 380, __pyx_L3_error)
  }
  goto __pyx_L4_argument_unpacking_done;
  __pyx_L5_argtuple_error:;
  __Pyx_RaiseArgtupleInvalid("rmq", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 380, __pyx_L3_error)
  __pyx_L3_error:;
  __Pyx_AddTraceback("bp._bp.BP.rmq", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __Pyx_RefNannyFinishContext();
  return NULL;
  __pyx_L4_argument_unpacking_done:;
  __pyx_r = __pyx_pf_2bp_3_bp_2BP_22rmq(((struct __pyx_obj_2bp_3_bp_BP *)__pyx_v_self), __pyx_v_i, __pyx_v_j);
  int __pyx_lineno = 0;
  const char *__pyx_filename = NULL;
  int __pyx_clineno = 0;

  /* function exit code */
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}

static PyObject *__pyx_pf_2bp_3_bp_2BP_22rmq(struct __pyx_obj_2bp_3_bp_BP *__pyx_v_self, __pyx_t_2bp_3_bp_SIZE_t __pyx_v_i, __pyx_t_2bp_3_bp_SIZE_t __pyx_v_j) {
  PyObject *__pyx_r = NULL;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("rmq", 0);
  __Pyx_XDECREF(__pyx_r);
  __pyx_t_1 = __Pyx_PyInt_From_Py_intptr_t(__pyx_f_2bp_3_bp_2BP_rmq(__pyx_v_self, __pyx_v_i, __pyx_v_j, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 380, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_r = __pyx_t_1;
  __pyx_t_1 = 0;
  goto __pyx_L0;

  /* function exit code */
  __pyx_L1_error:;
  __Pyx_XDECREF(__pyx_t_1);
  __Pyx_AddTraceback("bp._bp.BP.rmq", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __pyx_r = NULL;
  __pyx_L0:;
  __Pyx_XGIVEREF(__pyx_r);
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}
 0381:         """The leftmost minimum excess in i -> j"""
 0382:         cdef:
 0383:             SIZE_t k, min_k
 0384:             SIZE_t min_v, obs_v
 0385: 
+0386:         min_k = i
  __pyx_v_min_k = __pyx_v_i;
+0387:         min_v = self.excess(i)  # a value larger than what will be tested
  __pyx_v_min_v = __pyx_f_2bp_3_bp_2BP_excess(__pyx_v_self, __pyx_v_i);
+0388:         for k in range(i, j + 1):
  __pyx_t_1 = (__pyx_v_j + 1);
  __pyx_t_2 = __pyx_t_1;
  for (__pyx_t_3 = __pyx_v_i; __pyx_t_3 < __pyx_t_2; __pyx_t_3+=1) {
    __pyx_v_k = __pyx_t_3;
+0389:             obs_v = self.excess(k)
    __pyx_v_obs_v = __pyx_f_2bp_3_bp_2BP_excess(__pyx_v_self, __pyx_v_k);
+0390:             if obs_v < min_v:
    __pyx_t_4 = ((__pyx_v_obs_v < __pyx_v_min_v) != 0);
    if (__pyx_t_4) {
/* … */
    }
  }
+0391:                 min_k = k
      __pyx_v_min_k = __pyx_v_k;
+0392:                 min_v = obs_v
      __pyx_v_min_v = __pyx_v_obs_v;
+0393:         return min_k
  __pyx_r = __pyx_v_min_k;
  goto __pyx_L0;
 0394: 
+0395:     cpdef SIZE_t rMq(self, SIZE_t i, SIZE_t j) nogil:
static PyObject *__pyx_pw_2bp_3_bp_2BP_25rMq(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
static __pyx_t_2bp_3_bp_SIZE_t __pyx_f_2bp_3_bp_2BP_rMq(struct __pyx_obj_2bp_3_bp_BP *__pyx_v_self, __pyx_t_2bp_3_bp_SIZE_t __pyx_v_i, __pyx_t_2bp_3_bp_SIZE_t __pyx_v_j, CYTHON_UNUSED int __pyx_skip_dispatch) {
  __pyx_t_2bp_3_bp_SIZE_t __pyx_v_k;
  __pyx_t_2bp_3_bp_SIZE_t __pyx_v_max_k;
  __pyx_t_2bp_3_bp_SIZE_t __pyx_v_max_v;
  __pyx_t_2bp_3_bp_SIZE_t __pyx_v_obs_v;
  __pyx_t_2bp_3_bp_SIZE_t __pyx_r;
/* … */
  /* function exit code */
  __pyx_L0:;
  return __pyx_r;
}

/* Python wrapper */
static PyObject *__pyx_pw_2bp_3_bp_2BP_25rMq(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
static char __pyx_doc_2bp_3_bp_2BP_24rMq[] = "The leftmost maximmum excess in i -> j";
static PyObject *__pyx_pw_2bp_3_bp_2BP_25rMq(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
  __pyx_t_2bp_3_bp_SIZE_t __pyx_v_i;
  __pyx_t_2bp_3_bp_SIZE_t __pyx_v_j;
  PyObject *__pyx_r = 0;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("rMq (wrapper)", 0);
  {
    static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_i,&__pyx_n_s_j,0};
    PyObject* values[2] = {0,0};
    if (unlikely(__pyx_kwds)) {
      Py_ssize_t kw_args;
      const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args);
      switch (pos_args) {
        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
        CYTHON_FALLTHROUGH;
        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
        CYTHON_FALLTHROUGH;
        case  0: break;
        default: goto __pyx_L5_argtuple_error;
      }
      kw_args = PyDict_Size(__pyx_kwds);
      switch (pos_args) {
        case  0:
        if (likely((values[0] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_i)) != 0)) kw_args--;
        else goto __pyx_L5_argtuple_error;
        CYTHON_FALLTHROUGH;
        case  1:
        if (likely((values[1] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_j)) != 0)) kw_args--;
        else {
          __Pyx_RaiseArgtupleInvalid("rMq", 1, 2, 2, 1); __PYX_ERR(0, 395, __pyx_L3_error)
        }
      }
      if (unlikely(kw_args > 0)) {
        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "rMq") < 0)) __PYX_ERR(0, 395, __pyx_L3_error)
      }
    } else if (PyTuple_GET_SIZE(__pyx_args) != 2) {
      goto __pyx_L5_argtuple_error;
    } else {
      values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
      values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
    }
    __pyx_v_i = __Pyx_PyInt_As_Py_intptr_t(values[0]); if (unlikely((__pyx_v_i == ((npy_intp)-1)) && PyErr_Occurred())) __PYX_ERR(0, 395, __pyx_L3_error)
    __pyx_v_j = __Pyx_PyInt_As_Py_intptr_t(values[1]); if (unlikely((__pyx_v_j == ((npy_intp)-1)) && PyErr_Occurred())) __PYX_ERR(0, 395, __pyx_L3_error)
  }
  goto __pyx_L4_argument_unpacking_done;
  __pyx_L5_argtuple_error:;
  __Pyx_RaiseArgtupleInvalid("rMq", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 395, __pyx_L3_error)
  __pyx_L3_error:;
  __Pyx_AddTraceback("bp._bp.BP.rMq", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __Pyx_RefNannyFinishContext();
  return NULL;
  __pyx_L4_argument_unpacking_done:;
  __pyx_r = __pyx_pf_2bp_3_bp_2BP_24rMq(((struct __pyx_obj_2bp_3_bp_BP *)__pyx_v_self), __pyx_v_i, __pyx_v_j);
  int __pyx_lineno = 0;
  const char *__pyx_filename = NULL;
  int __pyx_clineno = 0;

  /* function exit code */
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}

static PyObject *__pyx_pf_2bp_3_bp_2BP_24rMq(struct __pyx_obj_2bp_3_bp_BP *__pyx_v_self, __pyx_t_2bp_3_bp_SIZE_t __pyx_v_i, __pyx_t_2bp_3_bp_SIZE_t __pyx_v_j) {
  PyObject *__pyx_r = NULL;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("rMq", 0);
  __Pyx_XDECREF(__pyx_r);
  __pyx_t_1 = __Pyx_PyInt_From_Py_intptr_t(__pyx_f_2bp_3_bp_2BP_rMq(__pyx_v_self, __pyx_v_i, __pyx_v_j, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 395, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_r = __pyx_t_1;
  __pyx_t_1 = 0;
  goto __pyx_L0;

  /* function exit code */
  __pyx_L1_error:;
  __Pyx_XDECREF(__pyx_t_1);
  __Pyx_AddTraceback("bp._bp.BP.rMq", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __pyx_r = NULL;
  __pyx_L0:;
  __Pyx_XGIVEREF(__pyx_r);
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}
 0396:         """The leftmost maximmum excess in i -> j"""
 0397:         cdef:
 0398:             SIZE_t k, max_k
 0399:             SIZE_t max_v, obs_v
 0400: 
+0401:         max_k = i
  __pyx_v_max_k = __pyx_v_i;
+0402:         max_v = self.excess(i)  # a value larger than what will be tested
  __pyx_v_max_v = __pyx_f_2bp_3_bp_2BP_excess(__pyx_v_self, __pyx_v_i);
+0403:         for k in range(i, j + 1):
  __pyx_t_1 = (__pyx_v_j + 1);
  __pyx_t_2 = __pyx_t_1;
  for (__pyx_t_3 = __pyx_v_i; __pyx_t_3 < __pyx_t_2; __pyx_t_3+=1) {
    __pyx_v_k = __pyx_t_3;
+0404:             obs_v = self.excess(k)
    __pyx_v_obs_v = __pyx_f_2bp_3_bp_2BP_excess(__pyx_v_self, __pyx_v_k);
+0405:             if obs_v > max_v:
    __pyx_t_4 = ((__pyx_v_obs_v > __pyx_v_max_v) != 0);
    if (__pyx_t_4) {
/* … */
    }
  }
+0406:                 max_k = k
      __pyx_v_max_k = __pyx_v_k;
+0407:                 max_v = obs_v
      __pyx_v_max_v = __pyx_v_obs_v;
 0408: 
+0409:         return max_k
  __pyx_r = __pyx_v_max_k;
  goto __pyx_L0;
 0410: 
+0411:     def __len__(self):
/* Python wrapper */
static Py_ssize_t __pyx_pw_2bp_3_bp_2BP_27__len__(PyObject *__pyx_v_self); /*proto*/
static char __pyx_doc_2bp_3_bp_2BP_26__len__[] = "The number of nodes in the tree";
#if CYTHON_UPDATE_DESCRIPTOR_DOC
struct wrapperbase __pyx_wrapperbase_2bp_3_bp_2BP_26__len__;
#endif
static Py_ssize_t __pyx_pw_2bp_3_bp_2BP_27__len__(PyObject *__pyx_v_self) {
  Py_ssize_t __pyx_r;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("__len__ (wrapper)", 0);
  __pyx_r = __pyx_pf_2bp_3_bp_2BP_26__len__(((struct __pyx_obj_2bp_3_bp_BP *)__pyx_v_self));

  /* function exit code */
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}

static Py_ssize_t __pyx_pf_2bp_3_bp_2BP_26__len__(struct __pyx_obj_2bp_3_bp_BP *__pyx_v_self) {
  Py_ssize_t __pyx_r;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("__len__", 0);
/* … */
  /* function exit code */
  __pyx_L0:;
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}
 0412:         """The number of nodes in the tree"""
+0413:         return self.size / 2
  __pyx_r = (__pyx_v_self->size / 2);
  goto __pyx_L0;
 0414: 
+0415:     def __repr__(self):
/* Python wrapper */
static PyObject *__pyx_pw_2bp_3_bp_2BP_29__repr__(PyObject *__pyx_v_self); /*proto*/
static char __pyx_doc_2bp_3_bp_2BP_28__repr__[] = "Returns summary of the tree\n        \n        Returns\n        -------\n        str\n            A summary of this node and all descendants\n        \n        Notes\n        -----\n        This method returns the name of the node and a count of tips and the\n        number of internal nodes in the tree. This docstring and repr was\n        adapted from skbio.TreeNode\n        ";
#if CYTHON_UPDATE_DESCRIPTOR_DOC
struct wrapperbase __pyx_wrapperbase_2bp_3_bp_2BP_28__repr__;
#endif
static PyObject *__pyx_pw_2bp_3_bp_2BP_29__repr__(PyObject *__pyx_v_self) {
  PyObject *__pyx_r = 0;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("__repr__ (wrapper)", 0);
  __pyx_r = __pyx_pf_2bp_3_bp_2BP_28__repr__(((struct __pyx_obj_2bp_3_bp_BP *)__pyx_v_self));

  /* function exit code */
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}

static PyObject *__pyx_pf_2bp_3_bp_2BP_28__repr__(struct __pyx_obj_2bp_3_bp_BP *__pyx_v_self) {
  PyObject *__pyx_v_total_nodes = 0;
  PyObject *__pyx_v_tip_count = 0;
  PyObject *__pyx_r = NULL;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("__repr__", 0);
/* … */
  /* function exit code */
  __pyx_L1_error:;
  __Pyx_XDECREF(__pyx_t_2);
  __Pyx_XDECREF(__pyx_t_3);
  __Pyx_XDECREF(__pyx_t_4);
  __Pyx_AddTraceback("bp._bp.BP.__repr__", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __pyx_r = NULL;
  __pyx_L0:;
  __Pyx_XDECREF(__pyx_v_total_nodes);
  __Pyx_XDECREF(__pyx_v_tip_count);
  __Pyx_XGIVEREF(__pyx_r);
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}
 0416:         """Returns summary of the tree
 0417:         
 0418:         Returns
 0419:         -------
 0420:         str
 0421:             A summary of this node and all descendants
 0422:         
 0423:         Notes
 0424:         -----
 0425:         This method returns the name of the node and a count of tips and the
 0426:         number of internal nodes in the tree. This docstring and repr was
 0427:         adapted from skbio.TreeNode
 0428:         """
+0429:         cdef total_nodes = len(self)
  __pyx_t_1 = PyObject_Length(((PyObject *)__pyx_v_self)); if (unlikely(__pyx_t_1 == ((Py_ssize_t)-1))) __PYX_ERR(0, 429, __pyx_L1_error)
  __pyx_t_2 = PyInt_FromSsize_t(__pyx_t_1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 429, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __pyx_v_total_nodes = __pyx_t_2;
  __pyx_t_2 = 0;
+0430:         cdef tip_count = self.ntips()
  __pyx_t_2 = __Pyx_PyInt_From_Py_intptr_t(__pyx_f_2bp_3_bp_2BP_ntips(__pyx_v_self, 0)); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 430, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __pyx_v_tip_count = __pyx_t_2;
  __pyx_t_2 = 0;
 0431: 
+0432:         return "<BP, name: %s, internal node count: %d, tips count: %d>" % \
  __Pyx_XDECREF(__pyx_r);
/* … */
  __pyx_t_3 = __Pyx_PyString_Format(__pyx_kp_s_BP_name_s_internal_node_count_d, __pyx_t_4); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 432, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
  __pyx_r = __pyx_t_3;
  __pyx_t_3 = 0;
  goto __pyx_L0;
+0433:                 (self.name(0), total_nodes - tip_count, tip_count)
  __pyx_t_2 = __pyx_f_2bp_3_bp_2BP_name(__pyx_v_self, 0, 0); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 433, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __pyx_t_3 = PyNumber_Subtract(__pyx_v_total_nodes, __pyx_v_tip_count); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 433, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __pyx_t_4 = PyTuple_New(3); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 433, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  __Pyx_GIVEREF(__pyx_t_2);
  PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_2);
  __Pyx_GIVEREF(__pyx_t_3);
  PyTuple_SET_ITEM(__pyx_t_4, 1, __pyx_t_3);
  __Pyx_INCREF(__pyx_v_tip_count);
  __Pyx_GIVEREF(__pyx_v_tip_count);
  PyTuple_SET_ITEM(__pyx_t_4, 2, __pyx_v_tip_count);
  __pyx_t_2 = 0;
  __pyx_t_3 = 0;
 0434: 
+0435:     def __reduce__(self):
/* Python wrapper */
static PyObject *__pyx_pw_2bp_3_bp_2BP_31__reduce__(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused); /*proto*/
static PyObject *__pyx_pw_2bp_3_bp_2BP_31__reduce__(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused) {
  PyObject *__pyx_r = 0;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("__reduce__ (wrapper)", 0);
  __pyx_r = __pyx_pf_2bp_3_bp_2BP_30__reduce__(((struct __pyx_obj_2bp_3_bp_BP *)__pyx_v_self));

  /* function exit code */
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}

static PyObject *__pyx_pf_2bp_3_bp_2BP_30__reduce__(struct __pyx_obj_2bp_3_bp_BP *__pyx_v_self) {
  PyObject *__pyx_r = NULL;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("__reduce__", 0);
/* … */
  /* function exit code */
  __pyx_L1_error:;
  __Pyx_XDECREF(__pyx_t_1);
  __Pyx_XDECREF(__pyx_t_2);
  __Pyx_AddTraceback("bp._bp.BP.__reduce__", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __pyx_r = NULL;
  __pyx_L0:;
  __Pyx_XGIVEREF(__pyx_r);
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}
+0436:         return (BP, (self.B, self._lengths, self._names))
  __Pyx_XDECREF(__pyx_r);
  __pyx_t_1 = PyTuple_New(3); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 436, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __Pyx_INCREF(((PyObject *)__pyx_v_self->B));
  __Pyx_GIVEREF(((PyObject *)__pyx_v_self->B));
  PyTuple_SET_ITEM(__pyx_t_1, 0, ((PyObject *)__pyx_v_self->B));
  __Pyx_INCREF(((PyObject *)__pyx_v_self->_lengths));
  __Pyx_GIVEREF(((PyObject *)__pyx_v_self->_lengths));
  PyTuple_SET_ITEM(__pyx_t_1, 1, ((PyObject *)__pyx_v_self->_lengths));
  __Pyx_INCREF(((PyObject *)__pyx_v_self->_names));
  __Pyx_GIVEREF(((PyObject *)__pyx_v_self->_names));
  PyTuple_SET_ITEM(__pyx_t_1, 2, ((PyObject *)__pyx_v_self->_names));
  __pyx_t_2 = PyTuple_New(2); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 436, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __Pyx_INCREF(((PyObject *)__pyx_ptype_2bp_3_bp_BP));
  __Pyx_GIVEREF(((PyObject *)__pyx_ptype_2bp_3_bp_BP));
  PyTuple_SET_ITEM(__pyx_t_2, 0, ((PyObject *)__pyx_ptype_2bp_3_bp_BP));
  __Pyx_GIVEREF(__pyx_t_1);
  PyTuple_SET_ITEM(__pyx_t_2, 1, __pyx_t_1);
  __pyx_t_1 = 0;
  __pyx_r = __pyx_t_2;
  __pyx_t_2 = 0;
  goto __pyx_L0;
 0437: 
+0438:     cpdef SIZE_t depth(self, SIZE_t i) nogil:
static PyObject *__pyx_pw_2bp_3_bp_2BP_33depth(PyObject *__pyx_v_self, PyObject *__pyx_arg_i); /*proto*/
static __pyx_t_2bp_3_bp_SIZE_t __pyx_f_2bp_3_bp_2BP_depth(struct __pyx_obj_2bp_3_bp_BP *__pyx_v_self, __pyx_t_2bp_3_bp_SIZE_t __pyx_v_i, CYTHON_UNUSED int __pyx_skip_dispatch) {
  __pyx_t_2bp_3_bp_SIZE_t __pyx_r;
/* … */
  /* function exit code */
  __pyx_L1_error:;
  __Pyx_WriteUnraisable("bp._bp.BP.depth", __pyx_clineno, __pyx_lineno, __pyx_filename, 1, 1);
  __pyx_r = 0;
  __pyx_L0:;
  return __pyx_r;
}

/* Python wrapper */
static PyObject *__pyx_pw_2bp_3_bp_2BP_33depth(PyObject *__pyx_v_self, PyObject *__pyx_arg_i); /*proto*/
static char __pyx_doc_2bp_3_bp_2BP_32depth[] = "The depth of node i";
static PyObject *__pyx_pw_2bp_3_bp_2BP_33depth(PyObject *__pyx_v_self, PyObject *__pyx_arg_i) {
  __pyx_t_2bp_3_bp_SIZE_t __pyx_v_i;
  PyObject *__pyx_r = 0;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("depth (wrapper)", 0);
  assert(__pyx_arg_i); {
    __pyx_v_i = __Pyx_PyInt_As_Py_intptr_t(__pyx_arg_i); if (unlikely((__pyx_v_i == ((npy_intp)-1)) && PyErr_Occurred())) __PYX_ERR(0, 438, __pyx_L3_error)
  }
  goto __pyx_L4_argument_unpacking_done;
  __pyx_L3_error:;
  __Pyx_AddTraceback("bp._bp.BP.depth", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __Pyx_RefNannyFinishContext();
  return NULL;
  __pyx_L4_argument_unpacking_done:;
  __pyx_r = __pyx_pf_2bp_3_bp_2BP_32depth(((struct __pyx_obj_2bp_3_bp_BP *)__pyx_v_self), ((__pyx_t_2bp_3_bp_SIZE_t)__pyx_v_i));
  int __pyx_lineno = 0;
  const char *__pyx_filename = NULL;
  int __pyx_clineno = 0;

  /* function exit code */
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}

static PyObject *__pyx_pf_2bp_3_bp_2BP_32depth(struct __pyx_obj_2bp_3_bp_BP *__pyx_v_self, __pyx_t_2bp_3_bp_SIZE_t __pyx_v_i) {
  PyObject *__pyx_r = NULL;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("depth", 0);
  __Pyx_XDECREF(__pyx_r);
  __pyx_t_1 = __Pyx_PyInt_From_Py_intptr_t(__pyx_f_2bp_3_bp_2BP_depth(__pyx_v_self, __pyx_v_i, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 438, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_r = __pyx_t_1;
  __pyx_t_1 = 0;
  goto __pyx_L0;

  /* function exit code */
  __pyx_L1_error:;
  __Pyx_XDECREF(__pyx_t_1);
  __Pyx_AddTraceback("bp._bp.BP.depth", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __pyx_r = NULL;
  __pyx_L0:;
  __Pyx_XGIVEREF(__pyx_r);
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}
 0439:         """The depth of node i"""
+0440:         return self._e_index[i]
  if (unlikely(!__pyx_v_self->_e_index.memview)) {PyErr_SetString(PyExc_AttributeError,"Memoryview is not initialized");__PYX_ERR(0, 440, __pyx_L1_error)}
  __pyx_t_1 = __pyx_v_i;
  __pyx_r = (*((__pyx_t_2bp_3_bp_SIZE_t *) ( /* dim=0 */ (__pyx_v_self->_e_index.data + __pyx_t_1 * __pyx_v_self->_e_index.strides[0]) )));
  goto __pyx_L0;
 0441: 
+0442:     cpdef SIZE_t root(self) nogil:
static PyObject *__pyx_pw_2bp_3_bp_2BP_35root(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused); /*proto*/
static __pyx_t_2bp_3_bp_SIZE_t __pyx_f_2bp_3_bp_2BP_root(CYTHON_UNUSED struct __pyx_obj_2bp_3_bp_BP *__pyx_v_self, CYTHON_UNUSED int __pyx_skip_dispatch) {
  __pyx_t_2bp_3_bp_SIZE_t __pyx_r;
/* … */
  /* function exit code */
  __pyx_L0:;
  return __pyx_r;
}

/* Python wrapper */
static PyObject *__pyx_pw_2bp_3_bp_2BP_35root(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused); /*proto*/
static char __pyx_doc_2bp_3_bp_2BP_34root[] = "The root of the tree";
static PyObject *__pyx_pw_2bp_3_bp_2BP_35root(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused) {
  PyObject *__pyx_r = 0;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("root (wrapper)", 0);
  __pyx_r = __pyx_pf_2bp_3_bp_2BP_34root(((struct __pyx_obj_2bp_3_bp_BP *)__pyx_v_self));

  /* function exit code */
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}

static PyObject *__pyx_pf_2bp_3_bp_2BP_34root(struct __pyx_obj_2bp_3_bp_BP *__pyx_v_self) {
  PyObject *__pyx_r = NULL;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("root", 0);
  __Pyx_XDECREF(__pyx_r);
  __pyx_t_1 = __Pyx_PyInt_From_Py_intptr_t(__pyx_f_2bp_3_bp_2BP_root(__pyx_v_self, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 442, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_r = __pyx_t_1;
  __pyx_t_1 = 0;
  goto __pyx_L0;

  /* function exit code */
  __pyx_L1_error:;
  __Pyx_XDECREF(__pyx_t_1);
  __Pyx_AddTraceback("bp._bp.BP.root", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __pyx_r = NULL;
  __pyx_L0:;
  __Pyx_XGIVEREF(__pyx_r);
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}
 0443:         """The root of the tree"""
+0444:         return 0
  __pyx_r = 0;
  goto __pyx_L0;
 0445: 
+0446:     cpdef SIZE_t parent(self, SIZE_t i) nogil:
static PyObject *__pyx_pw_2bp_3_bp_2BP_37parent(PyObject *__pyx_v_self, PyObject *__pyx_arg_i); /*proto*/
static __pyx_t_2bp_3_bp_SIZE_t __pyx_f_2bp_3_bp_2BP_parent(struct __pyx_obj_2bp_3_bp_BP *__pyx_v_self, __pyx_t_2bp_3_bp_SIZE_t __pyx_v_i, CYTHON_UNUSED int __pyx_skip_dispatch) {
  __pyx_t_2bp_3_bp_SIZE_t __pyx_r;
/* … */
  /* function exit code */
  __pyx_L0:;
  return __pyx_r;
}

/* Python wrapper */
static PyObject *__pyx_pw_2bp_3_bp_2BP_37parent(PyObject *__pyx_v_self, PyObject *__pyx_arg_i); /*proto*/
static char __pyx_doc_2bp_3_bp_2BP_36parent[] = "The parent of node i";
static PyObject *__pyx_pw_2bp_3_bp_2BP_37parent(PyObject *__pyx_v_self, PyObject *__pyx_arg_i) {
  __pyx_t_2bp_3_bp_SIZE_t __pyx_v_i;
  PyObject *__pyx_r = 0;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("parent (wrapper)", 0);
  assert(__pyx_arg_i); {
    __pyx_v_i = __Pyx_PyInt_As_Py_intptr_t(__pyx_arg_i); if (unlikely((__pyx_v_i == ((npy_intp)-1)) && PyErr_Occurred())) __PYX_ERR(0, 446, __pyx_L3_error)
  }
  goto __pyx_L4_argument_unpacking_done;
  __pyx_L3_error:;
  __Pyx_AddTraceback("bp._bp.BP.parent", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __Pyx_RefNannyFinishContext();
  return NULL;
  __pyx_L4_argument_unpacking_done:;
  __pyx_r = __pyx_pf_2bp_3_bp_2BP_36parent(((struct __pyx_obj_2bp_3_bp_BP *)__pyx_v_self), ((__pyx_t_2bp_3_bp_SIZE_t)__pyx_v_i));
  int __pyx_lineno = 0;
  const char *__pyx_filename = NULL;
  int __pyx_clineno = 0;

  /* function exit code */
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}

static PyObject *__pyx_pf_2bp_3_bp_2BP_36parent(struct __pyx_obj_2bp_3_bp_BP *__pyx_v_self, __pyx_t_2bp_3_bp_SIZE_t __pyx_v_i) {
  PyObject *__pyx_r = NULL;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("parent", 0);
  __Pyx_XDECREF(__pyx_r);
  __pyx_t_1 = __Pyx_PyInt_From_Py_intptr_t(__pyx_f_2bp_3_bp_2BP_parent(__pyx_v_self, __pyx_v_i, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 446, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_r = __pyx_t_1;
  __pyx_t_1 = 0;
  goto __pyx_L0;

  /* function exit code */
  __pyx_L1_error:;
  __Pyx_XDECREF(__pyx_t_1);
  __Pyx_AddTraceback("bp._bp.BP.parent", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __pyx_r = NULL;
  __pyx_L0:;
  __Pyx_XGIVEREF(__pyx_r);
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}
 0447:         """The parent of node i"""
 0448:         # TODO: only make operations like this defined on the open parentheses.
 0449:         # this monkeying with checking open/close sucks.
+0450:         if i == self.root() or i == (self.size - 1):
  __pyx_t_2 = ((__pyx_v_i == __pyx_f_2bp_3_bp_2BP_root(__pyx_v_self, 0)) != 0);
  if (!__pyx_t_2) {
  } else {
    __pyx_t_1 = __pyx_t_2;
    goto __pyx_L4_bool_binop_done;
  }
  __pyx_t_2 = ((__pyx_v_i == (__pyx_v_self->size - 1)) != 0);
  __pyx_t_1 = __pyx_t_2;
  __pyx_L4_bool_binop_done:;
  if (__pyx_t_1) {
/* … */
  }
+0451:             return -1
    __pyx_r = -1;
    goto __pyx_L0;
 0452:         else:
+0453:             return self.enclose(i)
  /*else*/ {
    __pyx_r = __pyx_f_2bp_3_bp_2BP_enclose(__pyx_v_self, __pyx_v_i);
    goto __pyx_L0;
  }
 0454: 
+0455:     cpdef BOOL_t isleaf(self, SIZE_t i) nogil:
static PyObject *__pyx_pw_2bp_3_bp_2BP_39isleaf(PyObject *__pyx_v_self, PyObject *__pyx_arg_i); /*proto*/
static CYTHON_INLINE __pyx_t_2bp_3_bp_BOOL_t __pyx_f_2bp_3_bp_2BP_isleaf(struct __pyx_obj_2bp_3_bp_BP *__pyx_v_self, __pyx_t_2bp_3_bp_SIZE_t __pyx_v_i, CYTHON_UNUSED int __pyx_skip_dispatch) {
  __pyx_t_2bp_3_bp_BOOL_t __pyx_r;
/* … */
  /* function exit code */
  __pyx_L0:;
  return __pyx_r;
}

/* Python wrapper */
static PyObject *__pyx_pw_2bp_3_bp_2BP_39isleaf(PyObject *__pyx_v_self, PyObject *__pyx_arg_i); /*proto*/
static char __pyx_doc_2bp_3_bp_2BP_38isleaf[] = "Whether the node is a leaf";
static PyObject *__pyx_pw_2bp_3_bp_2BP_39isleaf(PyObject *__pyx_v_self, PyObject *__pyx_arg_i) {
  __pyx_t_2bp_3_bp_SIZE_t __pyx_v_i;
  PyObject *__pyx_r = 0;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("isleaf (wrapper)", 0);
  assert(__pyx_arg_i); {
    __pyx_v_i = __Pyx_PyInt_As_Py_intptr_t(__pyx_arg_i); if (unlikely((__pyx_v_i == ((npy_intp)-1)) && PyErr_Occurred())) __PYX_ERR(0, 455, __pyx_L3_error)
  }
  goto __pyx_L4_argument_unpacking_done;
  __pyx_L3_error:;
  __Pyx_AddTraceback("bp._bp.BP.isleaf", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __Pyx_RefNannyFinishContext();
  return NULL;
  __pyx_L4_argument_unpacking_done:;
  __pyx_r = __pyx_pf_2bp_3_bp_2BP_38isleaf(((struct __pyx_obj_2bp_3_bp_BP *)__pyx_v_self), ((__pyx_t_2bp_3_bp_SIZE_t)__pyx_v_i));
  int __pyx_lineno = 0;
  const char *__pyx_filename = NULL;
  int __pyx_clineno = 0;

  /* function exit code */
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}

static PyObject *__pyx_pf_2bp_3_bp_2BP_38isleaf(struct __pyx_obj_2bp_3_bp_BP *__pyx_v_self, __pyx_t_2bp_3_bp_SIZE_t __pyx_v_i) {
  PyObject *__pyx_r = NULL;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("isleaf", 0);
  __Pyx_XDECREF(__pyx_r);
  __pyx_t_1 = __Pyx_PyInt_From_npy_uint8(__pyx_f_2bp_3_bp_2BP_isleaf(__pyx_v_self, __pyx_v_i, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 455, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_r = __pyx_t_1;
  __pyx_t_1 = 0;
  goto __pyx_L0;

  /* function exit code */
  __pyx_L1_error:;
  __Pyx_XDECREF(__pyx_t_1);
  __Pyx_AddTraceback("bp._bp.BP.isleaf", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __pyx_r = NULL;
  __pyx_L0:;
  __Pyx_XGIVEREF(__pyx_r);
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}
 0456:         """Whether the node is a leaf"""
+0457:         return self._b_ptr[i] and (not self._b_ptr[i + 1])
  if ((__pyx_v_self->_b_ptr[__pyx_v_i])) {
  } else {
    __pyx_t_1 = (__pyx_v_self->_b_ptr[__pyx_v_i]);
    goto __pyx_L3_bool_binop_done;
  }
  __pyx_t_2 = (!((__pyx_v_self->_b_ptr[(__pyx_v_i + 1)]) != 0));
  __pyx_t_1 = __pyx_t_2;
  __pyx_L3_bool_binop_done:;
  __pyx_r = __pyx_t_1;
  goto __pyx_L0;
 0458: 
+0459:     cpdef SIZE_t fchild(self, SIZE_t i) nogil:
static PyObject *__pyx_pw_2bp_3_bp_2BP_41fchild(PyObject *__pyx_v_self, PyObject *__pyx_arg_i); /*proto*/
static __pyx_t_2bp_3_bp_SIZE_t __pyx_f_2bp_3_bp_2BP_fchild(struct __pyx_obj_2bp_3_bp_BP *__pyx_v_self, __pyx_t_2bp_3_bp_SIZE_t __pyx_v_i, CYTHON_UNUSED int __pyx_skip_dispatch) {
  __pyx_t_2bp_3_bp_SIZE_t __pyx_r;
/* … */
  /* function exit code */
  __pyx_L0:;
  return __pyx_r;
}

/* Python wrapper */
static PyObject *__pyx_pw_2bp_3_bp_2BP_41fchild(PyObject *__pyx_v_self, PyObject *__pyx_arg_i); /*proto*/
static char __pyx_doc_2bp_3_bp_2BP_40fchild[] = "The first child of i (i.e., the left child)\n\n        fchild(i) = i + 1 (if i is not a leaf)\n\n        Returns 0 if the node is a leaf as the root cannot be a child by\n        definition.\n        ";
static PyObject *__pyx_pw_2bp_3_bp_2BP_41fchild(PyObject *__pyx_v_self, PyObject *__pyx_arg_i) {
  __pyx_t_2bp_3_bp_SIZE_t __pyx_v_i;
  PyObject *__pyx_r = 0;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("fchild (wrapper)", 0);
  assert(__pyx_arg_i); {
    __pyx_v_i = __Pyx_PyInt_As_Py_intptr_t(__pyx_arg_i); if (unlikely((__pyx_v_i == ((npy_intp)-1)) && PyErr_Occurred())) __PYX_ERR(0, 459, __pyx_L3_error)
  }
  goto __pyx_L4_argument_unpacking_done;
  __pyx_L3_error:;
  __Pyx_AddTraceback("bp._bp.BP.fchild", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __Pyx_RefNannyFinishContext();
  return NULL;
  __pyx_L4_argument_unpacking_done:;
  __pyx_r = __pyx_pf_2bp_3_bp_2BP_40fchild(((struct __pyx_obj_2bp_3_bp_BP *)__pyx_v_self), ((__pyx_t_2bp_3_bp_SIZE_t)__pyx_v_i));
  int __pyx_lineno = 0;
  const char *__pyx_filename = NULL;
  int __pyx_clineno = 0;

  /* function exit code */
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}

static PyObject *__pyx_pf_2bp_3_bp_2BP_40fchild(struct __pyx_obj_2bp_3_bp_BP *__pyx_v_self, __pyx_t_2bp_3_bp_SIZE_t __pyx_v_i) {
  PyObject *__pyx_r = NULL;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("fchild", 0);
  __Pyx_XDECREF(__pyx_r);
  __pyx_t_1 = __Pyx_PyInt_From_Py_intptr_t(__pyx_f_2bp_3_bp_2BP_fchild(__pyx_v_self, __pyx_v_i, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 459, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_r = __pyx_t_1;
  __pyx_t_1 = 0;
  goto __pyx_L0;

  /* function exit code */
  __pyx_L1_error:;
  __Pyx_XDECREF(__pyx_t_1);
  __Pyx_AddTraceback("bp._bp.BP.fchild", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __pyx_r = NULL;
  __pyx_L0:;
  __Pyx_XGIVEREF(__pyx_r);
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}
 0460:         """The first child of i (i.e., the left child)
 0461: 
 0462:         fchild(i) = i + 1 (if i is not a leaf)
 0463: 
 0464:         Returns 0 if the node is a leaf as the root cannot be a child by
 0465:         definition.
 0466:         """
+0467:         if self._b_ptr[i]:
  __pyx_t_1 = ((__pyx_v_self->_b_ptr[__pyx_v_i]) != 0);
  if (__pyx_t_1) {
/* … */
  }
+0468:             if self.isleaf(i):
    __pyx_t_1 = (__pyx_f_2bp_3_bp_2BP_isleaf(__pyx_v_self, __pyx_v_i, 0) != 0);
    if (__pyx_t_1) {
/* … */
    }
+0469:                 return 0
      __pyx_r = 0;
      goto __pyx_L0;
 0470:             else:
+0471:                 return i + 1
    /*else*/ {
      __pyx_r = (__pyx_v_i + 1);
      goto __pyx_L0;
    }
 0472:         else:
+0473:             return self.fchild(self.open(i))
  /*else*/ {
    __pyx_r = __pyx_f_2bp_3_bp_2BP_fchild(__pyx_v_self, __pyx_f_2bp_3_bp_2BP_open(__pyx_v_self, __pyx_v_i), 0);
    goto __pyx_L0;
  }
 0474: 
+0475:     cpdef SIZE_t lchild(self, SIZE_t i) nogil:
static PyObject *__pyx_pw_2bp_3_bp_2BP_43lchild(PyObject *__pyx_v_self, PyObject *__pyx_arg_i); /*proto*/
static __pyx_t_2bp_3_bp_SIZE_t __pyx_f_2bp_3_bp_2BP_lchild(struct __pyx_obj_2bp_3_bp_BP *__pyx_v_self, __pyx_t_2bp_3_bp_SIZE_t __pyx_v_i, CYTHON_UNUSED int __pyx_skip_dispatch) {
  __pyx_t_2bp_3_bp_SIZE_t __pyx_r;
/* … */
  /* function exit code */
  __pyx_L0:;
  return __pyx_r;
}

/* Python wrapper */
static PyObject *__pyx_pw_2bp_3_bp_2BP_43lchild(PyObject *__pyx_v_self, PyObject *__pyx_arg_i); /*proto*/
static char __pyx_doc_2bp_3_bp_2BP_42lchild[] = "The last child of i (i.e., the right child)\n\n        lchild(i) = open(close(i) \342\210\222 1) (if i is not a leaf)\n\n        Returns 0 if the node is a leaf as the root cannot be a child by\n        definition.\n        ";
static PyObject *__pyx_pw_2bp_3_bp_2BP_43lchild(PyObject *__pyx_v_self, PyObject *__pyx_arg_i) {
  __pyx_t_2bp_3_bp_SIZE_t __pyx_v_i;
  PyObject *__pyx_r = 0;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("lchild (wrapper)", 0);
  assert(__pyx_arg_i); {
    __pyx_v_i = __Pyx_PyInt_As_Py_intptr_t(__pyx_arg_i); if (unlikely((__pyx_v_i == ((npy_intp)-1)) && PyErr_Occurred())) __PYX_ERR(0, 475, __pyx_L3_error)
  }
  goto __pyx_L4_argument_unpacking_done;
  __pyx_L3_error:;
  __Pyx_AddTraceback("bp._bp.BP.lchild", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __Pyx_RefNannyFinishContext();
  return NULL;
  __pyx_L4_argument_unpacking_done:;
  __pyx_r = __pyx_pf_2bp_3_bp_2BP_42lchild(((struct __pyx_obj_2bp_3_bp_BP *)__pyx_v_self), ((__pyx_t_2bp_3_bp_SIZE_t)__pyx_v_i));
  int __pyx_lineno = 0;
  const char *__pyx_filename = NULL;
  int __pyx_clineno = 0;

  /* function exit code */
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}

static PyObject *__pyx_pf_2bp_3_bp_2BP_42lchild(struct __pyx_obj_2bp_3_bp_BP *__pyx_v_self, __pyx_t_2bp_3_bp_SIZE_t __pyx_v_i) {
  PyObject *__pyx_r = NULL;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("lchild", 0);
  __Pyx_XDECREF(__pyx_r);
  __pyx_t_1 = __Pyx_PyInt_From_Py_intptr_t(__pyx_f_2bp_3_bp_2BP_lchild(__pyx_v_self, __pyx_v_i, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 475, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_r = __pyx_t_1;
  __pyx_t_1 = 0;
  goto __pyx_L0;

  /* function exit code */
  __pyx_L1_error:;
  __Pyx_XDECREF(__pyx_t_1);
  __Pyx_AddTraceback("bp._bp.BP.lchild", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __pyx_r = NULL;
  __pyx_L0:;
  __Pyx_XGIVEREF(__pyx_r);
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}
 0476:         """The last child of i (i.e., the right child)
 0477: 
 0478:         lchild(i) = open(close(i) − 1) (if i is not a leaf)
 0479: 
 0480:         Returns 0 if the node is a leaf as the root cannot be a child by
 0481:         definition.
 0482:         """
+0483:         if self._b_ptr[i]:
  __pyx_t_1 = ((__pyx_v_self->_b_ptr[__pyx_v_i]) != 0);
  if (__pyx_t_1) {
/* … */
  }
+0484:             if self.isleaf(i):
    __pyx_t_1 = (__pyx_f_2bp_3_bp_2BP_isleaf(__pyx_v_self, __pyx_v_i, 0) != 0);
    if (__pyx_t_1) {
/* … */
    }
+0485:                 return 0
      __pyx_r = 0;
      goto __pyx_L0;
 0486:             else:
+0487:                 return self.open(self.close(i) - 1)
    /*else*/ {
      __pyx_r = __pyx_f_2bp_3_bp_2BP_open(__pyx_v_self, (__pyx_f_2bp_3_bp_2BP_close(__pyx_v_self, __pyx_v_i, 0) - 1));
      goto __pyx_L0;
    }
 0488:         else:
+0489:             return self.lchild(self.open(i))
  /*else*/ {
    __pyx_r = __pyx_f_2bp_3_bp_2BP_lchild(__pyx_v_self, __pyx_f_2bp_3_bp_2BP_open(__pyx_v_self, __pyx_v_i), 0);
    goto __pyx_L0;
  }
 0490: 
+0491:     def mincount(self, SIZE_t i, SIZE_t j):
/* Python wrapper */
static PyObject *__pyx_pw_2bp_3_bp_2BP_45mincount(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
static char __pyx_doc_2bp_3_bp_2BP_44mincount[] = "number of occurrences of the minimum in excess(i), excess(i + 1), . . . , excess(j).";
static PyObject *__pyx_pw_2bp_3_bp_2BP_45mincount(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
  __pyx_t_2bp_3_bp_SIZE_t __pyx_v_i;
  __pyx_t_2bp_3_bp_SIZE_t __pyx_v_j;
  PyObject *__pyx_r = 0;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("mincount (wrapper)", 0);
  {
    static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_i,&__pyx_n_s_j,0};
    PyObject* values[2] = {0,0};
    if (unlikely(__pyx_kwds)) {
      Py_ssize_t kw_args;
      const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args);
      switch (pos_args) {
        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
        CYTHON_FALLTHROUGH;
        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
        CYTHON_FALLTHROUGH;
        case  0: break;
        default: goto __pyx_L5_argtuple_error;
      }
      kw_args = PyDict_Size(__pyx_kwds);
      switch (pos_args) {
        case  0:
        if (likely((values[0] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_i)) != 0)) kw_args--;
        else goto __pyx_L5_argtuple_error;
        CYTHON_FALLTHROUGH;
        case  1:
        if (likely((values[1] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_j)) != 0)) kw_args--;
        else {
          __Pyx_RaiseArgtupleInvalid("mincount", 1, 2, 2, 1); __PYX_ERR(0, 491, __pyx_L3_error)
        }
      }
      if (unlikely(kw_args > 0)) {
        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "mincount") < 0)) __PYX_ERR(0, 491, __pyx_L3_error)
      }
    } else if (PyTuple_GET_SIZE(__pyx_args) != 2) {
      goto __pyx_L5_argtuple_error;
    } else {
      values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
      values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
    }
    __pyx_v_i = __Pyx_PyInt_As_Py_intptr_t(values[0]); if (unlikely((__pyx_v_i == ((npy_intp)-1)) && PyErr_Occurred())) __PYX_ERR(0, 491, __pyx_L3_error)
    __pyx_v_j = __Pyx_PyInt_As_Py_intptr_t(values[1]); if (unlikely((__pyx_v_j == ((npy_intp)-1)) && PyErr_Occurred())) __PYX_ERR(0, 491, __pyx_L3_error)
  }
  goto __pyx_L4_argument_unpacking_done;
  __pyx_L5_argtuple_error:;
  __Pyx_RaiseArgtupleInvalid("mincount", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 491, __pyx_L3_error)
  __pyx_L3_error:;
  __Pyx_AddTraceback("bp._bp.BP.mincount", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __Pyx_RefNannyFinishContext();
  return NULL;
  __pyx_L4_argument_unpacking_done:;
  __pyx_r = __pyx_pf_2bp_3_bp_2BP_44mincount(((struct __pyx_obj_2bp_3_bp_BP *)__pyx_v_self), __pyx_v_i, __pyx_v_j);
  int __pyx_lineno = 0;
  const char *__pyx_filename = NULL;
  int __pyx_clineno = 0;

  /* function exit code */
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}

static PyObject *__pyx_pf_2bp_3_bp_2BP_44mincount(struct __pyx_obj_2bp_3_bp_BP *__pyx_v_self, __pyx_t_2bp_3_bp_SIZE_t __pyx_v_i, __pyx_t_2bp_3_bp_SIZE_t __pyx_v_j) {
  PyObject *__pyx_v_excess = NULL;
  PyObject *__pyx_v_counts = NULL;
  long __pyx_v_k;
  PyObject *__pyx_r = NULL;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("mincount", 0);
/* … */
  /* function exit code */
  __pyx_L1_error:;
  __Pyx_XDECREF(__pyx_t_1);
  __Pyx_XDECREF(__pyx_t_2);
  __Pyx_XDECREF(__pyx_t_6);
  __Pyx_XDECREF(__pyx_t_7);
  __Pyx_AddTraceback("bp._bp.BP.mincount", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __pyx_r = NULL;
  __pyx_L0:;
  __Pyx_XDECREF(__pyx_v_excess);
  __Pyx_XDECREF(__pyx_v_counts);
  __Pyx_XGIVEREF(__pyx_r);
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}
 0492:         """number of occurrences of the minimum in excess(i), excess(i + 1), . . . , excess(j)."""
+0493:         excess, counts = np.unique([self.excess(k) for k in range(i, j + 1)], return_counts=True)
  __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_np); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 493, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_unique); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 493, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_t_1 = PyList_New(0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 493, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_3 = (__pyx_v_j + 1);
  __pyx_t_4 = __pyx_t_3;
  for (__pyx_t_5 = __pyx_v_i; __pyx_t_5 < __pyx_t_4; __pyx_t_5+=1) {
    __pyx_v_k = __pyx_t_5;
    __pyx_t_6 = __Pyx_PyInt_From_Py_intptr_t(__pyx_f_2bp_3_bp_2BP_excess(__pyx_v_self, __pyx_v_k)); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 493, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_6);
    if (unlikely(__Pyx_ListComp_Append(__pyx_t_1, (PyObject*)__pyx_t_6))) __PYX_ERR(0, 493, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
  }
  __pyx_t_6 = PyTuple_New(1); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 493, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_6);
  __Pyx_GIVEREF(__pyx_t_1);
  PyTuple_SET_ITEM(__pyx_t_6, 0, __pyx_t_1);
  __pyx_t_1 = 0;
  __pyx_t_1 = __Pyx_PyDict_NewPresized(1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 493, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  if (PyDict_SetItem(__pyx_t_1, __pyx_n_s_return_counts, Py_True) < 0) __PYX_ERR(0, 493, __pyx_L1_error)
  __pyx_t_7 = __Pyx_PyObject_Call(__pyx_t_2, __pyx_t_6, __pyx_t_1); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 493, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_7);
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  if ((likely(PyTuple_CheckExact(__pyx_t_7))) || (PyList_CheckExact(__pyx_t_7))) {
    PyObject* sequence = __pyx_t_7;
    Py_ssize_t size = __Pyx_PySequence_SIZE(sequence);
    if (unlikely(size != 2)) {
      if (size > 2) __Pyx_RaiseTooManyValuesError(2);
      else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size);
      __PYX_ERR(0, 493, __pyx_L1_error)
    }
    #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
    if (likely(PyTuple_CheckExact(sequence))) {
      __pyx_t_1 = PyTuple_GET_ITEM(sequence, 0); 
      __pyx_t_6 = PyTuple_GET_ITEM(sequence, 1); 
    } else {
      __pyx_t_1 = PyList_GET_ITEM(sequence, 0); 
      __pyx_t_6 = PyList_GET_ITEM(sequence, 1); 
    }
    __Pyx_INCREF(__pyx_t_1);
    __Pyx_INCREF(__pyx_t_6);
    #else
    __pyx_t_1 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 493, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
    __pyx_t_6 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 493, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_6);
    #endif
    __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
  } else {
    Py_ssize_t index = -1;
    __pyx_t_2 = PyObject_GetIter(__pyx_t_7); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 493, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
    __pyx_t_8 = Py_TYPE(__pyx_t_2)->tp_iternext;
    index = 0; __pyx_t_1 = __pyx_t_8(__pyx_t_2); if (unlikely(!__pyx_t_1)) goto __pyx_L5_unpacking_failed;
    __Pyx_GOTREF(__pyx_t_1);
    index = 1; __pyx_t_6 = __pyx_t_8(__pyx_t_2); if (unlikely(!__pyx_t_6)) goto __pyx_L5_unpacking_failed;
    __Pyx_GOTREF(__pyx_t_6);
    if (__Pyx_IternextUnpackEndCheck(__pyx_t_8(__pyx_t_2), 2) < 0) __PYX_ERR(0, 493, __pyx_L1_error)
    __pyx_t_8 = NULL;
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    goto __pyx_L6_unpacking_done;
    __pyx_L5_unpacking_failed:;
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    __pyx_t_8 = NULL;
    if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index);
    __PYX_ERR(0, 493, __pyx_L1_error)
    __pyx_L6_unpacking_done:;
  }
  __pyx_v_excess = __pyx_t_1;
  __pyx_t_1 = 0;
  __pyx_v_counts = __pyx_t_6;
  __pyx_t_6 = 0;
+0494:         return counts[excess.argmin()]
  __Pyx_XDECREF(__pyx_r);
  __pyx_t_6 = __Pyx_PyObject_GetAttrStr(__pyx_v_excess, __pyx_n_s_argmin); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 494, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_6);
  __pyx_t_1 = NULL;
  if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_6))) {
    __pyx_t_1 = PyMethod_GET_SELF(__pyx_t_6);
    if (likely(__pyx_t_1)) {
      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_6);
      __Pyx_INCREF(__pyx_t_1);
      __Pyx_INCREF(function);
      __Pyx_DECREF_SET(__pyx_t_6, function);
    }
  }
  __pyx_t_7 = (__pyx_t_1) ? __Pyx_PyObject_CallOneArg(__pyx_t_6, __pyx_t_1) : __Pyx_PyObject_CallNoArg(__pyx_t_6);
  __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0;
  if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 494, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_7);
  __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
  __pyx_t_6 = __Pyx_PyObject_GetItem(__pyx_v_counts, __pyx_t_7); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 494, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_6);
  __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
  __pyx_r = __pyx_t_6;
  __pyx_t_6 = 0;
  goto __pyx_L0;
 0495: 
+0496:     def minselect(self, SIZE_t i, SIZE_t j, SIZE_t q):
/* Python wrapper */
static PyObject *__pyx_pw_2bp_3_bp_2BP_47minselect(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
static char __pyx_doc_2bp_3_bp_2BP_46minselect[] = "position of the qth minimum in excess(i), excess(i + 1), . . . , excess(j).";
static PyObject *__pyx_pw_2bp_3_bp_2BP_47minselect(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
  __pyx_t_2bp_3_bp_SIZE_t __pyx_v_i;
  __pyx_t_2bp_3_bp_SIZE_t __pyx_v_j;
  __pyx_t_2bp_3_bp_SIZE_t __pyx_v_q;
  PyObject *__pyx_r = 0;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("minselect (wrapper)", 0);
  {
    static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_i,&__pyx_n_s_j,&__pyx_n_s_q,0};
    PyObject* values[3] = {0,0,0};
    if (unlikely(__pyx_kwds)) {
      Py_ssize_t kw_args;
      const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args);
      switch (pos_args) {
        case  3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2);
        CYTHON_FALLTHROUGH;
        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
        CYTHON_FALLTHROUGH;
        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
        CYTHON_FALLTHROUGH;
        case  0: break;
        default: goto __pyx_L5_argtuple_error;
      }
      kw_args = PyDict_Size(__pyx_kwds);
      switch (pos_args) {
        case  0:
        if (likely((values[0] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_i)) != 0)) kw_args--;
        else goto __pyx_L5_argtuple_error;
        CYTHON_FALLTHROUGH;
        case  1:
        if (likely((values[1] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_j)) != 0)) kw_args--;
        else {
          __Pyx_RaiseArgtupleInvalid("minselect", 1, 3, 3, 1); __PYX_ERR(0, 496, __pyx_L3_error)
        }
        CYTHON_FALLTHROUGH;
        case  2:
        if (likely((values[2] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_q)) != 0)) kw_args--;
        else {
          __Pyx_RaiseArgtupleInvalid("minselect", 1, 3, 3, 2); __PYX_ERR(0, 496, __pyx_L3_error)
        }
      }
      if (unlikely(kw_args > 0)) {
        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "minselect") < 0)) __PYX_ERR(0, 496, __pyx_L3_error)
      }
    } else if (PyTuple_GET_SIZE(__pyx_args) != 3) {
      goto __pyx_L5_argtuple_error;
    } else {
      values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
      values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
      values[2] = PyTuple_GET_ITEM(__pyx_args, 2);
    }
    __pyx_v_i = __Pyx_PyInt_As_Py_intptr_t(values[0]); if (unlikely((__pyx_v_i == ((npy_intp)-1)) && PyErr_Occurred())) __PYX_ERR(0, 496, __pyx_L3_error)
    __pyx_v_j = __Pyx_PyInt_As_Py_intptr_t(values[1]); if (unlikely((__pyx_v_j == ((npy_intp)-1)) && PyErr_Occurred())) __PYX_ERR(0, 496, __pyx_L3_error)
    __pyx_v_q = __Pyx_PyInt_As_Py_intptr_t(values[2]); if (unlikely((__pyx_v_q == ((npy_intp)-1)) && PyErr_Occurred())) __PYX_ERR(0, 496, __pyx_L3_error)
  }
  goto __pyx_L4_argument_unpacking_done;
  __pyx_L5_argtuple_error:;
  __Pyx_RaiseArgtupleInvalid("minselect", 1, 3, 3, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 496, __pyx_L3_error)
  __pyx_L3_error:;
  __Pyx_AddTraceback("bp._bp.BP.minselect", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __Pyx_RefNannyFinishContext();
  return NULL;
  __pyx_L4_argument_unpacking_done:;
  __pyx_r = __pyx_pf_2bp_3_bp_2BP_46minselect(((struct __pyx_obj_2bp_3_bp_BP *)__pyx_v_self), __pyx_v_i, __pyx_v_j, __pyx_v_q);
  int __pyx_lineno = 0;
  const char *__pyx_filename = NULL;
  int __pyx_clineno = 0;

  /* function exit code */
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}

static PyObject *__pyx_pf_2bp_3_bp_2BP_46minselect(struct __pyx_obj_2bp_3_bp_BP *__pyx_v_self, __pyx_t_2bp_3_bp_SIZE_t __pyx_v_i, __pyx_t_2bp_3_bp_SIZE_t __pyx_v_j, __pyx_t_2bp_3_bp_SIZE_t __pyx_v_q) {
  PyObject *__pyx_v_counts = NULL;
  PyObject *__pyx_v_index = NULL;
  long __pyx_v_k;
  PyObject *__pyx_r = NULL;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("minselect", 0);
/* … */
  /* function exit code */
  __pyx_L1_error:;
  __Pyx_XDECREF(__pyx_t_1);
  __Pyx_XDECREF(__pyx_t_2);
  __Pyx_XDECREF(__pyx_t_3);
  __Pyx_XDECREF(__pyx_t_7);
  __Pyx_AddTraceback("bp._bp.BP.minselect", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __pyx_r = NULL;
  __pyx_L0:;
  __Pyx_XDECREF(__pyx_v_counts);
  __Pyx_XDECREF(__pyx_v_index);
  __Pyx_XGIVEREF(__pyx_r);
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}
 0497:         """position of the qth minimum in excess(i), excess(i + 1), . . . , excess(j)."""
+0498:         counts = np.array([self.excess(k) for k in range(i, j + 1)])
  __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_np); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 498, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_array); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 498, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __pyx_t_2 = PyList_New(0); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 498, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __pyx_t_4 = (__pyx_v_j + 1);
  __pyx_t_5 = __pyx_t_4;
  for (__pyx_t_6 = __pyx_v_i; __pyx_t_6 < __pyx_t_5; __pyx_t_6+=1) {
    __pyx_v_k = __pyx_t_6;
    __pyx_t_7 = __Pyx_PyInt_From_Py_intptr_t(__pyx_f_2bp_3_bp_2BP_excess(__pyx_v_self, __pyx_v_k)); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 498, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_7);
    if (unlikely(__Pyx_ListComp_Append(__pyx_t_2, (PyObject*)__pyx_t_7))) __PYX_ERR(0, 498, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
  }
  __pyx_t_7 = NULL;
  if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
    __pyx_t_7 = PyMethod_GET_SELF(__pyx_t_3);
    if (likely(__pyx_t_7)) {
      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
      __Pyx_INCREF(__pyx_t_7);
      __Pyx_INCREF(function);
      __Pyx_DECREF_SET(__pyx_t_3, function);
    }
  }
  __pyx_t_1 = (__pyx_t_7) ? __Pyx_PyObject_Call2Args(__pyx_t_3, __pyx_t_7, __pyx_t_2) : __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_2);
  __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 498, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  __pyx_v_counts = __pyx_t_1;
  __pyx_t_1 = 0;
+0499:         index = counts == counts.min()
  __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_v_counts, __pyx_n_s_min); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 499, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __pyx_t_2 = NULL;
  if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_3))) {
    __pyx_t_2 = PyMethod_GET_SELF(__pyx_t_3);
    if (likely(__pyx_t_2)) {
      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
      __Pyx_INCREF(__pyx_t_2);
      __Pyx_INCREF(function);
      __Pyx_DECREF_SET(__pyx_t_3, function);
    }
  }
  __pyx_t_1 = (__pyx_t_2) ? __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_2) : __Pyx_PyObject_CallNoArg(__pyx_t_3);
  __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
  if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 499, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  __pyx_t_3 = PyObject_RichCompare(__pyx_v_counts, __pyx_t_1, Py_EQ); __Pyx_XGOTREF(__pyx_t_3); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 499, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_v_index = __pyx_t_3;
  __pyx_t_3 = 0;
 0500: 
+0501:         if index.sum() < q:
  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_index, __pyx_n_s_sum); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 501, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_2 = NULL;
  if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_1))) {
    __pyx_t_2 = PyMethod_GET_SELF(__pyx_t_1);
    if (likely(__pyx_t_2)) {
      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_1);
      __Pyx_INCREF(__pyx_t_2);
      __Pyx_INCREF(function);
      __Pyx_DECREF_SET(__pyx_t_1, function);
    }
  }
  __pyx_t_3 = (__pyx_t_2) ? __Pyx_PyObject_CallOneArg(__pyx_t_1, __pyx_t_2) : __Pyx_PyObject_CallNoArg(__pyx_t_1);
  __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
  if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 501, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_t_1 = __Pyx_PyInt_From_Py_intptr_t(__pyx_v_q); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 501, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_2 = PyObject_RichCompare(__pyx_t_3, __pyx_t_1, Py_LT); __Pyx_XGOTREF(__pyx_t_2); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 501, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_t_8 = __Pyx_PyObject_IsTrue(__pyx_t_2); if (unlikely(__pyx_t_8 < 0)) __PYX_ERR(0, 501, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  if (__pyx_t_8) {
/* … */
  }
+0502:             return None
    __Pyx_XDECREF(__pyx_r);
    __pyx_r = Py_None; __Pyx_INCREF(Py_None);
    goto __pyx_L0;
 0503:         else:
+0504:             return i + index.nonzero()[0][q - 1]
  /*else*/ {
    __Pyx_XDECREF(__pyx_r);
    __pyx_t_2 = __Pyx_PyInt_From_Py_intptr_t(__pyx_v_i); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 504, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_v_index, __pyx_n_s_nonzero); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 504, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_3);
    __pyx_t_7 = NULL;
    if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_3))) {
      __pyx_t_7 = PyMethod_GET_SELF(__pyx_t_3);
      if (likely(__pyx_t_7)) {
        PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
        __Pyx_INCREF(__pyx_t_7);
        __Pyx_INCREF(function);
        __Pyx_DECREF_SET(__pyx_t_3, function);
      }
    }
    __pyx_t_1 = (__pyx_t_7) ? __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_7) : __Pyx_PyObject_CallNoArg(__pyx_t_3);
    __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
    if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 504, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
    __pyx_t_3 = __Pyx_GetItemInt(__pyx_t_1, 0, long, 1, __Pyx_PyInt_From_long, 0, 0, 0); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 504, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_3);
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
    __pyx_t_4 = (__pyx_v_q - 1);
    __pyx_t_1 = __Pyx_GetItemInt(__pyx_t_3, __pyx_t_4, long, 1, __Pyx_PyInt_From_long, 0, 0, 0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 504, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
    __pyx_t_3 = PyNumber_Add(__pyx_t_2, __pyx_t_1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 504, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_3);
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
    __pyx_r = __pyx_t_3;
    __pyx_t_3 = 0;
    goto __pyx_L0;
  }
 0505: 
+0506:     cpdef SIZE_t nsibling(self, SIZE_t i) nogil:
static PyObject *__pyx_pw_2bp_3_bp_2BP_49nsibling(PyObject *__pyx_v_self, PyObject *__pyx_arg_i); /*proto*/
static __pyx_t_2bp_3_bp_SIZE_t __pyx_f_2bp_3_bp_2BP_nsibling(struct __pyx_obj_2bp_3_bp_BP *__pyx_v_self, __pyx_t_2bp_3_bp_SIZE_t __pyx_v_i, CYTHON_UNUSED int __pyx_skip_dispatch) {
  __pyx_t_2bp_3_bp_SIZE_t __pyx_v_pos;
  __pyx_t_2bp_3_bp_SIZE_t __pyx_r;
/* … */
  /* function exit code */
  __pyx_L0:;
  return __pyx_r;
}

/* Python wrapper */
static PyObject *__pyx_pw_2bp_3_bp_2BP_49nsibling(PyObject *__pyx_v_self, PyObject *__pyx_arg_i); /*proto*/
static char __pyx_doc_2bp_3_bp_2BP_48nsibling[] = "The next sibling of i (i.e., the sibling to the right)\n\n        nsibling(i) = close(i) + 1 (if the result j holds B[j] = 0 then i has no next sibling)\n\n        Will return 0 if there is no sibling. This makes sense as the root\n        cannot have a sibling by definition\n        ";
static PyObject *__pyx_pw_2bp_3_bp_2BP_49nsibling(PyObject *__pyx_v_self, PyObject *__pyx_arg_i) {
  __pyx_t_2bp_3_bp_SIZE_t __pyx_v_i;
  PyObject *__pyx_r = 0;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("nsibling (wrapper)", 0);
  assert(__pyx_arg_i); {
    __pyx_v_i = __Pyx_PyInt_As_Py_intptr_t(__pyx_arg_i); if (unlikely((__pyx_v_i == ((npy_intp)-1)) && PyErr_Occurred())) __PYX_ERR(0, 506, __pyx_L3_error)
  }
  goto __pyx_L4_argument_unpacking_done;
  __pyx_L3_error:;
  __Pyx_AddTraceback("bp._bp.BP.nsibling", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __Pyx_RefNannyFinishContext();
  return NULL;
  __pyx_L4_argument_unpacking_done:;
  __pyx_r = __pyx_pf_2bp_3_bp_2BP_48nsibling(((struct __pyx_obj_2bp_3_bp_BP *)__pyx_v_self), ((__pyx_t_2bp_3_bp_SIZE_t)__pyx_v_i));
  int __pyx_lineno = 0;
  const char *__pyx_filename = NULL;
  int __pyx_clineno = 0;

  /* function exit code */
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}

static PyObject *__pyx_pf_2bp_3_bp_2BP_48nsibling(struct __pyx_obj_2bp_3_bp_BP *__pyx_v_self, __pyx_t_2bp_3_bp_SIZE_t __pyx_v_i) {
  PyObject *__pyx_r = NULL;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("nsibling", 0);
  __Pyx_XDECREF(__pyx_r);
  __pyx_t_1 = __Pyx_PyInt_From_Py_intptr_t(__pyx_f_2bp_3_bp_2BP_nsibling(__pyx_v_self, __pyx_v_i, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 506, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_r = __pyx_t_1;
  __pyx_t_1 = 0;
  goto __pyx_L0;

  /* function exit code */
  __pyx_L1_error:;
  __Pyx_XDECREF(__pyx_t_1);
  __Pyx_AddTraceback("bp._bp.BP.nsibling", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __pyx_r = NULL;
  __pyx_L0:;
  __Pyx_XGIVEREF(__pyx_r);
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}
 0507:         """The next sibling of i (i.e., the sibling to the right)
 0508: 
 0509:         nsibling(i) = close(i) + 1 (if the result j holds B[j] = 0 then i has no next sibling)
 0510: 
 0511:         Will return 0 if there is no sibling. This makes sense as the root
 0512:         cannot have a sibling by definition
 0513:         """
 0514:         cdef SIZE_t pos
 0515: 
+0516:         if self._b_ptr[i]:
  __pyx_t_1 = ((__pyx_v_self->_b_ptr[__pyx_v_i]) != 0);
  if (__pyx_t_1) {
/* … */
    goto __pyx_L3;
  }
+0517:             pos = self.close(i) + 1
    __pyx_v_pos = (__pyx_f_2bp_3_bp_2BP_close(__pyx_v_self, __pyx_v_i, 0) + 1);
 0518:         else:
+0519:             pos = self.nsibling(self.open(i))
  /*else*/ {
    __pyx_v_pos = __pyx_f_2bp_3_bp_2BP_nsibling(__pyx_v_self, __pyx_f_2bp_3_bp_2BP_open(__pyx_v_self, __pyx_v_i), 0);
  }
  __pyx_L3:;
 0520: 
+0521:         if pos >= self.size:
  __pyx_t_1 = ((__pyx_v_pos >= __pyx_v_self->size) != 0);
  if (__pyx_t_1) {
/* … */
  }
+0522:             return 0
    __pyx_r = 0;
    goto __pyx_L0;
+0523:         elif self._b_ptr[pos]:
  __pyx_t_1 = ((__pyx_v_self->_b_ptr[__pyx_v_pos]) != 0);
  if (__pyx_t_1) {
/* … */
  }
+0524:             return pos
    __pyx_r = __pyx_v_pos;
    goto __pyx_L0;
 0525:         else:
+0526:             return 0
  /*else*/ {
    __pyx_r = 0;
    goto __pyx_L0;
  }
 0527: 
+0528:     cpdef SIZE_t psibling(self, SIZE_t i) nogil:
static PyObject *__pyx_pw_2bp_3_bp_2BP_51psibling(PyObject *__pyx_v_self, PyObject *__pyx_arg_i); /*proto*/
static __pyx_t_2bp_3_bp_SIZE_t __pyx_f_2bp_3_bp_2BP_psibling(struct __pyx_obj_2bp_3_bp_BP *__pyx_v_self, __pyx_t_2bp_3_bp_SIZE_t __pyx_v_i, CYTHON_UNUSED int __pyx_skip_dispatch) {
  __pyx_t_2bp_3_bp_SIZE_t __pyx_v_pos;
  __pyx_t_2bp_3_bp_SIZE_t __pyx_r;
/* … */
  /* function exit code */
  __pyx_L0:;
  return __pyx_r;
}

/* Python wrapper */
static PyObject *__pyx_pw_2bp_3_bp_2BP_51psibling(PyObject *__pyx_v_self, PyObject *__pyx_arg_i); /*proto*/
static char __pyx_doc_2bp_3_bp_2BP_50psibling[] = "The previous sibling of i (i.e., the sibling to the left)\n\n        psibling(i) = open(i \342\210\222 1) (if B[i \342\210\222 1] = 1 then i has no previous sibling)\n\n        Will return 0 if there is no sibling. This makes sense as the root\n        cannot have a sibling by definition\n        ";
static PyObject *__pyx_pw_2bp_3_bp_2BP_51psibling(PyObject *__pyx_v_self, PyObject *__pyx_arg_i) {
  __pyx_t_2bp_3_bp_SIZE_t __pyx_v_i;
  PyObject *__pyx_r = 0;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("psibling (wrapper)", 0);
  assert(__pyx_arg_i); {
    __pyx_v_i = __Pyx_PyInt_As_Py_intptr_t(__pyx_arg_i); if (unlikely((__pyx_v_i == ((npy_intp)-1)) && PyErr_Occurred())) __PYX_ERR(0, 528, __pyx_L3_error)
  }
  goto __pyx_L4_argument_unpacking_done;
  __pyx_L3_error:;
  __Pyx_AddTraceback("bp._bp.BP.psibling", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __Pyx_RefNannyFinishContext();
  return NULL;
  __pyx_L4_argument_unpacking_done:;
  __pyx_r = __pyx_pf_2bp_3_bp_2BP_50psibling(((struct __pyx_obj_2bp_3_bp_BP *)__pyx_v_self), ((__pyx_t_2bp_3_bp_SIZE_t)__pyx_v_i));
  int __pyx_lineno = 0;
  const char *__pyx_filename = NULL;
  int __pyx_clineno = 0;

  /* function exit code */
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}

static PyObject *__pyx_pf_2bp_3_bp_2BP_50psibling(struct __pyx_obj_2bp_3_bp_BP *__pyx_v_self, __pyx_t_2bp_3_bp_SIZE_t __pyx_v_i) {
  PyObject *__pyx_r = NULL;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("psibling", 0);
  __Pyx_XDECREF(__pyx_r);
  __pyx_t_1 = __Pyx_PyInt_From_Py_intptr_t(__pyx_f_2bp_3_bp_2BP_psibling(__pyx_v_self, __pyx_v_i, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 528, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_r = __pyx_t_1;
  __pyx_t_1 = 0;
  goto __pyx_L0;

  /* function exit code */
  __pyx_L1_error:;
  __Pyx_XDECREF(__pyx_t_1);
  __Pyx_AddTraceback("bp._bp.BP.psibling", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __pyx_r = NULL;
  __pyx_L0:;
  __Pyx_XGIVEREF(__pyx_r);
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}
 0529:         """The previous sibling of i (i.e., the sibling to the left)
 0530: 
 0531:         psibling(i) = open(i − 1) (if B[i − 1] = 1 then i has no previous sibling)
 0532: 
 0533:         Will return 0 if there is no sibling. This makes sense as the root
 0534:         cannot have a sibling by definition
 0535:         """
 0536:         cdef SIZE_t pos
 0537: 
+0538:         if self._b_ptr[i]:
  __pyx_t_1 = ((__pyx_v_self->_b_ptr[__pyx_v_i]) != 0);
  if (__pyx_t_1) {
/* … */
    goto __pyx_L3;
  }
+0539:             if self._b_ptr[max(0, i - 1)]:
    __pyx_t_1 = ((__pyx_v_self->_b_ptr[__pyx_f_2bp_3_bp_max(0, (__pyx_v_i - 1))]) != 0);
    if (__pyx_t_1) {
/* … */
    }
+0540:                 return 0
      __pyx_r = 0;
      goto __pyx_L0;
 0541: 
+0542:             pos = self.open(i - 1)
    __pyx_v_pos = __pyx_f_2bp_3_bp_2BP_open(__pyx_v_self, (__pyx_v_i - 1));
 0543:         else:
+0544:             pos = self.psibling(self.open(i))
  /*else*/ {
    __pyx_v_pos = __pyx_f_2bp_3_bp_2BP_psibling(__pyx_v_self, __pyx_f_2bp_3_bp_2BP_open(__pyx_v_self, __pyx_v_i), 0);
  }
  __pyx_L3:;
 0545: 
+0546:         if pos < 0:
  __pyx_t_1 = ((__pyx_v_pos < 0) != 0);
  if (__pyx_t_1) {
/* … */
  }
+0547:             return 0
    __pyx_r = 0;
    goto __pyx_L0;
+0548:         elif self._b_ptr[pos]:
  __pyx_t_1 = ((__pyx_v_self->_b_ptr[__pyx_v_pos]) != 0);
  if (__pyx_t_1) {
/* … */
  }
+0549:             return pos
    __pyx_r = __pyx_v_pos;
    goto __pyx_L0;
 0550:         else:
+0551:             return 0
  /*else*/ {
    __pyx_r = 0;
    goto __pyx_L0;
  }
 0552: 
+0553:     cpdef SIZE_t preorder(self, SIZE_t i) nogil:
static PyObject *__pyx_pw_2bp_3_bp_2BP_53preorder(PyObject *__pyx_v_self, PyObject *__pyx_arg_i); /*proto*/
static __pyx_t_2bp_3_bp_SIZE_t __pyx_f_2bp_3_bp_2BP_preorder(struct __pyx_obj_2bp_3_bp_BP *__pyx_v_self, __pyx_t_2bp_3_bp_SIZE_t __pyx_v_i, CYTHON_UNUSED int __pyx_skip_dispatch) {
  __pyx_t_2bp_3_bp_SIZE_t __pyx_r;
/* … */
  /* function exit code */
  __pyx_L0:;
  return __pyx_r;
}

/* Python wrapper */
static PyObject *__pyx_pw_2bp_3_bp_2BP_53preorder(PyObject *__pyx_v_self, PyObject *__pyx_arg_i); /*proto*/
static char __pyx_doc_2bp_3_bp_2BP_52preorder[] = "Preorder rank of node i\n        \n        Parameters\n        ----------\n        i : int\n            The node index to assess the preorder order of.\n\n        Returns\n        -------\n        int\n            The nodes order of evaluation in a preorder traversal of the tree.\n        ";
static PyObject *__pyx_pw_2bp_3_bp_2BP_53preorder(PyObject *__pyx_v_self, PyObject *__pyx_arg_i) {
  __pyx_t_2bp_3_bp_SIZE_t __pyx_v_i;
  PyObject *__pyx_r = 0;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("preorder (wrapper)", 0);
  assert(__pyx_arg_i); {
    __pyx_v_i = __Pyx_PyInt_As_Py_intptr_t(__pyx_arg_i); if (unlikely((__pyx_v_i == ((npy_intp)-1)) && PyErr_Occurred())) __PYX_ERR(0, 553, __pyx_L3_error)
  }
  goto __pyx_L4_argument_unpacking_done;
  __pyx_L3_error:;
  __Pyx_AddTraceback("bp._bp.BP.preorder", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __Pyx_RefNannyFinishContext();
  return NULL;
  __pyx_L4_argument_unpacking_done:;
  __pyx_r = __pyx_pf_2bp_3_bp_2BP_52preorder(((struct __pyx_obj_2bp_3_bp_BP *)__pyx_v_self), ((__pyx_t_2bp_3_bp_SIZE_t)__pyx_v_i));
  int __pyx_lineno = 0;
  const char *__pyx_filename = NULL;
  int __pyx_clineno = 0;

  /* function exit code */
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}

static PyObject *__pyx_pf_2bp_3_bp_2BP_52preorder(struct __pyx_obj_2bp_3_bp_BP *__pyx_v_self, __pyx_t_2bp_3_bp_SIZE_t __pyx_v_i) {
  PyObject *__pyx_r = NULL;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("preorder", 0);
  __Pyx_XDECREF(__pyx_r);
  __pyx_t_1 = __Pyx_PyInt_From_Py_intptr_t(__pyx_f_2bp_3_bp_2BP_preorder(__pyx_v_self, __pyx_v_i, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 553, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_r = __pyx_t_1;
  __pyx_t_1 = 0;
  goto __pyx_L0;

  /* function exit code */
  __pyx_L1_error:;
  __Pyx_XDECREF(__pyx_t_1);
  __Pyx_AddTraceback("bp._bp.BP.preorder", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __pyx_r = NULL;
  __pyx_L0:;
  __Pyx_XGIVEREF(__pyx_r);
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}
 0554:         """Preorder rank of node i
 0555:         
 0556:         Parameters
 0557:         ----------
 0558:         i : int
 0559:             The node index to assess the preorder order of.
 0560: 
 0561:         Returns
 0562:         -------
 0563:         int
 0564:             The nodes order of evaluation in a preorder traversal of the tree.
 0565:         """
+0566:         if self._b_ptr[i]:
  __pyx_t_1 = ((__pyx_v_self->_b_ptr[__pyx_v_i]) != 0);
  if (__pyx_t_1) {
/* … */
  }
+0567:             return self.rank(1, i)
    __pyx_r = __pyx_f_2bp_3_bp_2BP_rank(__pyx_v_self, 1, __pyx_v_i);
    goto __pyx_L0;
 0568:         else:
+0569:             return self.preorder(self.open(i))
  /*else*/ {
    __pyx_r = __pyx_f_2bp_3_bp_2BP_preorder(__pyx_v_self, __pyx_f_2bp_3_bp_2BP_open(__pyx_v_self, __pyx_v_i), 0);
    goto __pyx_L0;
  }
 0570: 
+0571:     cpdef SIZE_t preorderselect(self, SIZE_t k) nogil:
static PyObject *__pyx_pw_2bp_3_bp_2BP_55preorderselect(PyObject *__pyx_v_self, PyObject *__pyx_arg_k); /*proto*/
static __pyx_t_2bp_3_bp_SIZE_t __pyx_f_2bp_3_bp_2BP_preorderselect(struct __pyx_obj_2bp_3_bp_BP *__pyx_v_self, __pyx_t_2bp_3_bp_SIZE_t __pyx_v_k, CYTHON_UNUSED int __pyx_skip_dispatch) {
  __pyx_t_2bp_3_bp_SIZE_t __pyx_r;
/* … */
  /* function exit code */
  __pyx_L0:;
  return __pyx_r;
}

/* Python wrapper */
static PyObject *__pyx_pw_2bp_3_bp_2BP_55preorderselect(PyObject *__pyx_v_self, PyObject *__pyx_arg_k); /*proto*/
static char __pyx_doc_2bp_3_bp_2BP_54preorderselect[] = "The index of the node with preorder k\n        \n        Parameters\n        ----------\n        k : int\n            The preorder evaluation order to search for.\n\n        Returns\n        -------\n        int\n            The index position of the node in the tree.\n        ";
static PyObject *__pyx_pw_2bp_3_bp_2BP_55preorderselect(PyObject *__pyx_v_self, PyObject *__pyx_arg_k) {
  __pyx_t_2bp_3_bp_SIZE_t __pyx_v_k;
  PyObject *__pyx_r = 0;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("preorderselect (wrapper)", 0);
  assert(__pyx_arg_k); {
    __pyx_v_k = __Pyx_PyInt_As_Py_intptr_t(__pyx_arg_k); if (unlikely((__pyx_v_k == ((npy_intp)-1)) && PyErr_Occurred())) __PYX_ERR(0, 571, __pyx_L3_error)
  }
  goto __pyx_L4_argument_unpacking_done;
  __pyx_L3_error:;
  __Pyx_AddTraceback("bp._bp.BP.preorderselect", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __Pyx_RefNannyFinishContext();
  return NULL;
  __pyx_L4_argument_unpacking_done:;
  __pyx_r = __pyx_pf_2bp_3_bp_2BP_54preorderselect(((struct __pyx_obj_2bp_3_bp_BP *)__pyx_v_self), ((__pyx_t_2bp_3_bp_SIZE_t)__pyx_v_k));
  int __pyx_lineno = 0;
  const char *__pyx_filename = NULL;
  int __pyx_clineno = 0;

  /* function exit code */
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}

static PyObject *__pyx_pf_2bp_3_bp_2BP_54preorderselect(struct __pyx_obj_2bp_3_bp_BP *__pyx_v_self, __pyx_t_2bp_3_bp_SIZE_t __pyx_v_k) {
  PyObject *__pyx_r = NULL;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("preorderselect", 0);
  __Pyx_XDECREF(__pyx_r);
  __pyx_t_1 = __Pyx_PyInt_From_Py_intptr_t(__pyx_f_2bp_3_bp_2BP_preorderselect(__pyx_v_self, __pyx_v_k, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 571, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_r = __pyx_t_1;
  __pyx_t_1 = 0;
  goto __pyx_L0;

  /* function exit code */
  __pyx_L1_error:;
  __Pyx_XDECREF(__pyx_t_1);
  __Pyx_AddTraceback("bp._bp.BP.preorderselect", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __pyx_r = NULL;
  __pyx_L0:;
  __Pyx_XGIVEREF(__pyx_r);
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}
 0572:         """The index of the node with preorder k
 0573:         
 0574:         Parameters
 0575:         ----------
 0576:         k : int
 0577:             The preorder evaluation order to search for.
 0578: 
 0579:         Returns
 0580:         -------
 0581:         int
 0582:             The index position of the node in the tree.
 0583:         """
+0584:         return self.select(1, k)
  __pyx_r = __pyx_f_2bp_3_bp_2BP_select(__pyx_v_self, 1, __pyx_v_k);
  goto __pyx_L0;
 0585: 
+0586:     cpdef SIZE_t postorder(self, SIZE_t i) nogil:
static PyObject *__pyx_pw_2bp_3_bp_2BP_57postorder(PyObject *__pyx_v_self, PyObject *__pyx_arg_i); /*proto*/
static __pyx_t_2bp_3_bp_SIZE_t __pyx_f_2bp_3_bp_2BP_postorder(struct __pyx_obj_2bp_3_bp_BP *__pyx_v_self, __pyx_t_2bp_3_bp_SIZE_t __pyx_v_i, CYTHON_UNUSED int __pyx_skip_dispatch) {
  __pyx_t_2bp_3_bp_SIZE_t __pyx_r;
/* … */
  /* function exit code */
  __pyx_L0:;
  return __pyx_r;
}

/* Python wrapper */
static PyObject *__pyx_pw_2bp_3_bp_2BP_57postorder(PyObject *__pyx_v_self, PyObject *__pyx_arg_i); /*proto*/
static char __pyx_doc_2bp_3_bp_2BP_56postorder[] = "Postorder rank of node i\n        \n        Parameters\n        ----------\n        i : int\n            The node index to assess the postorder order of.\n\n        Returns\n        -------\n        int\n            The nodes order of evaluation in a postorder traversal of the tree.\n        ";
static PyObject *__pyx_pw_2bp_3_bp_2BP_57postorder(PyObject *__pyx_v_self, PyObject *__pyx_arg_i) {
  __pyx_t_2bp_3_bp_SIZE_t __pyx_v_i;
  PyObject *__pyx_r = 0;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("postorder (wrapper)", 0);
  assert(__pyx_arg_i); {
    __pyx_v_i = __Pyx_PyInt_As_Py_intptr_t(__pyx_arg_i); if (unlikely((__pyx_v_i == ((npy_intp)-1)) && PyErr_Occurred())) __PYX_ERR(0, 586, __pyx_L3_error)
  }
  goto __pyx_L4_argument_unpacking_done;
  __pyx_L3_error:;
  __Pyx_AddTraceback("bp._bp.BP.postorder", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __Pyx_RefNannyFinishContext();
  return NULL;
  __pyx_L4_argument_unpacking_done:;
  __pyx_r = __pyx_pf_2bp_3_bp_2BP_56postorder(((struct __pyx_obj_2bp_3_bp_BP *)__pyx_v_self), ((__pyx_t_2bp_3_bp_SIZE_t)__pyx_v_i));
  int __pyx_lineno = 0;
  const char *__pyx_filename = NULL;
  int __pyx_clineno = 0;

  /* function exit code */
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}

static PyObject *__pyx_pf_2bp_3_bp_2BP_56postorder(struct __pyx_obj_2bp_3_bp_BP *__pyx_v_self, __pyx_t_2bp_3_bp_SIZE_t __pyx_v_i) {
  PyObject *__pyx_r = NULL;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("postorder", 0);
  __Pyx_XDECREF(__pyx_r);
  __pyx_t_1 = __Pyx_PyInt_From_Py_intptr_t(__pyx_f_2bp_3_bp_2BP_postorder(__pyx_v_self, __pyx_v_i, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 586, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_r = __pyx_t_1;
  __pyx_t_1 = 0;
  goto __pyx_L0;

  /* function exit code */
  __pyx_L1_error:;
  __Pyx_XDECREF(__pyx_t_1);
  __Pyx_AddTraceback("bp._bp.BP.postorder", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __pyx_r = NULL;
  __pyx_L0:;
  __Pyx_XGIVEREF(__pyx_r);
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}
 0587:         """Postorder rank of node i
 0588:         
 0589:         Parameters
 0590:         ----------
 0591:         i : int
 0592:             The node index to assess the postorder order of.
 0593: 
 0594:         Returns
 0595:         -------
 0596:         int
 0597:             The nodes order of evaluation in a postorder traversal of the tree.
 0598:         """
+0599:         if self._b_ptr[i]:
  __pyx_t_1 = ((__pyx_v_self->_b_ptr[__pyx_v_i]) != 0);
  if (__pyx_t_1) {
/* … */
  }
+0600:             return self.rank(0, self.close(i))
    __pyx_r = __pyx_f_2bp_3_bp_2BP_rank(__pyx_v_self, 0, __pyx_f_2bp_3_bp_2BP_close(__pyx_v_self, __pyx_v_i, 0));
    goto __pyx_L0;
 0601:         else:
+0602:             return self.rank(0, i)
  /*else*/ {
    __pyx_r = __pyx_f_2bp_3_bp_2BP_rank(__pyx_v_self, 0, __pyx_v_i);
    goto __pyx_L0;
  }
 0603: 
+0604:     cpdef SIZE_t postorderselect(self, SIZE_t k) nogil:
static PyObject *__pyx_pw_2bp_3_bp_2BP_59postorderselect(PyObject *__pyx_v_self, PyObject *__pyx_arg_k); /*proto*/
static __pyx_t_2bp_3_bp_SIZE_t __pyx_f_2bp_3_bp_2BP_postorderselect(struct __pyx_obj_2bp_3_bp_BP *__pyx_v_self, __pyx_t_2bp_3_bp_SIZE_t __pyx_v_k, CYTHON_UNUSED int __pyx_skip_dispatch) {
  __pyx_t_2bp_3_bp_SIZE_t __pyx_r;
/* … */
  /* function exit code */
  __pyx_L0:;
  return __pyx_r;
}

/* Python wrapper */
static PyObject *__pyx_pw_2bp_3_bp_2BP_59postorderselect(PyObject *__pyx_v_self, PyObject *__pyx_arg_k); /*proto*/
static char __pyx_doc_2bp_3_bp_2BP_58postorderselect[] = "The index of the node with postorder k\n        \n        Parameters\n        ----------\n        k : int\n            The postorder evaluation order to search for.\n\n        Returns\n        -------\n        int\n            The index position of the node in the tree.\n        ";
static PyObject *__pyx_pw_2bp_3_bp_2BP_59postorderselect(PyObject *__pyx_v_self, PyObject *__pyx_arg_k) {
  __pyx_t_2bp_3_bp_SIZE_t __pyx_v_k;
  PyObject *__pyx_r = 0;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("postorderselect (wrapper)", 0);
  assert(__pyx_arg_k); {
    __pyx_v_k = __Pyx_PyInt_As_Py_intptr_t(__pyx_arg_k); if (unlikely((__pyx_v_k == ((npy_intp)-1)) && PyErr_Occurred())) __PYX_ERR(0, 604, __pyx_L3_error)
  }
  goto __pyx_L4_argument_unpacking_done;
  __pyx_L3_error:;
  __Pyx_AddTraceback("bp._bp.BP.postorderselect", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __Pyx_RefNannyFinishContext();
  return NULL;
  __pyx_L4_argument_unpacking_done:;
  __pyx_r = __pyx_pf_2bp_3_bp_2BP_58postorderselect(((struct __pyx_obj_2bp_3_bp_BP *)__pyx_v_self), ((__pyx_t_2bp_3_bp_SIZE_t)__pyx_v_k));
  int __pyx_lineno = 0;
  const char *__pyx_filename = NULL;
  int __pyx_clineno = 0;

  /* function exit code */
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}

static PyObject *__pyx_pf_2bp_3_bp_2BP_58postorderselect(struct __pyx_obj_2bp_3_bp_BP *__pyx_v_self, __pyx_t_2bp_3_bp_SIZE_t __pyx_v_k) {
  PyObject *__pyx_r = NULL;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("postorderselect", 0);
  __Pyx_XDECREF(__pyx_r);
  __pyx_t_1 = __Pyx_PyInt_From_Py_intptr_t(__pyx_f_2bp_3_bp_2BP_postorderselect(__pyx_v_self, __pyx_v_k, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 604, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_r = __pyx_t_1;
  __pyx_t_1 = 0;
  goto __pyx_L0;

  /* function exit code */
  __pyx_L1_error:;
  __Pyx_XDECREF(__pyx_t_1);
  __Pyx_AddTraceback("bp._bp.BP.postorderselect", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __pyx_r = NULL;
  __pyx_L0:;
  __Pyx_XGIVEREF(__pyx_r);
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}
 0605:         """The index of the node with postorder k
 0606:         
 0607:         Parameters
 0608:         ----------
 0609:         k : int
 0610:             The postorder evaluation order to search for.
 0611: 
 0612:         Returns
 0613:         -------
 0614:         int
 0615:             The index position of the node in the tree.
 0616:         """
+0617:         return self.open(self.select(0, k))
  __pyx_r = __pyx_f_2bp_3_bp_2BP_open(__pyx_v_self, __pyx_f_2bp_3_bp_2BP_select(__pyx_v_self, 0, __pyx_v_k));
  goto __pyx_L0;
 0618: 
+0619:     cpdef BOOL_t isancestor(self, SIZE_t i, SIZE_t j) nogil:
static PyObject *__pyx_pw_2bp_3_bp_2BP_61isancestor(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
static __pyx_t_2bp_3_bp_BOOL_t __pyx_f_2bp_3_bp_2BP_isancestor(struct __pyx_obj_2bp_3_bp_BP *__pyx_v_self, __pyx_t_2bp_3_bp_SIZE_t __pyx_v_i, __pyx_t_2bp_3_bp_SIZE_t __pyx_v_j, CYTHON_UNUSED int __pyx_skip_dispatch) {
  __pyx_t_2bp_3_bp_BOOL_t __pyx_r;
/* … */
  /* function exit code */
  __pyx_L0:;
  return __pyx_r;
}

/* Python wrapper */
static PyObject *__pyx_pw_2bp_3_bp_2BP_61isancestor(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
static char __pyx_doc_2bp_3_bp_2BP_60isancestor[] = "Whether i is an ancestor of j\n\n        Parameters\n        ----------\n        i : int\n            A node index\n        j : int\n            A node index\n\n        Note\n        ----\n        False is returned if i == j. A node cannot be an ancestor of itself.\n\n        Returns\n        -------\n        bool\n            True if i is an ancestor of j, False otherwise.\n        ";
static PyObject *__pyx_pw_2bp_3_bp_2BP_61isancestor(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
  __pyx_t_2bp_3_bp_SIZE_t __pyx_v_i;
  __pyx_t_2bp_3_bp_SIZE_t __pyx_v_j;
  PyObject *__pyx_r = 0;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("isancestor (wrapper)", 0);
  {
    static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_i,&__pyx_n_s_j,0};
    PyObject* values[2] = {0,0};
    if (unlikely(__pyx_kwds)) {
      Py_ssize_t kw_args;
      const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args);
      switch (pos_args) {
        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
        CYTHON_FALLTHROUGH;
        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
        CYTHON_FALLTHROUGH;
        case  0: break;
        default: goto __pyx_L5_argtuple_error;
      }
      kw_args = PyDict_Size(__pyx_kwds);
      switch (pos_args) {
        case  0:
        if (likely((values[0] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_i)) != 0)) kw_args--;
        else goto __pyx_L5_argtuple_error;
        CYTHON_FALLTHROUGH;
        case  1:
        if (likely((values[1] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_j)) != 0)) kw_args--;
        else {
          __Pyx_RaiseArgtupleInvalid("isancestor", 1, 2, 2, 1); __PYX_ERR(0, 619, __pyx_L3_error)
        }
      }
      if (unlikely(kw_args > 0)) {
        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "isancestor") < 0)) __PYX_ERR(0, 619, __pyx_L3_error)
      }
    } else if (PyTuple_GET_SIZE(__pyx_args) != 2) {
      goto __pyx_L5_argtuple_error;
    } else {
      values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
      values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
    }
    __pyx_v_i = __Pyx_PyInt_As_Py_intptr_t(values[0]); if (unlikely((__pyx_v_i == ((npy_intp)-1)) && PyErr_Occurred())) __PYX_ERR(0, 619, __pyx_L3_error)
    __pyx_v_j = __Pyx_PyInt_As_Py_intptr_t(values[1]); if (unlikely((__pyx_v_j == ((npy_intp)-1)) && PyErr_Occurred())) __PYX_ERR(0, 619, __pyx_L3_error)
  }
  goto __pyx_L4_argument_unpacking_done;
  __pyx_L5_argtuple_error:;
  __Pyx_RaiseArgtupleInvalid("isancestor", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 619, __pyx_L3_error)
  __pyx_L3_error:;
  __Pyx_AddTraceback("bp._bp.BP.isancestor", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __Pyx_RefNannyFinishContext();
  return NULL;
  __pyx_L4_argument_unpacking_done:;
  __pyx_r = __pyx_pf_2bp_3_bp_2BP_60isancestor(((struct __pyx_obj_2bp_3_bp_BP *)__pyx_v_self), __pyx_v_i, __pyx_v_j);
  int __pyx_lineno = 0;
  const char *__pyx_filename = NULL;
  int __pyx_clineno = 0;

  /* function exit code */
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}

static PyObject *__pyx_pf_2bp_3_bp_2BP_60isancestor(struct __pyx_obj_2bp_3_bp_BP *__pyx_v_self, __pyx_t_2bp_3_bp_SIZE_t __pyx_v_i, __pyx_t_2bp_3_bp_SIZE_t __pyx_v_j) {
  PyObject *__pyx_r = NULL;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("isancestor", 0);
  __Pyx_XDECREF(__pyx_r);
  __pyx_t_1 = __Pyx_PyInt_From_npy_uint8(__pyx_f_2bp_3_bp_2BP_isancestor(__pyx_v_self, __pyx_v_i, __pyx_v_j, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 619, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_r = __pyx_t_1;
  __pyx_t_1 = 0;
  goto __pyx_L0;

  /* function exit code */
  __pyx_L1_error:;
  __Pyx_XDECREF(__pyx_t_1);
  __Pyx_AddTraceback("bp._bp.BP.isancestor", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __pyx_r = NULL;
  __pyx_L0:;
  __Pyx_XGIVEREF(__pyx_r);
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}
 0620:         """Whether i is an ancestor of j
 0621: 
 0622:         Parameters
 0623:         ----------
 0624:         i : int
 0625:             A node index
 0626:         j : int
 0627:             A node index
 0628: 
 0629:         Note
 0630:         ----
 0631:         False is returned if i == j. A node cannot be an ancestor of itself.
 0632: 
 0633:         Returns
 0634:         -------
 0635:         bool
 0636:             True if i is an ancestor of j, False otherwise.
 0637:         """
+0638:         if i == j:
  __pyx_t_1 = ((__pyx_v_i == __pyx_v_j) != 0);
  if (__pyx_t_1) {
/* … */
  }
+0639:             return False
    __pyx_r = 0;
    goto __pyx_L0;
 0640: 
+0641:         if not self._b_ptr[i]:
  __pyx_t_1 = ((!((__pyx_v_self->_b_ptr[__pyx_v_i]) != 0)) != 0);
  if (__pyx_t_1) {
/* … */
  }
+0642:             i = self.open(i)
    __pyx_v_i = __pyx_f_2bp_3_bp_2BP_open(__pyx_v_self, __pyx_v_i);
 0643: 
+0644:         return i <= j < self.close(i)
  __pyx_t_1 = (__pyx_v_i <= __pyx_v_j);
  if (__pyx_t_1) {
    __pyx_t_1 = (__pyx_v_j < __pyx_f_2bp_3_bp_2BP_close(__pyx_v_self, __pyx_v_i, 0));
  }
  __pyx_r = __pyx_t_1;
  goto __pyx_L0;
 0645: 
+0646:     cpdef SIZE_t subtree(self, SIZE_t i) nogil:
static PyObject *__pyx_pw_2bp_3_bp_2BP_63subtree(PyObject *__pyx_v_self, PyObject *__pyx_arg_i); /*proto*/
static __pyx_t_2bp_3_bp_SIZE_t __pyx_f_2bp_3_bp_2BP_subtree(struct __pyx_obj_2bp_3_bp_BP *__pyx_v_self, __pyx_t_2bp_3_bp_SIZE_t __pyx_v_i, CYTHON_UNUSED int __pyx_skip_dispatch) {
  __pyx_t_2bp_3_bp_SIZE_t __pyx_r;
/* … */
  /* function exit code */
  __pyx_L0:;
  return __pyx_r;
}

/* Python wrapper */
static PyObject *__pyx_pw_2bp_3_bp_2BP_63subtree(PyObject *__pyx_v_self, PyObject *__pyx_arg_i); /*proto*/
static char __pyx_doc_2bp_3_bp_2BP_62subtree[] = "The number of nodes in the subtree of i\n        \n        Parameters\n        ----------\n        i : int\n            The node to evaluate\n\n        Returns\n        -------\n        int\n            The number of nodes in the subtree of i\n        ";
static PyObject *__pyx_pw_2bp_3_bp_2BP_63subtree(PyObject *__pyx_v_self, PyObject *__pyx_arg_i) {
  __pyx_t_2bp_3_bp_SIZE_t __pyx_v_i;
  PyObject *__pyx_r = 0;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("subtree (wrapper)", 0);
  assert(__pyx_arg_i); {
    __pyx_v_i = __Pyx_PyInt_As_Py_intptr_t(__pyx_arg_i); if (unlikely((__pyx_v_i == ((npy_intp)-1)) && PyErr_Occurred())) __PYX_ERR(0, 646, __pyx_L3_error)
  }
  goto __pyx_L4_argument_unpacking_done;
  __pyx_L3_error:;
  __Pyx_AddTraceback("bp._bp.BP.subtree", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __Pyx_RefNannyFinishContext();
  return NULL;
  __pyx_L4_argument_unpacking_done:;
  __pyx_r = __pyx_pf_2bp_3_bp_2BP_62subtree(((struct __pyx_obj_2bp_3_bp_BP *)__pyx_v_self), ((__pyx_t_2bp_3_bp_SIZE_t)__pyx_v_i));
  int __pyx_lineno = 0;
  const char *__pyx_filename = NULL;
  int __pyx_clineno = 0;

  /* function exit code */
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}

static PyObject *__pyx_pf_2bp_3_bp_2BP_62subtree(struct __pyx_obj_2bp_3_bp_BP *__pyx_v_self, __pyx_t_2bp_3_bp_SIZE_t __pyx_v_i) {
  PyObject *__pyx_r = NULL;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("subtree", 0);
  __Pyx_XDECREF(__pyx_r);
  __pyx_t_1 = __Pyx_PyInt_From_Py_intptr_t(__pyx_f_2bp_3_bp_2BP_subtree(__pyx_v_self, __pyx_v_i, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 646, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_r = __pyx_t_1;
  __pyx_t_1 = 0;
  goto __pyx_L0;

  /* function exit code */
  __pyx_L1_error:;
  __Pyx_XDECREF(__pyx_t_1);
  __Pyx_AddTraceback("bp._bp.BP.subtree", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __pyx_r = NULL;
  __pyx_L0:;
  __Pyx_XGIVEREF(__pyx_r);
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}
 0647:         """The number of nodes in the subtree of i
 0648:         
 0649:         Parameters
 0650:         ----------
 0651:         i : int
 0652:             The node to evaluate
 0653: 
 0654:         Returns
 0655:         -------
 0656:         int
 0657:             The number of nodes in the subtree of i
 0658:         """
+0659:         if not self._b_ptr[i]:
  __pyx_t_1 = ((!((__pyx_v_self->_b_ptr[__pyx_v_i]) != 0)) != 0);
  if (__pyx_t_1) {
/* … */
  }
+0660:             i = self.open(i)
    __pyx_v_i = __pyx_f_2bp_3_bp_2BP_open(__pyx_v_self, __pyx_v_i);
 0661: 
+0662:         return (self.close(i) - i + 1) / 2
  __pyx_r = (((__pyx_f_2bp_3_bp_2BP_close(__pyx_v_self, __pyx_v_i, 0) - __pyx_v_i) + 1) / 2);
  goto __pyx_L0;
 0663: 
+0664:     cpdef SIZE_t levelancestor(self, SIZE_t i, SIZE_t d) nogil:
static PyObject *__pyx_pw_2bp_3_bp_2BP_65levelancestor(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
static __pyx_t_2bp_3_bp_SIZE_t __pyx_f_2bp_3_bp_2BP_levelancestor(struct __pyx_obj_2bp_3_bp_BP *__pyx_v_self, __pyx_t_2bp_3_bp_SIZE_t __pyx_v_i, __pyx_t_2bp_3_bp_SIZE_t __pyx_v_d, CYTHON_UNUSED int __pyx_skip_dispatch) {
  __pyx_t_2bp_3_bp_SIZE_t __pyx_r;
/* … */
  /* function exit code */
  __pyx_L0:;
  return __pyx_r;
}

/* Python wrapper */
static PyObject *__pyx_pw_2bp_3_bp_2BP_65levelancestor(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
static char __pyx_doc_2bp_3_bp_2BP_64levelancestor[] = "The ancestor j of i such that depth(j) = depth(i) \342\210\222 d\n        \n        Parameters\n        ----------\n        i : int\n            The node to evaluate\n\n        d : int\n            How many ancestors back to evaluate\n\n        Returns\n        -------\n        int\n            The node index of the ancestor to search for\n        ";
static PyObject *__pyx_pw_2bp_3_bp_2BP_65levelancestor(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
  __pyx_t_2bp_3_bp_SIZE_t __pyx_v_i;
  __pyx_t_2bp_3_bp_SIZE_t __pyx_v_d;
  PyObject *__pyx_r = 0;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("levelancestor (wrapper)", 0);
  {
    static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_i,&__pyx_n_s_d,0};
    PyObject* values[2] = {0,0};
    if (unlikely(__pyx_kwds)) {
      Py_ssize_t kw_args;
      const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args);
      switch (pos_args) {
        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
        CYTHON_FALLTHROUGH;
        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
        CYTHON_FALLTHROUGH;
        case  0: break;
        default: goto __pyx_L5_argtuple_error;
      }
      kw_args = PyDict_Size(__pyx_kwds);
      switch (pos_args) {
        case  0:
        if (likely((values[0] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_i)) != 0)) kw_args--;
        else goto __pyx_L5_argtuple_error;
        CYTHON_FALLTHROUGH;
        case  1:
        if (likely((values[1] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_d)) != 0)) kw_args--;
        else {
          __Pyx_RaiseArgtupleInvalid("levelancestor", 1, 2, 2, 1); __PYX_ERR(0, 664, __pyx_L3_error)
        }
      }
      if (unlikely(kw_args > 0)) {
        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "levelancestor") < 0)) __PYX_ERR(0, 664, __pyx_L3_error)
      }
    } else if (PyTuple_GET_SIZE(__pyx_args) != 2) {
      goto __pyx_L5_argtuple_error;
    } else {
      values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
      values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
    }
    __pyx_v_i = __Pyx_PyInt_As_Py_intptr_t(values[0]); if (unlikely((__pyx_v_i == ((npy_intp)-1)) && PyErr_Occurred())) __PYX_ERR(0, 664, __pyx_L3_error)
    __pyx_v_d = __Pyx_PyInt_As_Py_intptr_t(values[1]); if (unlikely((__pyx_v_d == ((npy_intp)-1)) && PyErr_Occurred())) __PYX_ERR(0, 664, __pyx_L3_error)
  }
  goto __pyx_L4_argument_unpacking_done;
  __pyx_L5_argtuple_error:;
  __Pyx_RaiseArgtupleInvalid("levelancestor", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 664, __pyx_L3_error)
  __pyx_L3_error:;
  __Pyx_AddTraceback("bp._bp.BP.levelancestor", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __Pyx_RefNannyFinishContext();
  return NULL;
  __pyx_L4_argument_unpacking_done:;
  __pyx_r = __pyx_pf_2bp_3_bp_2BP_64levelancestor(((struct __pyx_obj_2bp_3_bp_BP *)__pyx_v_self), __pyx_v_i, __pyx_v_d);
  int __pyx_lineno = 0;
  const char *__pyx_filename = NULL;
  int __pyx_clineno = 0;

  /* function exit code */
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}

static PyObject *__pyx_pf_2bp_3_bp_2BP_64levelancestor(struct __pyx_obj_2bp_3_bp_BP *__pyx_v_self, __pyx_t_2bp_3_bp_SIZE_t __pyx_v_i, __pyx_t_2bp_3_bp_SIZE_t __pyx_v_d) {
  PyObject *__pyx_r = NULL;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("levelancestor", 0);
  __Pyx_XDECREF(__pyx_r);
  __pyx_t_1 = __Pyx_PyInt_From_Py_intptr_t(__pyx_f_2bp_3_bp_2BP_levelancestor(__pyx_v_self, __pyx_v_i, __pyx_v_d, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 664, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_r = __pyx_t_1;
  __pyx_t_1 = 0;
  goto __pyx_L0;

  /* function exit code */
  __pyx_L1_error:;
  __Pyx_XDECREF(__pyx_t_1);
  __Pyx_AddTraceback("bp._bp.BP.levelancestor", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __pyx_r = NULL;
  __pyx_L0:;
  __Pyx_XGIVEREF(__pyx_r);
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}
 0665:         """The ancestor j of i such that depth(j) = depth(i) − d
 0666:         
 0667:         Parameters
 0668:         ----------
 0669:         i : int
 0670:             The node to evaluate
 0671: 
 0672:         d : int
 0673:             How many ancestors back to evaluate
 0674: 
 0675:         Returns
 0676:         -------
 0677:         int
 0678:             The node index of the ancestor to search for
 0679:         """
+0680:         if d <= 0:
  __pyx_t_1 = ((__pyx_v_d <= 0) != 0);
  if (__pyx_t_1) {
/* … */
  }
+0681:             return -1
    __pyx_r = -1;
    goto __pyx_L0;
 0682: 
+0683:         if not self._b_ptr[i]:
  __pyx_t_1 = ((!((__pyx_v_self->_b_ptr[__pyx_v_i]) != 0)) != 0);
  if (__pyx_t_1) {
/* … */
  }
+0684:             i = self.open(i)
    __pyx_v_i = __pyx_f_2bp_3_bp_2BP_open(__pyx_v_self, __pyx_v_i);
 0685: 
+0686:         return self.bwdsearch(i, -d - 1) + 1
  __pyx_r = (__pyx_f_2bp_3_bp_2BP_bwdsearch(__pyx_v_self, __pyx_v_i, ((-__pyx_v_d) - 1)) + 1);
  goto __pyx_L0;
 0687: 
+0688:     cpdef SIZE_t levelnext(self, SIZE_t i) nogil:
static PyObject *__pyx_pw_2bp_3_bp_2BP_67levelnext(PyObject *__pyx_v_self, PyObject *__pyx_arg_i); /*proto*/
static __pyx_t_2bp_3_bp_SIZE_t __pyx_f_2bp_3_bp_2BP_levelnext(struct __pyx_obj_2bp_3_bp_BP *__pyx_v_self, __pyx_t_2bp_3_bp_SIZE_t __pyx_v_i, CYTHON_UNUSED int __pyx_skip_dispatch) {
  __pyx_t_2bp_3_bp_SIZE_t __pyx_r;
/* … */
  /* function exit code */
  __pyx_L0:;
  return __pyx_r;
}

/* Python wrapper */
static PyObject *__pyx_pw_2bp_3_bp_2BP_67levelnext(PyObject *__pyx_v_self, PyObject *__pyx_arg_i); /*proto*/
static char __pyx_doc_2bp_3_bp_2BP_66levelnext[] = "The next node with the same depth\n        Parameters\n        ----------\n        i : int\n            The node to evaluate\n\n        Returns\n        -------\n        int\n            The node index of the next node or -1 if there isn't one\n        ";
static PyObject *__pyx_pw_2bp_3_bp_2BP_67levelnext(PyObject *__pyx_v_self, PyObject *__pyx_arg_i) {
  __pyx_t_2bp_3_bp_SIZE_t __pyx_v_i;
  PyObject *__pyx_r = 0;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("levelnext (wrapper)", 0);
  assert(__pyx_arg_i); {
    __pyx_v_i = __Pyx_PyInt_As_Py_intptr_t(__pyx_arg_i); if (unlikely((__pyx_v_i == ((npy_intp)-1)) && PyErr_Occurred())) __PYX_ERR(0, 688, __pyx_L3_error)
  }
  goto __pyx_L4_argument_unpacking_done;
  __pyx_L3_error:;
  __Pyx_AddTraceback("bp._bp.BP.levelnext", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __Pyx_RefNannyFinishContext();
  return NULL;
  __pyx_L4_argument_unpacking_done:;
  __pyx_r = __pyx_pf_2bp_3_bp_2BP_66levelnext(((struct __pyx_obj_2bp_3_bp_BP *)__pyx_v_self), ((__pyx_t_2bp_3_bp_SIZE_t)__pyx_v_i));
  int __pyx_lineno = 0;
  const char *__pyx_filename = NULL;
  int __pyx_clineno = 0;

  /* function exit code */
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}

static PyObject *__pyx_pf_2bp_3_bp_2BP_66levelnext(struct __pyx_obj_2bp_3_bp_BP *__pyx_v_self, __pyx_t_2bp_3_bp_SIZE_t __pyx_v_i) {
  PyObject *__pyx_r = NULL;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("levelnext", 0);
  __Pyx_XDECREF(__pyx_r);
  __pyx_t_1 = __Pyx_PyInt_From_Py_intptr_t(__pyx_f_2bp_3_bp_2BP_levelnext(__pyx_v_self, __pyx_v_i, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 688, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_r = __pyx_t_1;
  __pyx_t_1 = 0;
  goto __pyx_L0;

  /* function exit code */
  __pyx_L1_error:;
  __Pyx_XDECREF(__pyx_t_1);
  __Pyx_AddTraceback("bp._bp.BP.levelnext", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __pyx_r = NULL;
  __pyx_L0:;
  __Pyx_XGIVEREF(__pyx_r);
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}
 0689:         """The next node with the same depth
 0690:         Parameters
 0691:         ----------
 0692:         i : int
 0693:             The node to evaluate
 0694: 
 0695:         Returns
 0696:         -------
 0697:         int
 0698:             The node index of the next node or -1 if there isn't one
 0699:         """
+0700:         return self.fwdsearch(self.close(i), 1)
  __pyx_r = __pyx_f_2bp_3_bp_2BP_fwdsearch(__pyx_v_self, __pyx_f_2bp_3_bp_2BP_close(__pyx_v_self, __pyx_v_i, 0), 1);
  goto __pyx_L0;
 0701: 
+0702:     cpdef SIZE_t lca(self, SIZE_t i, SIZE_t j) nogil:
static PyObject *__pyx_pw_2bp_3_bp_2BP_69lca(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
static __pyx_t_2bp_3_bp_SIZE_t __pyx_f_2bp_3_bp_2BP_lca(struct __pyx_obj_2bp_3_bp_BP *__pyx_v_self, __pyx_t_2bp_3_bp_SIZE_t __pyx_v_i, __pyx_t_2bp_3_bp_SIZE_t __pyx_v_j, CYTHON_UNUSED int __pyx_skip_dispatch) {
  __pyx_t_2bp_3_bp_SIZE_t __pyx_r;
/* … */
  /* function exit code */
  __pyx_L0:;
  return __pyx_r;
}

/* Python wrapper */
static PyObject *__pyx_pw_2bp_3_bp_2BP_69lca(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
static char __pyx_doc_2bp_3_bp_2BP_68lca[] = "The lowest common ancestor of i and j\n\n        Parameters\n        ----------\n        i : int\n            A node index to evaluate\n        j : int\n            A node index to evalute\n\n        Returns\n        -------\n        int\n           The index of the lowest common ancestor\n        ";
static PyObject *__pyx_pw_2bp_3_bp_2BP_69lca(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
  __pyx_t_2bp_3_bp_SIZE_t __pyx_v_i;
  __pyx_t_2bp_3_bp_SIZE_t __pyx_v_j;
  PyObject *__pyx_r = 0;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("lca (wrapper)", 0);
  {
    static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_i,&__pyx_n_s_j,0};
    PyObject* values[2] = {0,0};
    if (unlikely(__pyx_kwds)) {
      Py_ssize_t kw_args;
      const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args);
      switch (pos_args) {
        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
        CYTHON_FALLTHROUGH;
        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
        CYTHON_FALLTHROUGH;
        case  0: break;
        default: goto __pyx_L5_argtuple_error;
      }
      kw_args = PyDict_Size(__pyx_kwds);
      switch (pos_args) {
        case  0:
        if (likely((values[0] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_i)) != 0)) kw_args--;
        else goto __pyx_L5_argtuple_error;
        CYTHON_FALLTHROUGH;
        case  1:
        if (likely((values[1] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_j)) != 0)) kw_args--;
        else {
          __Pyx_RaiseArgtupleInvalid("lca", 1, 2, 2, 1); __PYX_ERR(0, 702, __pyx_L3_error)
        }
      }
      if (unlikely(kw_args > 0)) {
        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "lca") < 0)) __PYX_ERR(0, 702, __pyx_L3_error)
      }
    } else if (PyTuple_GET_SIZE(__pyx_args) != 2) {
      goto __pyx_L5_argtuple_error;
    } else {
      values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
      values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
    }
    __pyx_v_i = __Pyx_PyInt_As_Py_intptr_t(values[0]); if (unlikely((__pyx_v_i == ((npy_intp)-1)) && PyErr_Occurred())) __PYX_ERR(0, 702, __pyx_L3_error)
    __pyx_v_j = __Pyx_PyInt_As_Py_intptr_t(values[1]); if (unlikely((__pyx_v_j == ((npy_intp)-1)) && PyErr_Occurred())) __PYX_ERR(0, 702, __pyx_L3_error)
  }
  goto __pyx_L4_argument_unpacking_done;
  __pyx_L5_argtuple_error:;
  __Pyx_RaiseArgtupleInvalid("lca", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 702, __pyx_L3_error)
  __pyx_L3_error:;
  __Pyx_AddTraceback("bp._bp.BP.lca", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __Pyx_RefNannyFinishContext();
  return NULL;
  __pyx_L4_argument_unpacking_done:;
  __pyx_r = __pyx_pf_2bp_3_bp_2BP_68lca(((struct __pyx_obj_2bp_3_bp_BP *)__pyx_v_self), __pyx_v_i, __pyx_v_j);
  int __pyx_lineno = 0;
  const char *__pyx_filename = NULL;
  int __pyx_clineno = 0;

  /* function exit code */
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}

static PyObject *__pyx_pf_2bp_3_bp_2BP_68lca(struct __pyx_obj_2bp_3_bp_BP *__pyx_v_self, __pyx_t_2bp_3_bp_SIZE_t __pyx_v_i, __pyx_t_2bp_3_bp_SIZE_t __pyx_v_j) {
  PyObject *__pyx_r = NULL;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("lca", 0);
  __Pyx_XDECREF(__pyx_r);
  __pyx_t_1 = __Pyx_PyInt_From_Py_intptr_t(__pyx_f_2bp_3_bp_2BP_lca(__pyx_v_self, __pyx_v_i, __pyx_v_j, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 702, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_r = __pyx_t_1;
  __pyx_t_1 = 0;
  goto __pyx_L0;

  /* function exit code */
  __pyx_L1_error:;
  __Pyx_XDECREF(__pyx_t_1);
  __Pyx_AddTraceback("bp._bp.BP.lca", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __pyx_r = NULL;
  __pyx_L0:;
  __Pyx_XGIVEREF(__pyx_r);
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}
 0703:         """The lowest common ancestor of i and j
 0704: 
 0705:         Parameters
 0706:         ----------
 0707:         i : int
 0708:             A node index to evaluate
 0709:         j : int
 0710:             A node index to evalute
 0711: 
 0712:         Returns
 0713:         -------
 0714:         int
 0715:            The index of the lowest common ancestor
 0716:         """
+0717:         if self.isancestor(i, j):
  __pyx_t_1 = (__pyx_f_2bp_3_bp_2BP_isancestor(__pyx_v_self, __pyx_v_i, __pyx_v_j, 0) != 0);
  if (__pyx_t_1) {
/* … */
  }
+0718:             return i
    __pyx_r = __pyx_v_i;
    goto __pyx_L0;
+0719:         elif self.isancestor(j, i):
  __pyx_t_1 = (__pyx_f_2bp_3_bp_2BP_isancestor(__pyx_v_self, __pyx_v_j, __pyx_v_i, 0) != 0);
  if (__pyx_t_1) {
/* … */
  }
+0720:             return j
    __pyx_r = __pyx_v_j;
    goto __pyx_L0;
 0721:         else:
+0722:             return self.parent(self.rmq(i, j) + 1)
  /*else*/ {
    __pyx_r = __pyx_f_2bp_3_bp_2BP_parent(__pyx_v_self, (__pyx_f_2bp_3_bp_2BP_rmq(__pyx_v_self, __pyx_v_i, __pyx_v_j, 0) + 1), 0);
    goto __pyx_L0;
  }
 0723: 
+0724:     cpdef SIZE_t deepestnode(self, SIZE_t i) nogil:
static PyObject *__pyx_pw_2bp_3_bp_2BP_71deepestnode(PyObject *__pyx_v_self, PyObject *__pyx_arg_i); /*proto*/
static __pyx_t_2bp_3_bp_SIZE_t __pyx_f_2bp_3_bp_2BP_deepestnode(struct __pyx_obj_2bp_3_bp_BP *__pyx_v_self, __pyx_t_2bp_3_bp_SIZE_t __pyx_v_i, CYTHON_UNUSED int __pyx_skip_dispatch) {
  __pyx_t_2bp_3_bp_SIZE_t __pyx_r;
/* … */
  /* function exit code */
  __pyx_L0:;
  return __pyx_r;
}

/* Python wrapper */
static PyObject *__pyx_pw_2bp_3_bp_2BP_71deepestnode(PyObject *__pyx_v_self, PyObject *__pyx_arg_i); /*proto*/
static char __pyx_doc_2bp_3_bp_2BP_70deepestnode[] = "The index of the deepestnode which descends from i\n\n        Parameters\n        ----------\n        i : int\n            The node to evaluate\n\n        Returns\n        -------\n        int\n            The index of the deepest node which descends from i\n        ";
static PyObject *__pyx_pw_2bp_3_bp_2BP_71deepestnode(PyObject *__pyx_v_self, PyObject *__pyx_arg_i) {
  __pyx_t_2bp_3_bp_SIZE_t __pyx_v_i;
  PyObject *__pyx_r = 0;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("deepestnode (wrapper)", 0);
  assert(__pyx_arg_i); {
    __pyx_v_i = __Pyx_PyInt_As_Py_intptr_t(__pyx_arg_i); if (unlikely((__pyx_v_i == ((npy_intp)-1)) && PyErr_Occurred())) __PYX_ERR(0, 724, __pyx_L3_error)
  }
  goto __pyx_L4_argument_unpacking_done;
  __pyx_L3_error:;
  __Pyx_AddTraceback("bp._bp.BP.deepestnode", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __Pyx_RefNannyFinishContext();
  return NULL;
  __pyx_L4_argument_unpacking_done:;
  __pyx_r = __pyx_pf_2bp_3_bp_2BP_70deepestnode(((struct __pyx_obj_2bp_3_bp_BP *)__pyx_v_self), ((__pyx_t_2bp_3_bp_SIZE_t)__pyx_v_i));
  int __pyx_lineno = 0;
  const char *__pyx_filename = NULL;
  int __pyx_clineno = 0;

  /* function exit code */
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}

static PyObject *__pyx_pf_2bp_3_bp_2BP_70deepestnode(struct __pyx_obj_2bp_3_bp_BP *__pyx_v_self, __pyx_t_2bp_3_bp_SIZE_t __pyx_v_i) {
  PyObject *__pyx_r = NULL;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("deepestnode", 0);
  __Pyx_XDECREF(__pyx_r);
  __pyx_t_1 = __Pyx_PyInt_From_Py_intptr_t(__pyx_f_2bp_3_bp_2BP_deepestnode(__pyx_v_self, __pyx_v_i, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 724, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_r = __pyx_t_1;
  __pyx_t_1 = 0;
  goto __pyx_L0;

  /* function exit code */
  __pyx_L1_error:;
  __Pyx_XDECREF(__pyx_t_1);
  __Pyx_AddTraceback("bp._bp.BP.deepestnode", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __pyx_r = NULL;
  __pyx_L0:;
  __Pyx_XGIVEREF(__pyx_r);
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}
 0725:         """The index of the deepestnode which descends from i
 0726: 
 0727:         Parameters
 0728:         ----------
 0729:         i : int
 0730:             The node to evaluate
 0731: 
 0732:         Returns
 0733:         -------
 0734:         int
 0735:             The index of the deepest node which descends from i
 0736:         """
+0737:         return self.rMq(self.open(i), self.close(i))
  __pyx_r = __pyx_f_2bp_3_bp_2BP_rMq(__pyx_v_self, __pyx_f_2bp_3_bp_2BP_open(__pyx_v_self, __pyx_v_i), __pyx_f_2bp_3_bp_2BP_close(__pyx_v_self, __pyx_v_i, 0), 0);
  goto __pyx_L0;
 0738: 
+0739:     cpdef SIZE_t height(self, SIZE_t i) nogil:
static PyObject *__pyx_pw_2bp_3_bp_2BP_73height(PyObject *__pyx_v_self, PyObject *__pyx_arg_i); /*proto*/
static __pyx_t_2bp_3_bp_SIZE_t __pyx_f_2bp_3_bp_2BP_height(struct __pyx_obj_2bp_3_bp_BP *__pyx_v_self, __pyx_t_2bp_3_bp_SIZE_t __pyx_v_i, CYTHON_UNUSED int __pyx_skip_dispatch) {
  __pyx_t_2bp_3_bp_SIZE_t __pyx_r;
/* … */
  /* function exit code */
  __pyx_L0:;
  return __pyx_r;
}

/* Python wrapper */
static PyObject *__pyx_pw_2bp_3_bp_2BP_73height(PyObject *__pyx_v_self, PyObject *__pyx_arg_i); /*proto*/
static char __pyx_doc_2bp_3_bp_2BP_72height[] = "The height of node i with respect to its deepest descendent\n\n        Parameters\n        ----------\n        i : int\n            The node to evaluate\n        \n        Notes\n        -----\n        Height is in terms of number of edges, not in terms of branch length\n        \n        Returns\n        -------\n        int\n            The number of edges between node i and its deepest node\n        ";
static PyObject *__pyx_pw_2bp_3_bp_2BP_73height(PyObject *__pyx_v_self, PyObject *__pyx_arg_i) {
  __pyx_t_2bp_3_bp_SIZE_t __pyx_v_i;
  PyObject *__pyx_r = 0;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("height (wrapper)", 0);
  assert(__pyx_arg_i); {
    __pyx_v_i = __Pyx_PyInt_As_Py_intptr_t(__pyx_arg_i); if (unlikely((__pyx_v_i == ((npy_intp)-1)) && PyErr_Occurred())) __PYX_ERR(0, 739, __pyx_L3_error)
  }
  goto __pyx_L4_argument_unpacking_done;
  __pyx_L3_error:;
  __Pyx_AddTraceback("bp._bp.BP.height", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __Pyx_RefNannyFinishContext();
  return NULL;
  __pyx_L4_argument_unpacking_done:;
  __pyx_r = __pyx_pf_2bp_3_bp_2BP_72height(((struct __pyx_obj_2bp_3_bp_BP *)__pyx_v_self), ((__pyx_t_2bp_3_bp_SIZE_t)__pyx_v_i));
  int __pyx_lineno = 0;
  const char *__pyx_filename = NULL;
  int __pyx_clineno = 0;

  /* function exit code */
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}

static PyObject *__pyx_pf_2bp_3_bp_2BP_72height(struct __pyx_obj_2bp_3_bp_BP *__pyx_v_self, __pyx_t_2bp_3_bp_SIZE_t __pyx_v_i) {
  PyObject *__pyx_r = NULL;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("height", 0);
  __Pyx_XDECREF(__pyx_r);
  __pyx_t_1 = __Pyx_PyInt_From_Py_intptr_t(__pyx_f_2bp_3_bp_2BP_height(__pyx_v_self, __pyx_v_i, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 739, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_r = __pyx_t_1;
  __pyx_t_1 = 0;
  goto __pyx_L0;

  /* function exit code */
  __pyx_L1_error:;
  __Pyx_XDECREF(__pyx_t_1);
  __Pyx_AddTraceback("bp._bp.BP.height", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __pyx_r = NULL;
  __pyx_L0:;
  __Pyx_XGIVEREF(__pyx_r);
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}
 0740:         """The height of node i with respect to its deepest descendent
 0741: 
 0742:         Parameters
 0743:         ----------
 0744:         i : int
 0745:             The node to evaluate
 0746:         
 0747:         Notes
 0748:         -----
 0749:         Height is in terms of number of edges, not in terms of branch length
 0750:         
 0751:         Returns
 0752:         -------
 0753:         int
 0754:             The number of edges between node i and its deepest node
 0755:         """
+0756:         return self.excess(self.deepestnode(i)) - self.excess(self.open(i))
  __pyx_r = (__pyx_f_2bp_3_bp_2BP_excess(__pyx_v_self, __pyx_f_2bp_3_bp_2BP_deepestnode(__pyx_v_self, __pyx_v_i, 0)) - __pyx_f_2bp_3_bp_2BP_excess(__pyx_v_self, __pyx_f_2bp_3_bp_2BP_open(__pyx_v_self, __pyx_v_i)));
  goto __pyx_L0;
 0757: 
+0758:     cpdef BP shear(self, set tips):
static PyObject *__pyx_pw_2bp_3_bp_2BP_75shear(PyObject *__pyx_v_self, PyObject *__pyx_v_tips); /*proto*/
static struct __pyx_obj_2bp_3_bp_BP *__pyx_f_2bp_3_bp_2BP_shear(struct __pyx_obj_2bp_3_bp_BP *__pyx_v_self, PyObject *__pyx_v_tips, CYTHON_UNUSED int __pyx_skip_dispatch) {
  __pyx_t_2bp_3_bp_SIZE_t __pyx_v_i;
  CYTHON_UNUSED __pyx_t_2bp_3_bp_SIZE_t __pyx_v_n;
  __pyx_t_2bp_3_bp_SIZE_t __pyx_v_p;
  __pyx_t_2bp_3_bp_SIZE_t __pyx_v_count;
  struct BIT_ARRAY *__pyx_v_mask;
  struct __pyx_obj_2bp_3_bp_BP *__pyx_v_new_bp = 0;
  struct __pyx_obj_2bp_3_bp_BP *__pyx_r = NULL;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("shear", 0);
/* … */
  /* function exit code */
  __pyx_L1_error:;
  __Pyx_XDECREF(__pyx_t_2);
  __Pyx_XDECREF(__pyx_t_9);
  __Pyx_AddTraceback("bp._bp.BP.shear", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __pyx_r = 0;
  __pyx_L0:;
  __Pyx_XDECREF((PyObject *)__pyx_v_new_bp);
  __Pyx_XGIVEREF((PyObject *)__pyx_r);
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}

/* Python wrapper */
static PyObject *__pyx_pw_2bp_3_bp_2BP_75shear(PyObject *__pyx_v_self, PyObject *__pyx_v_tips); /*proto*/
static char __pyx_doc_2bp_3_bp_2BP_74shear[] = "Remove all nodes from the tree except tips and ancestors of tips\n\n        Parameters\n        ----------\n        tips : set of str\n            The set of tip names to retain\n\n        Returns\n        -------\n        BP\n            A new BP tree corresponding to only the described tips and their\n            ancestors.\n        ";
static PyObject *__pyx_pw_2bp_3_bp_2BP_75shear(PyObject *__pyx_v_self, PyObject *__pyx_v_tips) {
  PyObject *__pyx_r = 0;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("shear (wrapper)", 0);
  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_tips), (&PySet_Type), 1, "tips", 1))) __PYX_ERR(0, 758, __pyx_L1_error)
  __pyx_r = __pyx_pf_2bp_3_bp_2BP_74shear(((struct __pyx_obj_2bp_3_bp_BP *)__pyx_v_self), ((PyObject*)__pyx_v_tips));
  int __pyx_lineno = 0;
  const char *__pyx_filename = NULL;
  int __pyx_clineno = 0;

  /* function exit code */
  goto __pyx_L0;
  __pyx_L1_error:;
  __pyx_r = NULL;
  __pyx_L0:;
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}

static PyObject *__pyx_pf_2bp_3_bp_2BP_74shear(struct __pyx_obj_2bp_3_bp_BP *__pyx_v_self, PyObject *__pyx_v_tips) {
  PyObject *__pyx_r = NULL;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("shear", 0);
  __Pyx_XDECREF(__pyx_r);
  __pyx_t_1 = ((PyObject *)__pyx_f_2bp_3_bp_2BP_shear(__pyx_v_self, __pyx_v_tips, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 758, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_r = __pyx_t_1;
  __pyx_t_1 = 0;
  goto __pyx_L0;

  /* function exit code */
  __pyx_L1_error:;
  __Pyx_XDECREF(__pyx_t_1);
  __Pyx_AddTraceback("bp._bp.BP.shear", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __pyx_r = NULL;
  __pyx_L0:;
  __Pyx_XGIVEREF(__pyx_r);
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}
 0759:         """Remove all nodes from the tree except tips and ancestors of tips
 0760: 
 0761:         Parameters
 0762:         ----------
 0763:         tips : set of str
 0764:             The set of tip names to retain
 0765: 
 0766:         Returns
 0767:         -------
 0768:         BP
 0769:             A new BP tree corresponding to only the described tips and their
 0770:             ancestors.
 0771:         """
 0772:         cdef:
+0773:             SIZE_t i, n = len(tips)
  if (unlikely(__pyx_v_tips == Py_None)) {
    PyErr_SetString(PyExc_TypeError, "object of type 'NoneType' has no len()");
    __PYX_ERR(0, 773, __pyx_L1_error)
  }
  __pyx_t_1 = PySet_GET_SIZE(__pyx_v_tips); if (unlikely(__pyx_t_1 == ((Py_ssize_t)-1))) __PYX_ERR(0, 773, __pyx_L1_error)
  __pyx_v_n = __pyx_t_1;
+0774:             SIZE_t p, t, count = 0
  __pyx_v_count = 0;
 0775:             BIT_ARRAY* mask
 0776:             BP new_bp
 0777: 
+0778:         mask = bit_array_create(self.B.size)
  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self->B), __pyx_n_s_size); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 778, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __pyx_t_3 = __Pyx_PyInt_As_uint64_t(__pyx_t_2); if (unlikely((__pyx_t_3 == ((bit_index_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 778, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __pyx_v_mask = bit_array_create(__pyx_t_3);
+0779:         bit_array_set_bit(mask, self.root())
  bit_array_set_bit(__pyx_v_mask, __pyx_f_2bp_3_bp_2BP_root(__pyx_v_self, 0));
+0780:         bit_array_set_bit(mask, self.close(self.root()))
  bit_array_set_bit(__pyx_v_mask, __pyx_f_2bp_3_bp_2BP_close(__pyx_v_self, __pyx_f_2bp_3_bp_2BP_root(__pyx_v_self, 0), 0));
 0781: 
+0782:         for i in range(self.B.size):
  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self->B), __pyx_n_s_size); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 782, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __pyx_t_4 = __Pyx_PyInt_As_long(__pyx_t_2); if (unlikely((__pyx_t_4 == (long)-1) && PyErr_Occurred())) __PYX_ERR(0, 782, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __pyx_t_5 = __pyx_t_4;
  for (__pyx_t_6 = 0; __pyx_t_6 < __pyx_t_5; __pyx_t_6+=1) {
    __pyx_v_i = __pyx_t_6;
 0783:             # isleaf is only defined on the open parenthesis
+0784:             if self.isleaf(i):
    __pyx_t_7 = (__pyx_f_2bp_3_bp_2BP_isleaf(__pyx_v_self, __pyx_v_i, 0) != 0);
    if (__pyx_t_7) {
/* … */
    }
  }
+0785:                 if self.name(i) in tips:  # gil is required for set operation
      __pyx_t_2 = __pyx_f_2bp_3_bp_2BP_name(__pyx_v_self, __pyx_v_i, 0); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 785, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_2);
      if (unlikely(__pyx_v_tips == Py_None)) {
        PyErr_SetString(PyExc_TypeError, "'NoneType' object is not iterable");
        __PYX_ERR(0, 785, __pyx_L1_error)
      }
      __pyx_t_7 = (__Pyx_PySet_ContainsTF(__pyx_t_2, __pyx_v_tips, Py_EQ)); if (unlikely(__pyx_t_7 < 0)) __PYX_ERR(0, 785, __pyx_L1_error)
      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
      __pyx_t_8 = (__pyx_t_7 != 0);
      if (__pyx_t_8) {
/* … */
      }
+0786:                     with nogil:
        {
            #ifdef WITH_THREAD
            PyThreadState *_save;
            Py_UNBLOCK_THREADS
            __Pyx_FastGIL_Remember();
            #endif
            /*try:*/ {
/* … */
            /*finally:*/ {
              /*normal exit:*/{
                #ifdef WITH_THREAD
                __Pyx_FastGIL_Forget();
                Py_BLOCK_THREADS
                #endif
                goto __pyx_L11;
              }
              __pyx_L11:;
            }
        }
+0787:                         count += 1
              __pyx_v_count = (__pyx_v_count + 1);
+0788:                         bit_array_set_bit(mask, i)
              bit_array_set_bit(__pyx_v_mask, __pyx_v_i);
+0789:                         bit_array_set_bit(mask, i + 1)
              bit_array_set_bit(__pyx_v_mask, (__pyx_v_i + 1));
 0790: 
+0791:                         p = self.parent(i)
              __pyx_v_p = __pyx_f_2bp_3_bp_2BP_parent(__pyx_v_self, __pyx_v_i, 0);
+0792:                         while p != 0 and bit_array_get_bit(mask, p) == 0:
              while (1) {
                __pyx_t_7 = ((__pyx_v_p != 0) != 0);
                if (__pyx_t_7) {
                } else {
                  __pyx_t_8 = __pyx_t_7;
                  goto __pyx_L14_bool_binop_done;
                }
                __pyx_t_7 = ((bit_array_get_bit(__pyx_v_mask, __pyx_v_p) == 0) != 0);
                __pyx_t_8 = __pyx_t_7;
                __pyx_L14_bool_binop_done:;
                if (!__pyx_t_8) break;
+0793:                             bit_array_set_bit(mask, p)
                bit_array_set_bit(__pyx_v_mask, __pyx_v_p);
+0794:                             bit_array_set_bit(mask, self.close(p))
                bit_array_set_bit(__pyx_v_mask, __pyx_f_2bp_3_bp_2BP_close(__pyx_v_self, __pyx_v_p, 0));
 0795: 
+0796:                             p = self.parent(p)
                __pyx_v_p = __pyx_f_2bp_3_bp_2BP_parent(__pyx_v_self, __pyx_v_p, 0);
              }
            }
 0797: 
+0798:         if count == 0:
  __pyx_t_8 = ((__pyx_v_count == 0) != 0);
  if (unlikely(__pyx_t_8)) {
/* … */
  }
+0799:             bit_array_free(mask)
    bit_array_free(__pyx_v_mask);
+0800:             raise ValueError("No requested tips found")
    __pyx_t_2 = __Pyx_PyObject_Call(__pyx_builtin_ValueError, __pyx_tuple__3, NULL); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 800, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __Pyx_Raise(__pyx_t_2, 0, 0, 0);
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    __PYX_ERR(0, 800, __pyx_L1_error)
/* … */
  __pyx_tuple__3 = PyTuple_Pack(1, __pyx_kp_s_No_requested_tips_found); if (unlikely(!__pyx_tuple__3)) __PYX_ERR(0, 800, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_tuple__3);
  __Pyx_GIVEREF(__pyx_tuple__3);
 0801: 
+0802:         new_bp = self._mask_from_self(mask, self._lengths)
  __pyx_t_2 = ((PyObject *)__pyx_v_self->_lengths);
  __Pyx_INCREF(__pyx_t_2);
  __pyx_t_9 = ((PyObject *)__pyx_f_2bp_3_bp_2BP__mask_from_self(__pyx_v_self, __pyx_v_mask, ((PyArrayObject *)__pyx_t_2))); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 802, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_9);
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __pyx_v_new_bp = ((struct __pyx_obj_2bp_3_bp_BP *)__pyx_t_9);
  __pyx_t_9 = 0;
+0803:         bit_array_free(mask)
  bit_array_free(__pyx_v_mask);
+0804:         return new_bp
  __Pyx_XDECREF(((PyObject *)__pyx_r));
  __Pyx_INCREF(((PyObject *)__pyx_v_new_bp));
  __pyx_r = __pyx_v_new_bp;
  goto __pyx_L0;
 0805: 
+0806:     cdef BP _mask_from_self(self, BIT_ARRAY* mask,
static struct __pyx_obj_2bp_3_bp_BP *__pyx_f_2bp_3_bp_2BP__mask_from_self(struct __pyx_obj_2bp_3_bp_BP *__pyx_v_self, struct BIT_ARRAY *__pyx_v_mask, PyArrayObject *__pyx_v_lengths) {
  __pyx_t_2bp_3_bp_SIZE_t __pyx_v_i;
  __pyx_t_2bp_3_bp_SIZE_t __pyx_v_k;
  __pyx_t_2bp_3_bp_SIZE_t __pyx_v_n;
  __pyx_t_2bp_3_bp_SIZE_t __pyx_v_mask_sum;
  PyArrayObject *__pyx_v_new_b = 0;
  PyArrayObject *__pyx_v_new_names = 0;
  PyArrayObject *__pyx_v_names = 0;
  PyArrayObject *__pyx_v_new_lengths = 0;
  __pyx_t_2bp_3_bp_BOOL_t *__pyx_v_new_b_ptr;
  __pyx_t_2bp_3_bp_DOUBLE_t *__pyx_v_lengths_ptr;
  __pyx_t_2bp_3_bp_DOUBLE_t *__pyx_v_new_lengths_ptr;
  __Pyx_LocalBuf_ND __pyx_pybuffernd_lengths;
  __Pyx_Buffer __pyx_pybuffer_lengths;
  __Pyx_LocalBuf_ND __pyx_pybuffernd_names;
  __Pyx_Buffer __pyx_pybuffer_names;
  __Pyx_LocalBuf_ND __pyx_pybuffernd_new_b;
  __Pyx_Buffer __pyx_pybuffer_new_b;
  __Pyx_LocalBuf_ND __pyx_pybuffernd_new_lengths;
  __Pyx_Buffer __pyx_pybuffer_new_lengths;
  __Pyx_LocalBuf_ND __pyx_pybuffernd_new_names;
  __Pyx_Buffer __pyx_pybuffer_new_names;
  struct __pyx_obj_2bp_3_bp_BP *__pyx_r = NULL;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("_mask_from_self", 0);
  __pyx_pybuffer_new_b.pybuffer.buf = NULL;
  __pyx_pybuffer_new_b.refcount = 0;
  __pyx_pybuffernd_new_b.data = NULL;
  __pyx_pybuffernd_new_b.rcbuffer = &__pyx_pybuffer_new_b;
  __pyx_pybuffer_new_names.pybuffer.buf = NULL;
  __pyx_pybuffer_new_names.refcount = 0;
  __pyx_pybuffernd_new_names.data = NULL;
  __pyx_pybuffernd_new_names.rcbuffer = &__pyx_pybuffer_new_names;
  __pyx_pybuffer_names.pybuffer.buf = NULL;
  __pyx_pybuffer_names.refcount = 0;
  __pyx_pybuffernd_names.data = NULL;
  __pyx_pybuffernd_names.rcbuffer = &__pyx_pybuffer_names;
  __pyx_pybuffer_new_lengths.pybuffer.buf = NULL;
  __pyx_pybuffer_new_lengths.refcount = 0;
  __pyx_pybuffernd_new_lengths.data = NULL;
  __pyx_pybuffernd_new_lengths.rcbuffer = &__pyx_pybuffer_new_lengths;
  __pyx_pybuffer_lengths.pybuffer.buf = NULL;
  __pyx_pybuffer_lengths.refcount = 0;
  __pyx_pybuffernd_lengths.data = NULL;
  __pyx_pybuffernd_lengths.rcbuffer = &__pyx_pybuffer_lengths;
  {
    __Pyx_BufFmt_StackElem __pyx_stack[1];
    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_lengths.rcbuffer->pybuffer, (PyObject*)__pyx_v_lengths, &__Pyx_TypeInfo_nn___pyx_t_2bp_3_bp_DOUBLE_t, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) __PYX_ERR(0, 806, __pyx_L1_error)
  }
  __pyx_pybuffernd_lengths.diminfo[0].strides = __pyx_pybuffernd_lengths.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_lengths.diminfo[0].shape = __pyx_pybuffernd_lengths.rcbuffer->pybuffer.shape[0];
/* … */
  /* function exit code */
  __pyx_L1_error:;
  __Pyx_XDECREF(__pyx_t_1);
  __Pyx_XDECREF(__pyx_t_3);
  __Pyx_XDECREF(__pyx_t_4);
  __Pyx_XDECREF(__pyx_t_5);
  { PyObject *__pyx_type, *__pyx_value, *__pyx_tb;
    __Pyx_PyThreadState_declare
    __Pyx_PyThreadState_assign
    __Pyx_ErrFetch(&__pyx_type, &__pyx_value, &__pyx_tb);
    __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_lengths.rcbuffer->pybuffer);
    __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_names.rcbuffer->pybuffer);
    __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_new_b.rcbuffer->pybuffer);
    __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_new_lengths.rcbuffer->pybuffer);
    __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_new_names.rcbuffer->pybuffer);
  __Pyx_ErrRestore(__pyx_type, __pyx_value, __pyx_tb);}
  __Pyx_AddTraceback("bp._bp.BP._mask_from_self", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __pyx_r = 0;
  goto __pyx_L2;
  __pyx_L0:;
  __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_lengths.rcbuffer->pybuffer);
  __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_names.rcbuffer->pybuffer);
  __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_new_b.rcbuffer->pybuffer);
  __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_new_lengths.rcbuffer->pybuffer);
  __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_new_names.rcbuffer->pybuffer);
  __pyx_L2:;
  __Pyx_XDECREF((PyObject *)__pyx_v_new_b);
  __Pyx_XDECREF((PyObject *)__pyx_v_new_names);
  __Pyx_XDECREF((PyObject *)__pyx_v_names);
  __Pyx_XDECREF((PyObject *)__pyx_v_new_lengths);
  __Pyx_XGIVEREF((PyObject *)__pyx_r);
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}
 0807:                             np.ndarray[DOUBLE_t, ndim=1] lengths):
 0808:         cdef:
 0809:             SIZE_t i, k, n, mask_sum
 0810:             np.ndarray[BOOL_t, ndim=1] new_b
 0811:             np.ndarray[object, ndim=1] new_names
+0812:             np.ndarray[object, ndim=1] names = self._names
  __pyx_t_1 = ((PyObject *)__pyx_v_self->_names);
  __Pyx_INCREF(__pyx_t_1);
  {
    __Pyx_BufFmt_StackElem __pyx_stack[1];
    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_names.rcbuffer->pybuffer, (PyObject*)((PyArrayObject *)__pyx_t_1), &__Pyx_TypeInfo_object, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {
      __pyx_v_names = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_pybuffernd_names.rcbuffer->pybuffer.buf = NULL;
      __PYX_ERR(0, 812, __pyx_L1_error)
    } else {__pyx_pybuffernd_names.diminfo[0].strides = __pyx_pybuffernd_names.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_names.diminfo[0].shape = __pyx_pybuffernd_names.rcbuffer->pybuffer.shape[0];
    }
  }
  __pyx_v_names = ((PyArrayObject *)__pyx_t_1);
  __pyx_t_1 = 0;
 0813:             np.ndarray[DOUBLE_t, ndim=1] new_lengths
 0814:             BOOL_t* new_b_ptr
 0815:             DOUBLE_t* lengths_ptr
 0816:             DOUBLE_t* new_lengths_ptr
 0817: 
+0818:         n = bit_array_length(mask)
  __pyx_v_n = bit_array_length(__pyx_v_mask);
+0819:         mask_sum = bit_array_num_bits_set(mask)
  __pyx_v_mask_sum = bit_array_num_bits_set(__pyx_v_mask);
 0820: 
+0821:         k = 0
  __pyx_v_k = 0;
 0822: 
+0823:         lengths_ptr = &lengths[0]
  __pyx_t_2 = 0;
  __pyx_v_lengths_ptr = (&(*__Pyx_BufPtrStrided1d(__pyx_t_2bp_3_bp_DOUBLE_t *, __pyx_pybuffernd_lengths.rcbuffer->pybuffer.buf, __pyx_t_2, __pyx_pybuffernd_lengths.diminfo[0].strides)));
 0824: 
+0825:         new_b = np.empty(mask_sum, dtype=BOOL)
  __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_np); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 825, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_empty); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 825, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_t_1 = __Pyx_PyInt_From_Py_intptr_t(__pyx_v_mask_sum); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 825, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_4 = PyTuple_New(1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 825, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  __Pyx_GIVEREF(__pyx_t_1);
  PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_1);
  __pyx_t_1 = 0;
  __pyx_t_1 = __Pyx_PyDict_NewPresized(1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 825, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __Pyx_GetModuleGlobalName(__pyx_t_5, __pyx_n_s_BOOL); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 825, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_5);
  if (PyDict_SetItem(__pyx_t_1, __pyx_n_s_dtype, __pyx_t_5) < 0) __PYX_ERR(0, 825, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
  __pyx_t_5 = __Pyx_PyObject_Call(__pyx_t_3, __pyx_t_4, __pyx_t_1); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 825, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_5);
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  if (!(likely(((__pyx_t_5) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_5, __pyx_ptype_5numpy_ndarray))))) __PYX_ERR(0, 825, __pyx_L1_error)
  __pyx_t_6 = ((PyArrayObject *)__pyx_t_5);
  {
    __Pyx_BufFmt_StackElem __pyx_stack[1];
    __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_new_b.rcbuffer->pybuffer);
    __pyx_t_7 = __Pyx_GetBufferAndValidate(&__pyx_pybuffernd_new_b.rcbuffer->pybuffer, (PyObject*)__pyx_t_6, &__Pyx_TypeInfo_nn___pyx_t_2bp_3_bp_BOOL_t, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack);
    if (unlikely(__pyx_t_7 < 0)) {
      PyErr_Fetch(&__pyx_t_8, &__pyx_t_9, &__pyx_t_10);
      if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_new_b.rcbuffer->pybuffer, (PyObject*)__pyx_v_new_b, &__Pyx_TypeInfo_nn___pyx_t_2bp_3_bp_BOOL_t, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {
        Py_XDECREF(__pyx_t_8); Py_XDECREF(__pyx_t_9); Py_XDECREF(__pyx_t_10);
        __Pyx_RaiseBufferFallbackError();
      } else {
        PyErr_Restore(__pyx_t_8, __pyx_t_9, __pyx_t_10);
      }
      __pyx_t_8 = __pyx_t_9 = __pyx_t_10 = 0;
    }
    __pyx_pybuffernd_new_b.diminfo[0].strides = __pyx_pybuffernd_new_b.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_new_b.diminfo[0].shape = __pyx_pybuffernd_new_b.rcbuffer->pybuffer.shape[0];
    if (unlikely(__pyx_t_7 < 0)) __PYX_ERR(0, 825, __pyx_L1_error)
  }
  __pyx_t_6 = 0;
  __pyx_v_new_b = ((PyArrayObject *)__pyx_t_5);
  __pyx_t_5 = 0;
+0826:         new_names = np.empty(mask_sum, dtype=object)
  __Pyx_GetModuleGlobalName(__pyx_t_5, __pyx_n_s_np); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 826, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_5);
  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_5, __pyx_n_s_empty); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 826, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
  __pyx_t_5 = __Pyx_PyInt_From_Py_intptr_t(__pyx_v_mask_sum); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 826, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_5);
  __pyx_t_4 = PyTuple_New(1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 826, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  __Pyx_GIVEREF(__pyx_t_5);
  PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_5);
  __pyx_t_5 = 0;
  __pyx_t_5 = __Pyx_PyDict_NewPresized(1); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 826, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_5);
  if (PyDict_SetItem(__pyx_t_5, __pyx_n_s_dtype, __pyx_builtin_object) < 0) __PYX_ERR(0, 826, __pyx_L1_error)
  __pyx_t_3 = __Pyx_PyObject_Call(__pyx_t_1, __pyx_t_4, __pyx_t_5); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 826, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
  if (!(likely(((__pyx_t_3) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_3, __pyx_ptype_5numpy_ndarray))))) __PYX_ERR(0, 826, __pyx_L1_error)
  __pyx_t_11 = ((PyArrayObject *)__pyx_t_3);
  {
    __Pyx_BufFmt_StackElem __pyx_stack[1];
    __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_new_names.rcbuffer->pybuffer);
    __pyx_t_7 = __Pyx_GetBufferAndValidate(&__pyx_pybuffernd_new_names.rcbuffer->pybuffer, (PyObject*)__pyx_t_11, &__Pyx_TypeInfo_object, PyBUF_FORMAT| PyBUF_STRIDES| PyBUF_WRITABLE, 1, 0, __pyx_stack);
    if (unlikely(__pyx_t_7 < 0)) {
      PyErr_Fetch(&__pyx_t_10, &__pyx_t_9, &__pyx_t_8);
      if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_new_names.rcbuffer->pybuffer, (PyObject*)__pyx_v_new_names, &__Pyx_TypeInfo_object, PyBUF_FORMAT| PyBUF_STRIDES| PyBUF_WRITABLE, 1, 0, __pyx_stack) == -1)) {
        Py_XDECREF(__pyx_t_10); Py_XDECREF(__pyx_t_9); Py_XDECREF(__pyx_t_8);
        __Pyx_RaiseBufferFallbackError();
      } else {
        PyErr_Restore(__pyx_t_10, __pyx_t_9, __pyx_t_8);
      }
      __pyx_t_10 = __pyx_t_9 = __pyx_t_8 = 0;
    }
    __pyx_pybuffernd_new_names.diminfo[0].strides = __pyx_pybuffernd_new_names.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_new_names.diminfo[0].shape = __pyx_pybuffernd_new_names.rcbuffer->pybuffer.shape[0];
    if (unlikely(__pyx_t_7 < 0)) __PYX_ERR(0, 826, __pyx_L1_error)
  }
  __pyx_t_11 = 0;
  __pyx_v_new_names = ((PyArrayObject *)__pyx_t_3);
  __pyx_t_3 = 0;
+0827:         new_lengths = np.empty(mask_sum, dtype=DOUBLE)
  __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_n_s_np); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 827, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __pyx_t_5 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_n_s_empty); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 827, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_5);
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  __pyx_t_3 = __Pyx_PyInt_From_Py_intptr_t(__pyx_v_mask_sum); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 827, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __pyx_t_4 = PyTuple_New(1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 827, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  __Pyx_GIVEREF(__pyx_t_3);
  PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_3);
  __pyx_t_3 = 0;
  __pyx_t_3 = __Pyx_PyDict_NewPresized(1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 827, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_DOUBLE); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 827, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  if (PyDict_SetItem(__pyx_t_3, __pyx_n_s_dtype, __pyx_t_1) < 0) __PYX_ERR(0, 827, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_t_1 = __Pyx_PyObject_Call(__pyx_t_5, __pyx_t_4, __pyx_t_3); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 827, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  if (!(likely(((__pyx_t_1) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_1, __pyx_ptype_5numpy_ndarray))))) __PYX_ERR(0, 827, __pyx_L1_error)
  __pyx_t_12 = ((PyArrayObject *)__pyx_t_1);
  {
    __Pyx_BufFmt_StackElem __pyx_stack[1];
    __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_new_lengths.rcbuffer->pybuffer);
    __pyx_t_7 = __Pyx_GetBufferAndValidate(&__pyx_pybuffernd_new_lengths.rcbuffer->pybuffer, (PyObject*)__pyx_t_12, &__Pyx_TypeInfo_nn___pyx_t_2bp_3_bp_DOUBLE_t, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack);
    if (unlikely(__pyx_t_7 < 0)) {
      PyErr_Fetch(&__pyx_t_8, &__pyx_t_9, &__pyx_t_10);
      if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_new_lengths.rcbuffer->pybuffer, (PyObject*)__pyx_v_new_lengths, &__Pyx_TypeInfo_nn___pyx_t_2bp_3_bp_DOUBLE_t, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {
        Py_XDECREF(__pyx_t_8); Py_XDECREF(__pyx_t_9); Py_XDECREF(__pyx_t_10);
        __Pyx_RaiseBufferFallbackError();
      } else {
        PyErr_Restore(__pyx_t_8, __pyx_t_9, __pyx_t_10);
      }
      __pyx_t_8 = __pyx_t_9 = __pyx_t_10 = 0;
    }
    __pyx_pybuffernd_new_lengths.diminfo[0].strides = __pyx_pybuffernd_new_lengths.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_new_lengths.diminfo[0].shape = __pyx_pybuffernd_new_lengths.rcbuffer->pybuffer.shape[0];
    if (unlikely(__pyx_t_7 < 0)) __PYX_ERR(0, 827, __pyx_L1_error)
  }
  __pyx_t_12 = 0;
  __pyx_v_new_lengths = ((PyArrayObject *)__pyx_t_1);
  __pyx_t_1 = 0;
 0828: 
+0829:         new_b_ptr = &new_b[0]
  __pyx_t_2 = 0;
  __pyx_v_new_b_ptr = (&(*__Pyx_BufPtrStrided1d(__pyx_t_2bp_3_bp_BOOL_t *, __pyx_pybuffernd_new_b.rcbuffer->pybuffer.buf, __pyx_t_2, __pyx_pybuffernd_new_b.diminfo[0].strides)));
+0830:         new_lengths_ptr = &new_lengths[0]
  __pyx_t_2 = 0;
  __pyx_v_new_lengths_ptr = (&(*__Pyx_BufPtrStrided1d(__pyx_t_2bp_3_bp_DOUBLE_t *, __pyx_pybuffernd_new_lengths.rcbuffer->pybuffer.buf, __pyx_t_2, __pyx_pybuffernd_new_lengths.diminfo[0].strides)));
 0831: 
+0832:         for i in range(n):
  __pyx_t_13 = __pyx_v_n;
  __pyx_t_14 = __pyx_t_13;
  for (__pyx_t_15 = 0; __pyx_t_15 < __pyx_t_14; __pyx_t_15+=1) {
    __pyx_v_i = __pyx_t_15;
+0833:             if bit_array_get_bit(mask, i):
    __pyx_t_16 = (bit_array_get_bit(__pyx_v_mask, __pyx_v_i) != 0);
    if (__pyx_t_16) {
/* … */
    }
  }
+0834:                 new_b_ptr[k] = self._b_ptr[i]
      (__pyx_v_new_b_ptr[__pyx_v_k]) = (__pyx_v_self->_b_ptr[__pyx_v_i]);
 0835: 
 0836:                 # since names is dtype=object, gil is required
+0837:                 new_names[k] = names[i]
      __pyx_t_2 = __pyx_v_i;
      __pyx_t_1 = (PyObject *) *__Pyx_BufPtrStrided1d(PyObject **, __pyx_pybuffernd_names.rcbuffer->pybuffer.buf, __pyx_t_2, __pyx_pybuffernd_names.diminfo[0].strides);
      if (unlikely(__pyx_t_1 == NULL)) __pyx_t_1 = Py_None;
      __Pyx_INCREF((PyObject*)__pyx_t_1);
      __pyx_t_2 = __pyx_v_k;
      __pyx_t_17 = __Pyx_BufPtrStrided1d(PyObject **, __pyx_pybuffernd_new_names.rcbuffer->pybuffer.buf, __pyx_t_2, __pyx_pybuffernd_new_names.diminfo[0].strides);
      __Pyx_XGOTREF(*__pyx_t_17);
      __Pyx_INCREF(__pyx_t_1); __Pyx_XDECREF(*__pyx_t_17);
      *__pyx_t_17 = __pyx_t_1;
      __Pyx_XGIVEREF(*__pyx_t_17);
      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+0838:                 new_lengths_ptr[k] = lengths_ptr[i]
      (__pyx_v_new_lengths_ptr[__pyx_v_k]) = (__pyx_v_lengths_ptr[__pyx_v_i]);
+0839:                 k += 1
      __pyx_v_k = (__pyx_v_k + 1);
 0840: 
+0841:         return BP(np.asarray(new_b), names=new_names, lengths=new_lengths)
  __Pyx_XDECREF(((PyObject *)__pyx_r));
  __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_n_s_np); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 841, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_n_s_asarray); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 841, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  __pyx_t_3 = NULL;
  if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_4))) {
    __pyx_t_3 = PyMethod_GET_SELF(__pyx_t_4);
    if (likely(__pyx_t_3)) {
      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_4);
      __Pyx_INCREF(__pyx_t_3);
      __Pyx_INCREF(function);
      __Pyx_DECREF_SET(__pyx_t_4, function);
    }
  }
  __pyx_t_1 = (__pyx_t_3) ? __Pyx_PyObject_Call2Args(__pyx_t_4, __pyx_t_3, ((PyObject *)__pyx_v_new_b)) : __Pyx_PyObject_CallOneArg(__pyx_t_4, ((PyObject *)__pyx_v_new_b));
  __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0;
  if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 841, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
  __pyx_t_4 = PyTuple_New(1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 841, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  __Pyx_GIVEREF(__pyx_t_1);
  PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_1);
  __pyx_t_1 = 0;
  __pyx_t_1 = __Pyx_PyDict_NewPresized(2); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 841, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  if (PyDict_SetItem(__pyx_t_1, __pyx_n_s_names, ((PyObject *)__pyx_v_new_names)) < 0) __PYX_ERR(0, 841, __pyx_L1_error)
  if (PyDict_SetItem(__pyx_t_1, __pyx_n_s_lengths, ((PyObject *)__pyx_v_new_lengths)) < 0) __PYX_ERR(0, 841, __pyx_L1_error)
  __pyx_t_3 = __Pyx_PyObject_Call(((PyObject *)__pyx_ptype_2bp_3_bp_BP), __pyx_t_4, __pyx_t_1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 841, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_r = ((struct __pyx_obj_2bp_3_bp_BP *)__pyx_t_3);
  __pyx_t_3 = 0;
  goto __pyx_L0;
 0842: 
+0843:     cpdef BP collapse(self):
static PyObject *__pyx_pw_2bp_3_bp_2BP_77collapse(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused); /*proto*/
static struct __pyx_obj_2bp_3_bp_BP *__pyx_f_2bp_3_bp_2BP_collapse(struct __pyx_obj_2bp_3_bp_BP *__pyx_v_self, CYTHON_UNUSED int __pyx_skip_dispatch) {
  __pyx_t_2bp_3_bp_SIZE_t __pyx_v_i;
  __pyx_t_2bp_3_bp_SIZE_t __pyx_v_n;
  __pyx_t_2bp_3_bp_SIZE_t __pyx_v_current;
  __pyx_t_2bp_3_bp_SIZE_t __pyx_v_first;
  __pyx_t_2bp_3_bp_SIZE_t __pyx_v_last;
  PyArrayObject *__pyx_v_new_lengths = 0;
  struct BIT_ARRAY *__pyx_v_mask;
  __pyx_t_2bp_3_bp_DOUBLE_t *__pyx_v_new_lengths_ptr;
  struct __pyx_obj_2bp_3_bp_BP *__pyx_v_new_bp = 0;
  __Pyx_LocalBuf_ND __pyx_pybuffernd_new_lengths;
  __Pyx_Buffer __pyx_pybuffer_new_lengths;
  struct __pyx_obj_2bp_3_bp_BP *__pyx_r = NULL;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("collapse", 0);
  __pyx_pybuffer_new_lengths.pybuffer.buf = NULL;
  __pyx_pybuffer_new_lengths.refcount = 0;
  __pyx_pybuffernd_new_lengths.data = NULL;
  __pyx_pybuffernd_new_lengths.rcbuffer = &__pyx_pybuffer_new_lengths;
/* … */
  /* function exit code */
  __pyx_L1_error:;
  __Pyx_XDECREF(__pyx_t_1);
  __Pyx_XDECREF(__pyx_t_2);
  __Pyx_XDECREF(__pyx_t_3);
  { PyObject *__pyx_type, *__pyx_value, *__pyx_tb;
    __Pyx_PyThreadState_declare
    __Pyx_PyThreadState_assign
    __Pyx_ErrFetch(&__pyx_type, &__pyx_value, &__pyx_tb);
    __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_new_lengths.rcbuffer->pybuffer);
  __Pyx_ErrRestore(__pyx_type, __pyx_value, __pyx_tb);}
  __Pyx_AddTraceback("bp._bp.BP.collapse", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __pyx_r = 0;
  goto __pyx_L2;
  __pyx_L0:;
  __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_new_lengths.rcbuffer->pybuffer);
  __pyx_L2:;
  __Pyx_XDECREF((PyObject *)__pyx_v_new_lengths);
  __Pyx_XDECREF((PyObject *)__pyx_v_new_bp);
  __Pyx_XGIVEREF((PyObject *)__pyx_r);
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}

/* Python wrapper */
static PyObject *__pyx_pw_2bp_3_bp_2BP_77collapse(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused); /*proto*/
static PyObject *__pyx_pw_2bp_3_bp_2BP_77collapse(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused) {
  PyObject *__pyx_r = 0;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("collapse (wrapper)", 0);
  __pyx_r = __pyx_pf_2bp_3_bp_2BP_76collapse(((struct __pyx_obj_2bp_3_bp_BP *)__pyx_v_self));

  /* function exit code */
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}

static PyObject *__pyx_pf_2bp_3_bp_2BP_76collapse(struct __pyx_obj_2bp_3_bp_BP *__pyx_v_self) {
  PyObject *__pyx_r = NULL;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("collapse", 0);
  __Pyx_XDECREF(__pyx_r);
  __pyx_t_1 = ((PyObject *)__pyx_f_2bp_3_bp_2BP_collapse(__pyx_v_self, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 843, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_r = __pyx_t_1;
  __pyx_t_1 = 0;
  goto __pyx_L0;

  /* function exit code */
  __pyx_L1_error:;
  __Pyx_XDECREF(__pyx_t_1);
  __Pyx_AddTraceback("bp._bp.BP.collapse", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __pyx_r = NULL;
  __pyx_L0:;
  __Pyx_XGIVEREF(__pyx_r);
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}
 0844:         cdef:
+0845:             SIZE_t i, n = self.B.sum()
  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self->B), __pyx_n_s_sum); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 845, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __pyx_t_3 = NULL;
  if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_2))) {
    __pyx_t_3 = PyMethod_GET_SELF(__pyx_t_2);
    if (likely(__pyx_t_3)) {
      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_2);
      __Pyx_INCREF(__pyx_t_3);
      __Pyx_INCREF(function);
      __Pyx_DECREF_SET(__pyx_t_2, function);
    }
  }
  __pyx_t_1 = (__pyx_t_3) ? __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_t_3) : __Pyx_PyObject_CallNoArg(__pyx_t_2);
  __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0;
  if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 845, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __pyx_t_4 = __Pyx_PyInt_As_Py_intptr_t(__pyx_t_1); if (unlikely((__pyx_t_4 == ((npy_intp)-1)) && PyErr_Occurred())) __PYX_ERR(0, 845, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_v_n = __pyx_t_4;
 0846:             SIZE_t current, first, last
 0847:             np.ndarray[DOUBLE_t, ndim=1] new_lengths
 0848:             BIT_ARRAY* mask
 0849:             DOUBLE_t* new_lengths_ptr
 0850:             BP new_bp
 0851: 
+0852:         mask = bit_array_create(self.B.size)
  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self->B), __pyx_n_s_size); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 852, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_5 = __Pyx_PyInt_As_uint64_t(__pyx_t_1); if (unlikely((__pyx_t_5 == ((bit_index_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 852, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_v_mask = bit_array_create(__pyx_t_5);
+0853:         bit_array_set_bit(mask, self.root())
  bit_array_set_bit(__pyx_v_mask, __pyx_f_2bp_3_bp_2BP_root(__pyx_v_self, 0));
+0854:         bit_array_set_bit(mask, self.close(self.root()))
  bit_array_set_bit(__pyx_v_mask, __pyx_f_2bp_3_bp_2BP_close(__pyx_v_self, __pyx_f_2bp_3_bp_2BP_root(__pyx_v_self, 0), 0));
 0855: 
+0856:         new_lengths = self._lengths.copy()
  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self->_lengths), __pyx_n_s_copy); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 856, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __pyx_t_3 = NULL;
  if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_2))) {
    __pyx_t_3 = PyMethod_GET_SELF(__pyx_t_2);
    if (likely(__pyx_t_3)) {
      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_2);
      __Pyx_INCREF(__pyx_t_3);
      __Pyx_INCREF(function);
      __Pyx_DECREF_SET(__pyx_t_2, function);
    }
  }
  __pyx_t_1 = (__pyx_t_3) ? __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_t_3) : __Pyx_PyObject_CallNoArg(__pyx_t_2);
  __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0;
  if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 856, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  if (!(likely(((__pyx_t_1) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_1, __pyx_ptype_5numpy_ndarray))))) __PYX_ERR(0, 856, __pyx_L1_error)
  __pyx_t_6 = ((PyArrayObject *)__pyx_t_1);
  {
    __Pyx_BufFmt_StackElem __pyx_stack[1];
    __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_new_lengths.rcbuffer->pybuffer);
    __pyx_t_7 = __Pyx_GetBufferAndValidate(&__pyx_pybuffernd_new_lengths.rcbuffer->pybuffer, (PyObject*)__pyx_t_6, &__Pyx_TypeInfo_nn___pyx_t_2bp_3_bp_DOUBLE_t, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack);
    if (unlikely(__pyx_t_7 < 0)) {
      PyErr_Fetch(&__pyx_t_8, &__pyx_t_9, &__pyx_t_10);
      if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_new_lengths.rcbuffer->pybuffer, (PyObject*)__pyx_v_new_lengths, &__Pyx_TypeInfo_nn___pyx_t_2bp_3_bp_DOUBLE_t, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {
        Py_XDECREF(__pyx_t_8); Py_XDECREF(__pyx_t_9); Py_XDECREF(__pyx_t_10);
        __Pyx_RaiseBufferFallbackError();
      } else {
        PyErr_Restore(__pyx_t_8, __pyx_t_9, __pyx_t_10);
      }
      __pyx_t_8 = __pyx_t_9 = __pyx_t_10 = 0;
    }
    __pyx_pybuffernd_new_lengths.diminfo[0].strides = __pyx_pybuffernd_new_lengths.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_new_lengths.diminfo[0].shape = __pyx_pybuffernd_new_lengths.rcbuffer->pybuffer.shape[0];
    if (unlikely(__pyx_t_7 < 0)) __PYX_ERR(0, 856, __pyx_L1_error)
  }
  __pyx_t_6 = 0;
  __pyx_v_new_lengths = ((PyArrayObject *)__pyx_t_1);
  __pyx_t_1 = 0;
+0857:         new_lengths_ptr = <DOUBLE_t*>new_lengths.data
  __pyx_v_new_lengths_ptr = ((__pyx_t_2bp_3_bp_DOUBLE_t *)__pyx_v_new_lengths->data);
 0858: 
+0859:         with nogil:
  {
      #ifdef WITH_THREAD
      PyThreadState *_save;
      Py_UNBLOCK_THREADS
      __Pyx_FastGIL_Remember();
      #endif
      /*try:*/ {
/* … */
      /*finally:*/ {
        /*normal exit:*/{
          #ifdef WITH_THREAD
          __Pyx_FastGIL_Forget();
          Py_BLOCK_THREADS
          #endif
          goto __pyx_L5;
        }
        __pyx_L5:;
      }
  }
+0860:             for i in range(n):
        __pyx_t_4 = __pyx_v_n;
        __pyx_t_11 = __pyx_t_4;
        for (__pyx_t_12 = 0; __pyx_t_12 < __pyx_t_11; __pyx_t_12+=1) {
          __pyx_v_i = __pyx_t_12;
+0861:                 current = self.preorderselect(i)
          __pyx_v_current = __pyx_f_2bp_3_bp_2BP_preorderselect(__pyx_v_self, __pyx_v_i, 0);
 0862: 
+0863:                 if self.isleaf(current):
          __pyx_t_13 = (__pyx_f_2bp_3_bp_2BP_isleaf(__pyx_v_self, __pyx_v_current, 0) != 0);
          if (__pyx_t_13) {
/* … */
            goto __pyx_L8;
          }
+0864:                     bit_array_set_bit(mask, current)
            bit_array_set_bit(__pyx_v_mask, __pyx_v_current);
+0865:                     bit_array_set_bit(mask, self.close(current))
            bit_array_set_bit(__pyx_v_mask, __pyx_f_2bp_3_bp_2BP_close(__pyx_v_self, __pyx_v_current, 0));
 0866:                 else:
+0867:                     first = self.fchild(current)
          /*else*/ {
            __pyx_v_first = __pyx_f_2bp_3_bp_2BP_fchild(__pyx_v_self, __pyx_v_current, 0);
+0868:                     last = self.lchild(current)
            __pyx_v_last = __pyx_f_2bp_3_bp_2BP_lchild(__pyx_v_self, __pyx_v_current, 0);
 0869: 
+0870:                     if first == last:
            __pyx_t_13 = ((__pyx_v_first == __pyx_v_last) != 0);
            if (__pyx_t_13) {
/* … */
              goto __pyx_L9;
            }
+0871:                         new_lengths_ptr[first] = new_lengths_ptr[first] + \
              (__pyx_v_new_lengths_ptr[__pyx_v_first]) = ((__pyx_v_new_lengths_ptr[__pyx_v_first]) + (__pyx_v_new_lengths_ptr[__pyx_v_current]));
 0872:                                 new_lengths_ptr[current]
 0873:                     else:
+0874:                         bit_array_set_bit(mask, current)
            /*else*/ {
              bit_array_set_bit(__pyx_v_mask, __pyx_v_current);
+0875:                         bit_array_set_bit(mask, self.close(current))
              bit_array_set_bit(__pyx_v_mask, __pyx_f_2bp_3_bp_2BP_close(__pyx_v_self, __pyx_v_current, 0));
            }
            __pyx_L9:;
          }
          __pyx_L8:;
        }
      }
 0876: 
+0877:         new_bp = self._mask_from_self(mask, new_lengths)
  __pyx_t_1 = ((PyObject *)__pyx_f_2bp_3_bp_2BP__mask_from_self(__pyx_v_self, __pyx_v_mask, ((PyArrayObject *)__pyx_v_new_lengths))); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 877, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_v_new_bp = ((struct __pyx_obj_2bp_3_bp_BP *)__pyx_t_1);
  __pyx_t_1 = 0;
+0878:         bit_array_free(mask)
  bit_array_free(__pyx_v_mask);
+0879:         return new_bp
  __Pyx_XDECREF(((PyObject *)__pyx_r));
  __Pyx_INCREF(((PyObject *)__pyx_v_new_bp));
  __pyx_r = __pyx_v_new_bp;
  goto __pyx_L0;
 0880: 
+0881:     cpdef inline SIZE_t ntips(self) nogil:
static PyObject *__pyx_pw_2bp_3_bp_2BP_79ntips(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused); /*proto*/
static __pyx_t_2bp_3_bp_SIZE_t __pyx_f_2bp_3_bp_2BP_ntips(struct __pyx_obj_2bp_3_bp_BP *__pyx_v_self, CYTHON_UNUSED int __pyx_skip_dispatch) {
  __pyx_t_2bp_3_bp_SIZE_t __pyx_v_i;
  __pyx_t_2bp_3_bp_SIZE_t __pyx_v_count;
  __pyx_t_2bp_3_bp_SIZE_t __pyx_v_n;
  __pyx_t_2bp_3_bp_SIZE_t __pyx_r;
/* … */
  /* function exit code */
  __pyx_L0:;
  return __pyx_r;
}

/* Python wrapper */
static PyObject *__pyx_pw_2bp_3_bp_2BP_79ntips(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused); /*proto*/
static PyObject *__pyx_pw_2bp_3_bp_2BP_79ntips(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused) {
  PyObject *__pyx_r = 0;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("ntips (wrapper)", 0);
  __pyx_r = __pyx_pf_2bp_3_bp_2BP_78ntips(((struct __pyx_obj_2bp_3_bp_BP *)__pyx_v_self));

  /* function exit code */
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}

static PyObject *__pyx_pf_2bp_3_bp_2BP_78ntips(struct __pyx_obj_2bp_3_bp_BP *__pyx_v_self) {
  PyObject *__pyx_r = NULL;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("ntips", 0);
  __Pyx_XDECREF(__pyx_r);
  __pyx_t_1 = __Pyx_PyInt_From_Py_intptr_t(__pyx_f_2bp_3_bp_2BP_ntips(__pyx_v_self, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 881, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_r = __pyx_t_1;
  __pyx_t_1 = 0;
  goto __pyx_L0;

  /* function exit code */
  __pyx_L1_error:;
  __Pyx_XDECREF(__pyx_t_1);
  __Pyx_AddTraceback("bp._bp.BP.ntips", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __pyx_r = NULL;
  __pyx_L0:;
  __Pyx_XGIVEREF(__pyx_r);
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}
 0882:         cdef:
+0883:             SIZE_t i = 0
  __pyx_v_i = 0;
+0884:             SIZE_t count = 0
  __pyx_v_count = 0;
+0885:             SIZE_t n = self.size
  __pyx_t_1 = __pyx_v_self->size;
  __pyx_v_n = __pyx_t_1;
 0886: 
+0887:         while i < (n - 1):
  while (1) {
    __pyx_t_2 = ((__pyx_v_i < (__pyx_v_n - 1)) != 0);
    if (!__pyx_t_2) break;
+0888:             if self._b_ptr[i] and not self._b_ptr[i+1]:
    __pyx_t_3 = ((__pyx_v_self->_b_ptr[__pyx_v_i]) != 0);
    if (__pyx_t_3) {
    } else {
      __pyx_t_2 = __pyx_t_3;
      goto __pyx_L6_bool_binop_done;
    }
    __pyx_t_3 = ((!((__pyx_v_self->_b_ptr[(__pyx_v_i + 1)]) != 0)) != 0);
    __pyx_t_2 = __pyx_t_3;
    __pyx_L6_bool_binop_done:;
    if (__pyx_t_2) {
/* … */
    }
+0889:                 count += 1
      __pyx_v_count = (__pyx_v_count + 1);
+0890:                 i += 1
      __pyx_v_i = (__pyx_v_i + 1);
+0891:             i += 1
    __pyx_v_i = (__pyx_v_i + 1);
  }
 0892: 
+0893:         return count
  __pyx_r = __pyx_v_count;
  goto __pyx_L0;
 0894: 
+0895:     cdef int scan_block_forward(self, int i, int k, int b, int d) nogil:
static int __pyx_f_2bp_3_bp_2BP_scan_block_forward(struct __pyx_obj_2bp_3_bp_BP *__pyx_v_self, int __pyx_v_i, int __pyx_v_k, int __pyx_v_b, int __pyx_v_d) {
  int __pyx_v_lower_bound;
  int __pyx_v_upper_bound;
  int __pyx_v_j;
  int __pyx_r;
/* … */
  /* function exit code */
  __pyx_L1_error:;
  __Pyx_WriteUnraisable("bp._bp.BP.scan_block_forward", __pyx_clineno, __pyx_lineno, __pyx_filename, 1, 1);
  __pyx_r = 0;
  __pyx_L0:;
  return __pyx_r;
}
 0896:         """Scan a block forward from i
 0897: 
 0898:         Parameters
 0899:         ----------
 0900:         bp : BP
 0901:             The tree
 0902:         i : int
 0903:             The index position to start from in the tree
 0904:         k : int
 0905:             The block to explore
 0906:         b : int
 0907:             The block size
 0908:         d : int
 0909:             The depth to search for
 0910: 
 0911:         Returns
 0912:         -------
 0913:         int
 0914:             The index position of the result. -1 is returned if a result is not
 0915:             found.
 0916:         """
 0917:         cdef int lower_bound
 0918:         cdef int upper_bound
 0919:         cdef int j
 0920: 
 0921:         # lower_bound is block boundary or right of i
+0922:         lower_bound = max(k, 0) * b
  __pyx_v_lower_bound = (__pyx_f_2bp_3_bp_max(__pyx_v_k, 0) * __pyx_v_b);
+0923:         lower_bound = max(i + 1, lower_bound)
  __pyx_v_lower_bound = __pyx_f_2bp_3_bp_max((__pyx_v_i + 1), __pyx_v_lower_bound);
 0924: 
 0925:         # upper_bound is block boundary or end of tree
+0926:         upper_bound = min((k + 1) * b, self.size)
  __pyx_v_upper_bound = __pyx_f_2bp_3_bp_min(((__pyx_v_k + 1) * __pyx_v_b), __pyx_v_self->size);
 0927: 
+0928:         for j in range(lower_bound, upper_bound):
  __pyx_t_1 = __pyx_v_upper_bound;
  __pyx_t_2 = __pyx_t_1;
  for (__pyx_t_3 = __pyx_v_lower_bound; __pyx_t_3 < __pyx_t_2; __pyx_t_3+=1) {
    __pyx_v_j = __pyx_t_3;
+0929:             if self._e_index[j] == d:
    if (unlikely(!__pyx_v_self->_e_index.memview)) {PyErr_SetString(PyExc_AttributeError,"Memoryview is not initialized");__PYX_ERR(0, 929, __pyx_L1_error)}
    __pyx_t_4 = __pyx_v_j;
    __pyx_t_5 = (((*((__pyx_t_2bp_3_bp_SIZE_t *) ( /* dim=0 */ (__pyx_v_self->_e_index.data + __pyx_t_4 * __pyx_v_self->_e_index.strides[0]) ))) == __pyx_v_d) != 0);
    if (__pyx_t_5) {
/* … */
    }
  }
+0930:                 return j
      __pyx_r = __pyx_v_j;
      goto __pyx_L0;
 0931: 
+0932:         return -1
  __pyx_r = -1;
  goto __pyx_L0;
 0933: 
+0934:     cdef int scan_block_backward(self, int i, int k, int b, int d) nogil:
static int __pyx_f_2bp_3_bp_2BP_scan_block_backward(struct __pyx_obj_2bp_3_bp_BP *__pyx_v_self, int __pyx_v_i, int __pyx_v_k, int __pyx_v_b, int __pyx_v_d) {
  int __pyx_v_lower_bound;
  int __pyx_v_upper_bound;
  int __pyx_v_j;
  int __pyx_r;
/* … */
  /* function exit code */
  __pyx_L0:;
  return __pyx_r;
}
 0935:         """Scan a block backward from i
 0936: 
 0937:         Parameters
 0938:         ----------
 0939:         i : int
 0940:             The index position to start from in the tree
 0941:         k : int
 0942:             The block to explore
 0943:         b : int
 0944:             The block size
 0945:         d : int
 0946:             The depth to search for
 0947: 
 0948:         Returns
 0949:         -------
 0950:         int
 0951:             The index position of the result. -1 is returned if a result is not
 0952:             found.
 0953:         """
 0954:         cdef int lower_bound
 0955:         cdef int upper_bound
 0956:         cdef int j
 0957: 
 0958:         # i and k are currently needed to handle the situation where 
 0959:         # k_start < i < k_end. It should be possible to resolve using partial 
 0960:         # excess.
 0961: 
 0962:         # range stop is exclusive, so need to set "stop" at -1 of boundary
+0963:         lower_bound = max(k, 0) * b - 1  # is it possible for k to be < 0?
  __pyx_v_lower_bound = ((__pyx_f_2bp_3_bp_max(__pyx_v_k, 0) * __pyx_v_b) - 1);
 0964: 
 0965:         # include the right most position of the k-1 block so we can identify
 0966:         # closures spanning blocks. Not positive if this is correct, however if the
 0967:         # block is "()((", and we're searching for the opening paired with ")", 
 0968:         # we need to go to evaluate the excess prior to the first "(", at least as
 0969:         # "open" is defined in Cordova and Navarro
+0970:         if lower_bound >= 0:
  __pyx_t_1 = ((__pyx_v_lower_bound >= 0) != 0);
  if (__pyx_t_1) {
/* … */
  }
+0971:             lower_bound -= 1
    __pyx_v_lower_bound = (__pyx_v_lower_bound - 1);
 0972: 
 0973:         # upper bound is block boundary or left of i, whichever is less
 0974:         # note that this is an inclusive boundary since this is a backward search
+0975:         upper_bound = min((k + 1) * b, self.size) - 1
  __pyx_v_upper_bound = (__pyx_f_2bp_3_bp_min(((__pyx_v_k + 1) * __pyx_v_b), __pyx_v_self->size) - 1);
+0976:         upper_bound = min(i - 1, upper_bound)
  __pyx_v_upper_bound = __pyx_f_2bp_3_bp_min((__pyx_v_i - 1), __pyx_v_upper_bound);
 0977: 
+0978:         if upper_bound <= 0:
  __pyx_t_1 = ((__pyx_v_upper_bound <= 0) != 0);
  if (__pyx_t_1) {
/* … */
  }
+0979:             return -1
    __pyx_r = -1;
    goto __pyx_L0;
 0980: 
+0981:         for j in range(upper_bound, lower_bound, -1):
  __pyx_t_2 = __pyx_v_lower_bound;
  __pyx_t_3 = __pyx_t_2;
  for (__pyx_t_4 = __pyx_v_upper_bound; __pyx_t_4 > __pyx_t_3; __pyx_t_4-=1) {
    __pyx_v_j = __pyx_t_4;
+0982:             if self.excess(j) == d:
    __pyx_t_1 = ((__pyx_f_2bp_3_bp_2BP_excess(__pyx_v_self, __pyx_v_j) == __pyx_v_d) != 0);
    if (__pyx_t_1) {
/* … */
    }
  }
+0983:                 return j
      __pyx_r = __pyx_v_j;
      goto __pyx_L0;
 0984: 
+0985:         return -1
  __pyx_r = -1;
  goto __pyx_L0;
 0986: 
+0987:     cdef SIZE_t fwdsearch(self, SIZE_t i, int d) nogil:
static __pyx_t_2bp_3_bp_SIZE_t __pyx_f_2bp_3_bp_2BP_fwdsearch(struct __pyx_obj_2bp_3_bp_BP *__pyx_v_self, __pyx_t_2bp_3_bp_SIZE_t __pyx_v_i, int __pyx_v_d) {
  int __pyx_v_k;
  int __pyx_v_result;
  int __pyx_v_node;
  __pyx_t_2bp_3_bp_SIZE_t __pyx_r;
/* … */
  /* function exit code */
  __pyx_L1_error:;
  __Pyx_WriteUnraisable("bp._bp.BP.fwdsearch", __pyx_clineno, __pyx_lineno, __pyx_filename, 1, 1);
  __pyx_r = 0;
  __pyx_L0:;
  return __pyx_r;
}
 0988:         """Search forward from i for desired excess
 0989: 
 0990:         Parameters
 0991:         ----------
 0992:         i : int
 0993:             The index to search forward from
 0994:         d : int
 0995:             The excess difference to search for (relative to E[i])
 0996:         
 0997:         Returns
 0998:         -------
 0999:         int
 1000:             The index of the result, or -1 if no result was found
 1001:         """
 1002:         cdef int k  # the block being interrogated
+1003:         cdef int result = -1 # the result of a scan within a block
  __pyx_v_result = -1;
 1004:         cdef int node  # the node within the binary tree being examined
 1005: 
 1006:         # get the block of parentheses to check
+1007:         k = i // self._rmm.b
  __pyx_v_k = (__pyx_v_i / __pyx_v_self->_rmm->b);
 1008: 
 1009:         # desired excess
+1010:         d += self._e_index[i]
  if (unlikely(!__pyx_v_self->_e_index.memview)) {PyErr_SetString(PyExc_AttributeError,"Memoryview is not initialized");__PYX_ERR(0, 1010, __pyx_L1_error)}
  __pyx_t_1 = __pyx_v_i;
  __pyx_v_d = (__pyx_v_d + (*((__pyx_t_2bp_3_bp_SIZE_t *) ( /* dim=0 */ (__pyx_v_self->_e_index.data + __pyx_t_1 * __pyx_v_self->_e_index.strides[0]) ))));
 1011: 
 1012:         # determine which node our block corresponds too
+1013:         node = bt_node_from_left(k, self._rmm.height)
  __pyx_v_node = __pyx_f_2bp_12_binary_tree_bt_node_from_left(__pyx_v_k, __pyx_v_self->_rmm->height);
 1014: 
 1015:         # see if our result is in our current block
+1016:         if self._rmm.mM[node, self._rmm.m_idx] <= d <= self._rmm.mM[node, self._rmm.M_idx]:
  if (unlikely(!__pyx_v_self->_rmm->mM.memview)) {PyErr_SetString(PyExc_AttributeError,"Memoryview is not initialized");__PYX_ERR(0, 1016, __pyx_L1_error)}
  __pyx_t_1 = __pyx_v_node;
  __pyx_t_2 = __pyx_v_self->_rmm->m_idx;
  __pyx_t_3 = ((*((__pyx_t_2bp_3_bp_SIZE_t *) ( /* dim=1 */ ((char *) (((__pyx_t_2bp_3_bp_SIZE_t *) ( /* dim=0 */ (__pyx_v_self->_rmm->mM.data + __pyx_t_1 * __pyx_v_self->_rmm->mM.strides[0]) )) + __pyx_t_2)) ))) <= __pyx_v_d);
  if (__pyx_t_3) {
    if (unlikely(!__pyx_v_self->_rmm->mM.memview)) {PyErr_SetString(PyExc_AttributeError,"Memoryview is not initialized");__PYX_ERR(0, 1016, __pyx_L1_error)}
    __pyx_t_4 = __pyx_v_node;
    __pyx_t_5 = __pyx_v_self->_rmm->M_idx;
    __pyx_t_3 = (__pyx_v_d <= (*((__pyx_t_2bp_3_bp_SIZE_t *) ( /* dim=1 */ ((char *) (((__pyx_t_2bp_3_bp_SIZE_t *) ( /* dim=0 */ (__pyx_v_self->_rmm->mM.data + __pyx_t_4 * __pyx_v_self->_rmm->mM.strides[0]) )) + __pyx_t_5)) ))));
  }
  __pyx_t_6 = (__pyx_t_3 != 0);
  if (__pyx_t_6) {
/* … */
  }
+1017:             result = self.scan_block_forward(i, k, self._rmm.b, d)
    __pyx_v_result = __pyx_f_2bp_3_bp_2BP_scan_block_forward(__pyx_v_self, __pyx_v_i, __pyx_v_k, __pyx_v_self->_rmm->b, __pyx_v_d);
 1018: 
 1019:         # if we do not have a result, we need to begin traversal of the tree
+1020:         if result == -1:
  __pyx_t_6 = ((__pyx_v_result == -1L) != 0);
  if (__pyx_t_6) {
/* … */
  }
 1021:             # walk up the tree
+1022:             while not bt_is_root(node):
    while (1) {
      __pyx_t_6 = ((!(__pyx_f_2bp_12_binary_tree_bt_is_root(__pyx_v_node) != 0)) != 0);
      if (!__pyx_t_6) break;
+1023:                 if bt_is_left_child(node):
      __pyx_t_6 = (__pyx_f_2bp_12_binary_tree_bt_is_left_child(__pyx_v_node) != 0);
      if (__pyx_t_6) {
/* … */
      }
+1024:                     node = bt_right_sibling(node)
        __pyx_v_node = __pyx_f_2bp_12_binary_tree_bt_right_sibling(__pyx_v_node);
+1025:                     if self._rmm.mM[node, self._rmm.m_idx] <= d  <= self._rmm.mM[node, self._rmm.M_idx]:
        if (unlikely(!__pyx_v_self->_rmm->mM.memview)) {PyErr_SetString(PyExc_AttributeError,"Memoryview is not initialized");__PYX_ERR(0, 1025, __pyx_L1_error)}
        __pyx_t_2 = __pyx_v_node;
        __pyx_t_1 = __pyx_v_self->_rmm->m_idx;
        __pyx_t_6 = ((*((__pyx_t_2bp_3_bp_SIZE_t *) ( /* dim=1 */ ((char *) (((__pyx_t_2bp_3_bp_SIZE_t *) ( /* dim=0 */ (__pyx_v_self->_rmm->mM.data + __pyx_t_2 * __pyx_v_self->_rmm->mM.strides[0]) )) + __pyx_t_1)) ))) <= __pyx_v_d);
        if (__pyx_t_6) {
          if (unlikely(!__pyx_v_self->_rmm->mM.memview)) {PyErr_SetString(PyExc_AttributeError,"Memoryview is not initialized");__PYX_ERR(0, 1025, __pyx_L1_error)}
          __pyx_t_5 = __pyx_v_node;
          __pyx_t_4 = __pyx_v_self->_rmm->M_idx;
          __pyx_t_6 = (__pyx_v_d <= (*((__pyx_t_2bp_3_bp_SIZE_t *) ( /* dim=1 */ ((char *) (((__pyx_t_2bp_3_bp_SIZE_t *) ( /* dim=0 */ (__pyx_v_self->_rmm->mM.data + __pyx_t_5 * __pyx_v_self->_rmm->mM.strides[0]) )) + __pyx_t_4)) ))));
        }
        __pyx_t_3 = (__pyx_t_6 != 0);
        if (__pyx_t_3) {
/* … */
        }
+1026:                         break
          goto __pyx_L6_break;
+1027:                 node = bt_parent(node)
      __pyx_v_node = __pyx_f_2bp_12_binary_tree_bt_parent(__pyx_v_node);
    }
    __pyx_L6_break:;
 1028: 
+1029:             if bt_is_root(node):
    __pyx_t_3 = (__pyx_f_2bp_12_binary_tree_bt_is_root(__pyx_v_node) != 0);
    if (__pyx_t_3) {
/* … */
    }
+1030:                 return -1
      __pyx_r = -1;
      goto __pyx_L0;
 1031: 
 1032:             # descend until we hit a leaf node
+1033:             while not bt_is_leaf(node, self._rmm.height):
    while (1) {
      __pyx_t_3 = ((!(__pyx_f_2bp_12_binary_tree_bt_is_leaf(__pyx_v_node, __pyx_v_self->_rmm->height) != 0)) != 0);
      if (!__pyx_t_3) break;
+1034:                 node = bt_left_child(node)
      __pyx_v_node = __pyx_f_2bp_12_binary_tree_bt_left_child(__pyx_v_node);
 1035: 
 1036:                 # evaluate right, if not found, pick left
+1037:                 if not (self._rmm.mM[node, self._rmm.m_idx] <= d <= self._rmm.mM[node, self._rmm.M_idx]):
      if (unlikely(!__pyx_v_self->_rmm->mM.memview)) {PyErr_SetString(PyExc_AttributeError,"Memoryview is not initialized");__PYX_ERR(0, 1037, __pyx_L1_error)}
      __pyx_t_1 = __pyx_v_node;
      __pyx_t_2 = __pyx_v_self->_rmm->m_idx;
      __pyx_t_3 = ((*((__pyx_t_2bp_3_bp_SIZE_t *) ( /* dim=1 */ ((char *) (((__pyx_t_2bp_3_bp_SIZE_t *) ( /* dim=0 */ (__pyx_v_self->_rmm->mM.data + __pyx_t_1 * __pyx_v_self->_rmm->mM.strides[0]) )) + __pyx_t_2)) ))) <= __pyx_v_d);
      if (__pyx_t_3) {
        if (unlikely(!__pyx_v_self->_rmm->mM.memview)) {PyErr_SetString(PyExc_AttributeError,"Memoryview is not initialized");__PYX_ERR(0, 1037, __pyx_L1_error)}
        __pyx_t_4 = __pyx_v_node;
        __pyx_t_5 = __pyx_v_self->_rmm->M_idx;
        __pyx_t_3 = (__pyx_v_d <= (*((__pyx_t_2bp_3_bp_SIZE_t *) ( /* dim=1 */ ((char *) (((__pyx_t_2bp_3_bp_SIZE_t *) ( /* dim=0 */ (__pyx_v_self->_rmm->mM.data + __pyx_t_4 * __pyx_v_self->_rmm->mM.strides[0]) )) + __pyx_t_5)) ))));
      }
      __pyx_t_6 = ((!(__pyx_t_3 != 0)) != 0);
      if (__pyx_t_6) {
/* … */
      }
    }
+1038:                     node = bt_right_sibling(node)
        __pyx_v_node = __pyx_f_2bp_12_binary_tree_bt_right_sibling(__pyx_v_node);
 1039: 
 1040:             # we have found a block with contains our solution. convert from the
 1041:             # node index back into the block index
+1042:             k = node - <int>(pow(2, self._rmm.height) - 1)
    __pyx_v_k = (__pyx_v_node - ((int)(pow(2.0, __pyx_v_self->_rmm->height) - 1.0)));
 1043: 
 1044:             # scan for a result using the original d
+1045:             result = self.scan_block_forward(i, k, self._rmm.b, d)
    __pyx_v_result = __pyx_f_2bp_3_bp_2BP_scan_block_forward(__pyx_v_self, __pyx_v_i, __pyx_v_k, __pyx_v_self->_rmm->b, __pyx_v_d);
 1046: 
+1047:         return result
  __pyx_r = __pyx_v_result;
  goto __pyx_L0;
 1048: 
+1049:     cdef SIZE_t bwdsearch(self, SIZE_t i, int d) nogil:
static __pyx_t_2bp_3_bp_SIZE_t __pyx_f_2bp_3_bp_2BP_bwdsearch(struct __pyx_obj_2bp_3_bp_BP *__pyx_v_self, __pyx_t_2bp_3_bp_SIZE_t __pyx_v_i, int __pyx_v_d) {
  int __pyx_v_k;
  int __pyx_v_result;
  int __pyx_v_node;
  __pyx_t_2bp_3_bp_SIZE_t __pyx_r;
/* … */
  /* function exit code */
  __pyx_L1_error:;
  __Pyx_WriteUnraisable("bp._bp.BP.bwdsearch", __pyx_clineno, __pyx_lineno, __pyx_filename, 1, 1);
  __pyx_r = 0;
  __pyx_L0:;
  return __pyx_r;
}
 1050:         """Search backward from i for desired excess
 1051: 
 1052:         Parameters
 1053:         ----------
 1054:         i : int
 1055:             The index to search forward from
 1056:         d : int
 1057:             The excess difference to search for (relative to E[i])
 1058:         
 1059:         Returns
 1060:         -------
 1061:         int
 1062:             The index of the result, or -1 if no result was found
 1063:         """
 1064:         cdef int k  # the block being interrogated
+1065:         cdef int result = -1 # the result of a scan within a block
  __pyx_v_result = -1;
 1066:         cdef int node  # the node within the binary tree being examined
 1067: 
 1068:         # get the block of parentheses to check
+1069:         k = i // self._rmm.b
  __pyx_v_k = (__pyx_v_i / __pyx_v_self->_rmm->b);
 1070: 
 1071:         # desired excess
+1072:         d += self.excess(i)
  __pyx_v_d = (__pyx_v_d + __pyx_f_2bp_3_bp_2BP_excess(__pyx_v_self, __pyx_v_i));
 1073: 
 1074:         # see if our result is in our current block
+1075:         result = self.scan_block_backward(i, k, self._rmm.b, d)
  __pyx_v_result = __pyx_f_2bp_3_bp_2BP_scan_block_backward(__pyx_v_self, __pyx_v_i, __pyx_v_k, __pyx_v_self->_rmm->b, __pyx_v_d);
 1076: 
 1077:         # determine which node our block corresponds too
+1078:         node = bt_node_from_left(k, self._rmm.height)
  __pyx_v_node = __pyx_f_2bp_12_binary_tree_bt_node_from_left(__pyx_v_k, __pyx_v_self->_rmm->height);
 1079: 
 1080:         # special case: check sibling
+1081:         if result == -1 and bt_is_right_child(node):
  __pyx_t_2 = ((__pyx_v_result == -1L) != 0);
  if (__pyx_t_2) {
  } else {
    __pyx_t_1 = __pyx_t_2;
    goto __pyx_L4_bool_binop_done;
  }
  __pyx_t_2 = (__pyx_f_2bp_12_binary_tree_bt_is_right_child(__pyx_v_node) != 0);
  __pyx_t_1 = __pyx_t_2;
  __pyx_L4_bool_binop_done:;
  if (__pyx_t_1) {
/* … */
  }
+1082:             node = bt_left_sibling(node)
    __pyx_v_node = __pyx_f_2bp_12_binary_tree_bt_left_sibling(__pyx_v_node);
+1083:             k = node - <int>(pow(2, self._rmm.height) - 1)
    __pyx_v_k = (__pyx_v_node - ((int)(pow(2.0, __pyx_v_self->_rmm->height) - 1.0)));
+1084:             result = self.scan_block_backward(i, k, self._rmm.b, d)
    __pyx_v_result = __pyx_f_2bp_3_bp_2BP_scan_block_backward(__pyx_v_self, __pyx_v_i, __pyx_v_k, __pyx_v_self->_rmm->b, __pyx_v_d);
 1085: 
 1086:            # reset node and k in the event that result == -1
+1087:             k = i // self._rmm.b
    __pyx_v_k = (__pyx_v_i / __pyx_v_self->_rmm->b);
+1088:             node = bt_right_sibling(node)
    __pyx_v_node = __pyx_f_2bp_12_binary_tree_bt_right_sibling(__pyx_v_node);
 1089: 
 1090:         # if we do not have a result, we need to begin traversal of the tree
+1091:         if result == -1:
  __pyx_t_1 = ((__pyx_v_result == -1L) != 0);
  if (__pyx_t_1) {
/* … */
  }
+1092:             while not bt_is_root(node):
    while (1) {
      __pyx_t_1 = ((!(__pyx_f_2bp_12_binary_tree_bt_is_root(__pyx_v_node) != 0)) != 0);
      if (!__pyx_t_1) break;
 1093:                 # right nodes cannot contain the solution as we are searching left
 1094:                 # As such, if we are the right node already, evaluate its sibling.
+1095:                 if bt_is_right_child(node):
      __pyx_t_1 = (__pyx_f_2bp_12_binary_tree_bt_is_right_child(__pyx_v_node) != 0);
      if (__pyx_t_1) {
/* … */
      }
+1096:                     node = bt_left_sibling(node)
        __pyx_v_node = __pyx_f_2bp_12_binary_tree_bt_left_sibling(__pyx_v_node);
+1097:                     if self._rmm.mM[node, self._rmm.m_idx] <= d <= self._rmm.mM[node, self._rmm.M_idx]:
        if (unlikely(!__pyx_v_self->_rmm->mM.memview)) {PyErr_SetString(PyExc_AttributeError,"Memoryview is not initialized");__PYX_ERR(0, 1097, __pyx_L1_error)}
        __pyx_t_3 = __pyx_v_node;
        __pyx_t_4 = __pyx_v_self->_rmm->m_idx;
        __pyx_t_1 = ((*((__pyx_t_2bp_3_bp_SIZE_t *) ( /* dim=1 */ ((char *) (((__pyx_t_2bp_3_bp_SIZE_t *) ( /* dim=0 */ (__pyx_v_self->_rmm->mM.data + __pyx_t_3 * __pyx_v_self->_rmm->mM.strides[0]) )) + __pyx_t_4)) ))) <= __pyx_v_d);
        if (__pyx_t_1) {
          if (unlikely(!__pyx_v_self->_rmm->mM.memview)) {PyErr_SetString(PyExc_AttributeError,"Memoryview is not initialized");__PYX_ERR(0, 1097, __pyx_L1_error)}
          __pyx_t_5 = __pyx_v_node;
          __pyx_t_6 = __pyx_v_self->_rmm->M_idx;
          __pyx_t_1 = (__pyx_v_d <= (*((__pyx_t_2bp_3_bp_SIZE_t *) ( /* dim=1 */ ((char *) (((__pyx_t_2bp_3_bp_SIZE_t *) ( /* dim=0 */ (__pyx_v_self->_rmm->mM.data + __pyx_t_5 * __pyx_v_self->_rmm->mM.strides[0]) )) + __pyx_t_6)) ))));
        }
        __pyx_t_2 = (__pyx_t_1 != 0);
        if (__pyx_t_2) {
/* … */
        }
+1098:                         break
          goto __pyx_L8_break;
 1099: 
 1100:                 # if we did not find a valid node, adjust for the relative
 1101:                 # excess of the current node, and ascend to the parent
+1102:                 node = bt_parent(node)
      __pyx_v_node = __pyx_f_2bp_12_binary_tree_bt_parent(__pyx_v_node);
    }
    __pyx_L8_break:;
 1103: 
+1104:             if bt_is_root(node):
    __pyx_t_2 = (__pyx_f_2bp_12_binary_tree_bt_is_root(__pyx_v_node) != 0);
    if (__pyx_t_2) {
/* … */
    }
+1105:                 return -1
      __pyx_r = -1;
      goto __pyx_L0;
 1106: 
 1107:             # descend until we hit a leaf node
+1108:             while not bt_is_leaf(node, self._rmm.height):
    while (1) {
      __pyx_t_2 = ((!(__pyx_f_2bp_12_binary_tree_bt_is_leaf(__pyx_v_node, __pyx_v_self->_rmm->height) != 0)) != 0);
      if (!__pyx_t_2) break;
+1109:                 node = bt_right_child(node)
      __pyx_v_node = __pyx_f_2bp_12_binary_tree_bt_right_child(__pyx_v_node);
 1110: 
 1111:                 # evaluate right, if not found, pick left
+1112:                 if not (self._rmm.mM[node, self._rmm.m_idx] <= d <= self._rmm.mM[node, self._rmm.M_idx]):
      if (unlikely(!__pyx_v_self->_rmm->mM.memview)) {PyErr_SetString(PyExc_AttributeError,"Memoryview is not initialized");__PYX_ERR(0, 1112, __pyx_L1_error)}
      __pyx_t_4 = __pyx_v_node;
      __pyx_t_3 = __pyx_v_self->_rmm->m_idx;
      __pyx_t_2 = ((*((__pyx_t_2bp_3_bp_SIZE_t *) ( /* dim=1 */ ((char *) (((__pyx_t_2bp_3_bp_SIZE_t *) ( /* dim=0 */ (__pyx_v_self->_rmm->mM.data + __pyx_t_4 * __pyx_v_self->_rmm->mM.strides[0]) )) + __pyx_t_3)) ))) <= __pyx_v_d);
      if (__pyx_t_2) {
        if (unlikely(!__pyx_v_self->_rmm->mM.memview)) {PyErr_SetString(PyExc_AttributeError,"Memoryview is not initialized");__PYX_ERR(0, 1112, __pyx_L1_error)}
        __pyx_t_6 = __pyx_v_node;
        __pyx_t_5 = __pyx_v_self->_rmm->M_idx;
        __pyx_t_2 = (__pyx_v_d <= (*((__pyx_t_2bp_3_bp_SIZE_t *) ( /* dim=1 */ ((char *) (((__pyx_t_2bp_3_bp_SIZE_t *) ( /* dim=0 */ (__pyx_v_self->_rmm->mM.data + __pyx_t_6 * __pyx_v_self->_rmm->mM.strides[0]) )) + __pyx_t_5)) ))));
      }
      __pyx_t_1 = ((!(__pyx_t_2 != 0)) != 0);
      if (__pyx_t_1) {
/* … */
      }
    }
+1113:                     node = bt_left_sibling(node)
        __pyx_v_node = __pyx_f_2bp_12_binary_tree_bt_left_sibling(__pyx_v_node);
 1114: 
 1115:             # we have found a block with contains our solution. convert from the
 1116:             # node index back into the block index
+1117:             k = node - <int>(pow(2, self._rmm.height) - 1)
    __pyx_v_k = (__pyx_v_node - ((int)(pow(2.0, __pyx_v_self->_rmm->height) - 1.0)));
 1118: 
 1119:             # scan for a result
+1120:             result = self.scan_block_backward(i, k, self._rmm.b, d)
    __pyx_v_result = __pyx_f_2bp_3_bp_2BP_scan_block_backward(__pyx_v_self, __pyx_v_i, __pyx_v_k, __pyx_v_self->_rmm->b, __pyx_v_d);
 1121: 
+1122:         return result
  __pyx_r = __pyx_v_result;
  goto __pyx_L0;
 1123: 
 1124: # add in .r and .n into rmm calculation
 1125: #   - necessary for mincount/minselect
 1126: ###
 1127: ###
 1128: 
 1129: 
 1130: