Generated by Cython 3.0.11

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: cut_finder.c

+001: # distutils: language = c
  __pyx_t_7 = __Pyx_PyDict_NewPresized(0); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 1, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_7);
  if (PyDict_SetItem(__pyx_d, __pyx_n_s_test, __pyx_t_7) < 0) __PYX_ERR(0, 1, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
 002: # cython: boundscheck = False
 003: # cython: wraparound = False
 004: # cython: profile = False
 005: 
+006: import numpy as np
  __pyx_t_7 = __Pyx_ImportDottedModule(__pyx_n_s_numpy, NULL); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 6, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_7);
  if (PyDict_SetItem(__pyx_d, __pyx_n_s_np, __pyx_t_7) < 0) __PYX_ERR(0, 6, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
 007: cimport numpy as np
 008: cimport cython
 009: from cython.parallel import prange
 010: from libc.stdlib cimport malloc, free
 011: 
+012: ctypedef np.int32_t NP_INT_t
typedef __pyx_t_5numpy_int32_t __pyx_t_5d_imm_9splitters_10cut_finder_NP_INT_t;
 013: ctypedef np.float64_t NP_FLOAT_t
 014: 
 015: cdef extern from "<math.h>" nogil:
 016:     const float INFINITY
 017: 
 018: cdef extern from "<limits.h>":
 019:     const int INT_MIN
 020:     const int INT_MAX
 021: 
+022: @cython.boundscheck(False)
/* Python wrapper */
static PyObject *__pyx_pw_5d_imm_9splitters_10cut_finder_1get_all_mistakes(PyObject *__pyx_self, 
#if CYTHON_METH_FASTCALL
PyObject *const *__pyx_args, Py_ssize_t __pyx_nargs, PyObject *__pyx_kwds
#else
PyObject *__pyx_args, PyObject *__pyx_kwds
#endif
); /*proto*/
PyDoc_STRVAR(__pyx_doc_5d_imm_9splitters_10cut_finder_get_all_mistakes, "\n    Main function to calculate mistakes for all features and thresholds.\n    Returns a list of Python dictionaries with 'feature', 'threshold', and 'mistakes'.\n    ");
static PyMethodDef __pyx_mdef_5d_imm_9splitters_10cut_finder_1get_all_mistakes = {"get_all_mistakes", (PyCFunction)(void*)(__Pyx_PyCFunction_FastCallWithKeywords)__pyx_pw_5d_imm_9splitters_10cut_finder_1get_all_mistakes, __Pyx_METH_FASTCALL|METH_KEYWORDS, __pyx_doc_5d_imm_9splitters_10cut_finder_get_all_mistakes};
static PyObject *__pyx_pw_5d_imm_9splitters_10cut_finder_1get_all_mistakes(PyObject *__pyx_self, 
#if CYTHON_METH_FASTCALL
PyObject *const *__pyx_args, Py_ssize_t __pyx_nargs, PyObject *__pyx_kwds
#else
PyObject *__pyx_args, PyObject *__pyx_kwds
#endif
) {
  __Pyx_memviewslice __pyx_v_X = { 0, 0, { 0 }, { 0 }, { 0 } };
  __Pyx_memviewslice __pyx_v_y = { 0, 0, { 0 }, { 0 }, { 0 } };
  __Pyx_memviewslice __pyx_v_centers = { 0, 0, { 0 }, { 0 }, { 0 } };
  __Pyx_memviewslice __pyx_v_valid_centers = { 0, 0, { 0 }, { 0 }, { 0 } };
  __Pyx_memviewslice __pyx_v_valid_cols = { 0, 0, { 0 }, { 0 }, { 0 } };
  int __pyx_v_njobs;
  #if !CYTHON_METH_FASTCALL
  CYTHON_UNUSED Py_ssize_t __pyx_nargs;
  #endif
  CYTHON_UNUSED PyObject *const *__pyx_kwvalues;
  PyObject *__pyx_r = 0;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("get_all_mistakes (wrapper)", 0);
  #if !CYTHON_METH_FASTCALL
  #if CYTHON_ASSUME_SAFE_MACROS
  __pyx_nargs = PyTuple_GET_SIZE(__pyx_args);
  #else
  __pyx_nargs = PyTuple_Size(__pyx_args); if (unlikely(__pyx_nargs < 0)) return NULL;
  #endif
  #endif
  __pyx_kwvalues = __Pyx_KwValues_FASTCALL(__pyx_args, __pyx_nargs);
  {
    PyObject **__pyx_pyargnames[] = {&__pyx_n_s_X,&__pyx_n_s_y,&__pyx_n_s_centers,&__pyx_n_s_valid_centers,&__pyx_n_s_valid_cols,&__pyx_n_s_njobs,0};
  PyObject* values[6] = {0,0,0,0,0,0};
    if (__pyx_kwds) {
      Py_ssize_t kw_args;
      switch (__pyx_nargs) {
        case  6: values[5] = __Pyx_Arg_FASTCALL(__pyx_args, 5);
        CYTHON_FALLTHROUGH;
        case  5: values[4] = __Pyx_Arg_FASTCALL(__pyx_args, 4);
        CYTHON_FALLTHROUGH;
        case  4: values[3] = __Pyx_Arg_FASTCALL(__pyx_args, 3);
        CYTHON_FALLTHROUGH;
        case  3: values[2] = __Pyx_Arg_FASTCALL(__pyx_args, 2);
        CYTHON_FALLTHROUGH;
        case  2: values[1] = __Pyx_Arg_FASTCALL(__pyx_args, 1);
        CYTHON_FALLTHROUGH;
        case  1: values[0] = __Pyx_Arg_FASTCALL(__pyx_args, 0);
        CYTHON_FALLTHROUGH;
        case  0: break;
        default: goto __pyx_L5_argtuple_error;
      }
      kw_args = __Pyx_NumKwargs_FASTCALL(__pyx_kwds);
      switch (__pyx_nargs) {
        case  0:
        if (likely((values[0] = __Pyx_GetKwValue_FASTCALL(__pyx_kwds, __pyx_kwvalues, __pyx_n_s_X)) != 0)) {
          (void)__Pyx_Arg_NewRef_FASTCALL(values[0]);
          kw_args--;
        }
        else if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 22, __pyx_L3_error)
        else goto __pyx_L5_argtuple_error;
        CYTHON_FALLTHROUGH;
        case  1:
        if (likely((values[1] = __Pyx_GetKwValue_FASTCALL(__pyx_kwds, __pyx_kwvalues, __pyx_n_s_y)) != 0)) {
          (void)__Pyx_Arg_NewRef_FASTCALL(values[1]);
          kw_args--;
        }
        else if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 22, __pyx_L3_error)
        else {
          __Pyx_RaiseArgtupleInvalid("get_all_mistakes", 1, 6, 6, 1); __PYX_ERR(0, 22, __pyx_L3_error)
        }
        CYTHON_FALLTHROUGH;
        case  2:
        if (likely((values[2] = __Pyx_GetKwValue_FASTCALL(__pyx_kwds, __pyx_kwvalues, __pyx_n_s_centers)) != 0)) {
          (void)__Pyx_Arg_NewRef_FASTCALL(values[2]);
          kw_args--;
        }
        else if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 22, __pyx_L3_error)
        else {
          __Pyx_RaiseArgtupleInvalid("get_all_mistakes", 1, 6, 6, 2); __PYX_ERR(0, 22, __pyx_L3_error)
        }
        CYTHON_FALLTHROUGH;
        case  3:
        if (likely((values[3] = __Pyx_GetKwValue_FASTCALL(__pyx_kwds, __pyx_kwvalues, __pyx_n_s_valid_centers)) != 0)) {
          (void)__Pyx_Arg_NewRef_FASTCALL(values[3]);
          kw_args--;
        }
        else if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 22, __pyx_L3_error)
        else {
          __Pyx_RaiseArgtupleInvalid("get_all_mistakes", 1, 6, 6, 3); __PYX_ERR(0, 22, __pyx_L3_error)
        }
        CYTHON_FALLTHROUGH;
        case  4:
        if (likely((values[4] = __Pyx_GetKwValue_FASTCALL(__pyx_kwds, __pyx_kwvalues, __pyx_n_s_valid_cols)) != 0)) {
          (void)__Pyx_Arg_NewRef_FASTCALL(values[4]);
          kw_args--;
        }
        else if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 22, __pyx_L3_error)
        else {
          __Pyx_RaiseArgtupleInvalid("get_all_mistakes", 1, 6, 6, 4); __PYX_ERR(0, 22, __pyx_L3_error)
        }
        CYTHON_FALLTHROUGH;
        case  5:
        if (likely((values[5] = __Pyx_GetKwValue_FASTCALL(__pyx_kwds, __pyx_kwvalues, __pyx_n_s_njobs)) != 0)) {
          (void)__Pyx_Arg_NewRef_FASTCALL(values[5]);
          kw_args--;
        }
        else if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 22, __pyx_L3_error)
        else {
          __Pyx_RaiseArgtupleInvalid("get_all_mistakes", 1, 6, 6, 5); __PYX_ERR(0, 22, __pyx_L3_error)
        }
      }
      if (unlikely(kw_args > 0)) {
        const Py_ssize_t kwd_pos_args = __pyx_nargs;
        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_kwvalues, __pyx_pyargnames, 0, values + 0, kwd_pos_args, "get_all_mistakes") < 0)) __PYX_ERR(0, 22, __pyx_L3_error)
      }
    } else if (unlikely(__pyx_nargs != 6)) {
      goto __pyx_L5_argtuple_error;
    } else {
      values[0] = __Pyx_Arg_FASTCALL(__pyx_args, 0);
      values[1] = __Pyx_Arg_FASTCALL(__pyx_args, 1);
      values[2] = __Pyx_Arg_FASTCALL(__pyx_args, 2);
      values[3] = __Pyx_Arg_FASTCALL(__pyx_args, 3);
      values[4] = __Pyx_Arg_FASTCALL(__pyx_args, 4);
      values[5] = __Pyx_Arg_FASTCALL(__pyx_args, 5);
    }
    __pyx_v_X = __Pyx_PyObject_to_MemoryviewSlice_dsds_nn___pyx_t_5d_imm_9splitters_10cut_finder_NP_FLOAT_t(values[0], PyBUF_WRITABLE); if (unlikely(!__pyx_v_X.memview)) __PYX_ERR(0, 25, __pyx_L3_error)
    __pyx_v_y = __Pyx_PyObject_to_MemoryviewSlice_ds_nn___pyx_t_5d_imm_9splitters_10cut_finder_NP_INT_t(values[1], PyBUF_WRITABLE); if (unlikely(!__pyx_v_y.memview)) __PYX_ERR(0, 25, __pyx_L3_error)
    __pyx_v_centers = __Pyx_PyObject_to_MemoryviewSlice_dsds_nn___pyx_t_5d_imm_9splitters_10cut_finder_NP_FLOAT_t(values[2], PyBUF_WRITABLE); if (unlikely(!__pyx_v_centers.memview)) __PYX_ERR(0, 25, __pyx_L3_error)
    __pyx_v_valid_centers = __Pyx_PyObject_to_MemoryviewSlice_ds_nn___pyx_t_5d_imm_9splitters_10cut_finder_NP_INT_t(values[3], PyBUF_WRITABLE); if (unlikely(!__pyx_v_valid_centers.memview)) __PYX_ERR(0, 26, __pyx_L3_error)
    __pyx_v_valid_cols = __Pyx_PyObject_to_MemoryviewSlice_ds_nn___pyx_t_5d_imm_9splitters_10cut_finder_NP_INT_t(values[4], PyBUF_WRITABLE); if (unlikely(!__pyx_v_valid_cols.memview)) __PYX_ERR(0, 26, __pyx_L3_error)
    __pyx_v_njobs = __Pyx_PyInt_As_int(values[5]); if (unlikely((__pyx_v_njobs == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 26, __pyx_L3_error)
  }
  goto __pyx_L6_skip;
  __pyx_L5_argtuple_error:;
  __Pyx_RaiseArgtupleInvalid("get_all_mistakes", 1, 6, 6, __pyx_nargs); __PYX_ERR(0, 22, __pyx_L3_error)
  __pyx_L6_skip:;
  goto __pyx_L4_argument_unpacking_done;
  __pyx_L3_error:;
  {
    Py_ssize_t __pyx_temp;
    for (__pyx_temp=0; __pyx_temp < (Py_ssize_t)(sizeof(values)/sizeof(values[0])); ++__pyx_temp) {
      __Pyx_Arg_XDECREF_FASTCALL(values[__pyx_temp]);
    }
  }
  __PYX_XCLEAR_MEMVIEW(&__pyx_v_X, 1);
  __PYX_XCLEAR_MEMVIEW(&__pyx_v_y, 1);
  __PYX_XCLEAR_MEMVIEW(&__pyx_v_centers, 1);
  __PYX_XCLEAR_MEMVIEW(&__pyx_v_valid_centers, 1);
  __PYX_XCLEAR_MEMVIEW(&__pyx_v_valid_cols, 1);
  __Pyx_AddTraceback("d_imm.splitters.cut_finder.get_all_mistakes", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __Pyx_RefNannyFinishContext();
  return NULL;
  __pyx_L4_argument_unpacking_done:;
  __pyx_r = __pyx_pf_5d_imm_9splitters_10cut_finder_get_all_mistakes(__pyx_self, __pyx_v_X, __pyx_v_y, __pyx_v_centers, __pyx_v_valid_centers, __pyx_v_valid_cols, __pyx_v_njobs);
  int __pyx_lineno = 0;
  const char *__pyx_filename = NULL;
  int __pyx_clineno = 0;

  /* function exit code */
  __PYX_XCLEAR_MEMVIEW(&__pyx_v_X, 1);
  __PYX_XCLEAR_MEMVIEW(&__pyx_v_y, 1);
  __PYX_XCLEAR_MEMVIEW(&__pyx_v_centers, 1);
  __PYX_XCLEAR_MEMVIEW(&__pyx_v_valid_centers, 1);
  __PYX_XCLEAR_MEMVIEW(&__pyx_v_valid_cols, 1);
  {
    Py_ssize_t __pyx_temp;
    for (__pyx_temp=0; __pyx_temp < (Py_ssize_t)(sizeof(values)/sizeof(values[0])); ++__pyx_temp) {
      __Pyx_Arg_XDECREF_FASTCALL(values[__pyx_temp]);
    }
  }
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}

static PyObject *__pyx_pf_5d_imm_9splitters_10cut_finder_get_all_mistakes(CYTHON_UNUSED PyObject *__pyx_self, __Pyx_memviewslice __pyx_v_X, __Pyx_memviewslice __pyx_v_y, __Pyx_memviewslice __pyx_v_centers, __Pyx_memviewslice __pyx_v_valid_centers, __Pyx_memviewslice __pyx_v_valid_cols, int __pyx_v_njobs) {
  int __pyx_v_n;
  int __pyx_v_k;
  int __pyx_v_d;
  int *__pyx_v_centers_count;
  PyObject *__pyx_v_feature_results = 0;
  int __pyx_v_col;
  int __pyx_v_i;
  PyObject *__pyx_r = NULL;
/* … */
  /* function exit code */
  __pyx_L1_error:;
  __Pyx_XDECREF(__pyx_t_1);
  __Pyx_AddTraceback("d_imm.splitters.cut_finder.get_all_mistakes", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __pyx_r = NULL;
  __pyx_L0:;
  __Pyx_XDECREF(__pyx_v_feature_results);
  __Pyx_XGIVEREF(__pyx_r);
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}
/* … */
  __pyx_tuple__23 = PyTuple_Pack(13, __pyx_n_s_X, __pyx_n_s_y, __pyx_n_s_centers, __pyx_n_s_valid_centers, __pyx_n_s_valid_cols, __pyx_n_s_njobs, __pyx_n_s_n, __pyx_n_s_k, __pyx_n_s_d, __pyx_n_s_centers_count, __pyx_n_s_feature_results, __pyx_n_s_col, __pyx_n_s_i); if (unlikely(!__pyx_tuple__23)) __PYX_ERR(0, 22, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_tuple__23);
  __Pyx_GIVEREF(__pyx_tuple__23);
/* … */
  __pyx_t_7 = __Pyx_CyFunction_New(&__pyx_mdef_5d_imm_9splitters_10cut_finder_1get_all_mistakes, 0, __pyx_n_s_get_all_mistakes, NULL, __pyx_n_s_d_imm_splitters_cut_finder, __pyx_d, ((PyObject *)__pyx_codeobj__24)); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 22, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_7);
  if (PyDict_SetItem(__pyx_d, __pyx_n_s_get_all_mistakes, __pyx_t_7) < 0) __PYX_ERR(0, 22, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
  __pyx_codeobj__24 = (PyObject*)__Pyx_PyCode_New(6, 0, 0, 13, 0, CO_OPTIMIZED|CO_NEWLOCALS, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__23, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_d_imm_splitters_cut_finder_pyx, __pyx_n_s_get_all_mistakes, 22, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__24)) __PYX_ERR(0, 22, __pyx_L1_error)
 023: @cython.wraparound(False)
 024: def get_all_mistakes(
 025:     NP_FLOAT_t[:,:] X, NP_INT_t[:] y, NP_FLOAT_t[:,:] centers,
 026:     NP_INT_t[:] valid_centers, NP_INT_t[:] valid_cols, int njobs
 027: ):
 028:     """
 029:     Main function to calculate mistakes for all features and thresholds.
 030:     Returns a list of Python dictionaries with 'feature', 'threshold', and 'mistakes'.
 031:     """
+032:     cdef int n = X.shape[0]
  __pyx_v_n = (__pyx_v_X.shape[0]);
+033:     cdef int k = centers.shape[0]
  __pyx_v_k = (__pyx_v_centers.shape[0]);
+034:     cdef int d = valid_cols.shape[0]
  __pyx_v_d = (__pyx_v_valid_cols.shape[0]);
+035:     cdef int *centers_count = <int *> malloc(k * sizeof(int))
  __pyx_v_centers_count = ((int *)malloc((__pyx_v_k * (sizeof(int)))));
+036:     cdef list feature_results = []
  __pyx_t_1 = PyList_New(0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 36, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_v_feature_results = ((PyObject*)__pyx_t_1);
  __pyx_t_1 = 0;
 037:     cdef int col
 038: 
 039:     # Initialize center counts
+040:     for i in range(k):
  __pyx_t_2 = __pyx_v_k;
  __pyx_t_3 = __pyx_t_2;
  for (__pyx_t_4 = 0; __pyx_t_4 < __pyx_t_3; __pyx_t_4+=1) {
    __pyx_v_i = __pyx_t_4;
+041:         centers_count[i] = 0
    (__pyx_v_centers_count[__pyx_v_i]) = 0;
  }
+042:     for i in range(n):
  __pyx_t_2 = __pyx_v_n;
  __pyx_t_3 = __pyx_t_2;
  for (__pyx_t_4 = 0; __pyx_t_4 < __pyx_t_3; __pyx_t_4+=1) {
    __pyx_v_i = __pyx_t_4;
+043:         centers_count[y[i]] += 1
    __pyx_t_5 = __pyx_v_i;
    __pyx_t_6 = (*((__pyx_t_5d_imm_9splitters_10cut_finder_NP_INT_t *) ( /* dim=0 */ (__pyx_v_y.data + __pyx_t_5 * __pyx_v_y.strides[0]) )));
    (__pyx_v_centers_count[__pyx_t_6]) = ((__pyx_v_centers_count[__pyx_t_6]) + 1);
  }
 044: 
+045:     if njobs is None or njobs <= 1:
  __pyx_t_1 = __Pyx_PyInt_From_int(__pyx_v_njobs); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 45, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_8 = (__pyx_t_1 == Py_None);
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  if (!__pyx_t_8) {
  } else {
    __pyx_t_7 = __pyx_t_8;
    goto __pyx_L8_bool_binop_done;
  }
  __pyx_t_8 = (__pyx_v_njobs <= 1);
  __pyx_t_7 = __pyx_t_8;
  __pyx_L8_bool_binop_done:;
  if (__pyx_t_7) {
/* … */
    goto __pyx_L7;
  }
 046:         # Iterate over valid columns
+047:         for col in range(d):
    __pyx_t_2 = __pyx_v_d;
    __pyx_t_3 = __pyx_t_2;
    for (__pyx_t_4 = 0; __pyx_t_4 < __pyx_t_3; __pyx_t_4+=1) {
      __pyx_v_col = __pyx_t_4;
+048:             if valid_cols[col] == 1:
      __pyx_t_5 = __pyx_v_col;
      __pyx_t_7 = ((*((__pyx_t_5d_imm_9splitters_10cut_finder_NP_INT_t *) ( /* dim=0 */ (__pyx_v_valid_cols.data + __pyx_t_5 * __pyx_v_valid_cols.strides[0]) ))) == 1);
      if (__pyx_t_7) {
/* … */
      }
    }
+049:                 update_col_all_mistakes(
        __pyx_f_5d_imm_9splitters_10cut_finder_update_col_all_mistakes(__pyx_v_X, __pyx_v_y, __pyx_v_centers, __pyx_v_valid_centers, __pyx_v_centers_count, __pyx_v_col, __pyx_v_n, __pyx_v_k, __pyx_v_feature_results); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 49, __pyx_L1_error)
 050:                     X, y, centers, valid_centers, centers_count,
 051:                     col, n, k, feature_results
 052:                 )
 053:     else:
 054:         # Parallelize the process
+055:         for col in prange(d, nogil=True, num_threads=njobs):
  /*else*/ {
    {
        #ifdef WITH_THREAD
        PyThreadState *_save;
        _save = NULL;
        Py_UNBLOCK_THREADS
        __Pyx_FastGIL_Remember();
        #endif
        /*try:*/ {
          __pyx_t_2 = __pyx_v_d;
          {
              #if ((defined(__APPLE__) || defined(__OSX__)) && (defined(__GNUC__) && (__GNUC__ > 2 || (__GNUC__ == 2 && (__GNUC_MINOR__ > 95)))))
                  #undef likely
                  #undef unlikely
                  #define likely(x)   (x)
                  #define unlikely(x) (x)
              #endif
              __pyx_t_4 = (__pyx_t_2 - 0 + 1 - 1/abs(1)) / 1;
              if (__pyx_t_4 > 0)
              {
                  #ifdef _OPENMP
                  #pragma omp parallel
                  #endif /* _OPENMP */
                  {
                      #ifdef _OPENMP
                      #pragma omp for firstprivate(__pyx_v_col) lastprivate(__pyx_v_col)          __pyx_t_2 = __pyx_v_d;
          {
              #if ((defined(__APPLE__) || defined(__OSX__)) && (defined(__GNUC__) && (__GNUC__ > 2 || (__GNUC__ == 2 && (__GNUC_MINOR__ > 95)))))
                  #undef likely
                  #undef unlikely
                  #define likely(x)   (x)
                  #define unlikely(x) (x)
              #endif
              __pyx_t_4 = (__pyx_t_2 - 0 + 1 - 1/abs(1)) / 1;
              if (__pyx_t_4 > 0)
              {
                  #ifdef _OPENMP
                  #pragma omp parallel
                  #endif /* _OPENMP */
                  {
                      #ifdef _OPENMP
                      #pragma omp for firstprivate(__pyx_v_col) lastprivate(__pyx_v_col) num_threads(__pyx_v_njobs)
                      #endif /* _OPENMP */
                      for (__pyx_t_3 = 0; __pyx_t_3 < __pyx_t_4; __pyx_t_3++){
                          {
                              __pyx_v_col = (int)(0 + 1 * __pyx_t_3);
/* … */
        /*finally:*/ {
          /*normal exit:*/{
            #ifdef WITH_THREAD
            __Pyx_FastGIL_Forget();
            Py_BLOCK_THREADS
            #endif
            goto __pyx_L15;
          }
          __pyx_L14_error: {
            #ifdef WITH_THREAD
            __Pyx_FastGIL_Forget();
            Py_BLOCK_THREADS
            #endif
            goto __pyx_L1_error;
          }
          __pyx_L15:;
        }
    }
  }
  __pyx_L7:;
+056:             if valid_cols[col] == 1:
                              __pyx_t_5 = __pyx_v_col;
                              __pyx_t_7 = ((*((__pyx_t_5d_imm_9splitters_10cut_finder_NP_INT_t *) ( /* dim=0 */ (__pyx_v_valid_cols.data + __pyx_t_5 * __pyx_v_valid_cols.strides[0]) ))) == 1);
                              if (__pyx_t_7) {
/* … */
                              }
                              goto __pyx_L22;
                              __pyx_L18_error:;
                              {
                                  #ifdef WITH_THREAD
                                  PyGILState_STATE __pyx_gilstate_save = __Pyx_PyGILState_Ensure();
                                  #endif
                                  #ifdef _OPENMP
                                  #pragma omp flush(__pyx_parallel_exc_type)
                                  #endif /* _OPENMP */
                                  if (!__pyx_parallel_exc_type) {
                                    __Pyx_ErrFetchWithState(&__pyx_parallel_exc_type, &__pyx_parallel_exc_value, &__pyx_parallel_exc_tb);
                                    __pyx_parallel_filename = __pyx_filename; __pyx_parallel_lineno = __pyx_lineno; __pyx_parallel_clineno = __pyx_clineno;
                                    __Pyx_GOTREF(__pyx_parallel_exc_type);
                                  }
                                  #ifdef WITH_THREAD
                                  __Pyx_PyGILState_Release(__pyx_gilstate_save);
                                  #endif
                              }
                              __pyx_parallel_why = 4;
                              goto __pyx_L21;
                              __pyx_L21:;
                              #ifdef _OPENMP
                              #pragma omp critical(__pyx_parallel_lastprivates0)
                              #endif /* _OPENMP */
                              {
                                  __pyx_parallel_temp0 = __pyx_v_col;
                              }
                              __pyx_L22:;
                              #ifdef _OPENMP
                              #pragma omp flush(__pyx_parallel_why)
                              #endif /* _OPENMP */
                          }
                      }
                      #ifdef _OPENMP
                      Py_END_ALLOW_THREADS
                      #else
{
#ifdef WITH_THREAD
                      PyGILState_STATE __pyx_gilstate_save = __Pyx_PyGILState_Ensure();
                      #endif
                      #endif /* _OPENMP */
                      /* Clean up any temporaries */
                      #ifdef WITH_THREAD
                      __Pyx_PyGILState_Release(__pyx_gilstate_save);
                      #endif
                      #ifndef _OPENMP
}
#endif /* _OPENMP */
                  }
              }
              if (__pyx_parallel_exc_type) {
                /* This may have been overridden by a continue, break or return in another thread. Prefer the error. */
                __pyx_parallel_why = 4;
              }
              if (__pyx_parallel_why) {
                __pyx_v_col = __pyx_parallel_temp0;
                switch (__pyx_parallel_why) {
                      case 4:
                  {
                      #ifdef WITH_THREAD
                      PyGILState_STATE __pyx_gilstate_save = __Pyx_PyGILState_Ensure();
                      #endif
                      __Pyx_GIVEREF(__pyx_parallel_exc_type);
                      __Pyx_ErrRestoreWithState(__pyx_parallel_exc_type, __pyx_parallel_exc_value, __pyx_parallel_exc_tb);
                      __pyx_filename = __pyx_parallel_filename; __pyx_lineno = __pyx_parallel_lineno; __pyx_clineno = __pyx_parallel_clineno;
                      #ifdef WITH_THREAD
                      __Pyx_PyGILState_Release(__pyx_gilstate_save);
                      #endif
                  }
                  goto __pyx_L14_error;
                }
              }
          }
          #if ((defined(__APPLE__) || defined(__OSX__)) && (defined(__GNUC__) && (__GNUC__ > 2 || (__GNUC__ == 2 && (__GNUC_MINOR__ > 95)))))
              #undef likely
              #undef unlikely
              #define likely(x)   __builtin_expect(!!(x), 1)
              #define unlikely(x) __builtin_expect(!!(x), 0)
          #endif
        }
+057:                 update_col_all_mistakes(
                                __pyx_f_5d_imm_9splitters_10cut_finder_update_col_all_mistakes(__pyx_v_X, __pyx_v_y, __pyx_v_centers, __pyx_v_valid_centers, __pyx_v_centers_count, __pyx_v_col, __pyx_v_n, __pyx_v_k, __pyx_v_feature_results); if (unlikely(__Pyx_ErrOccurredWithGIL())) __PYX_ERR(0, 57, __pyx_L18_error)
 058:                     X, y, centers, valid_centers, centers_count,
 059:                     col, n, k, feature_results
 060:                 )
 061: 
+062:     free(centers_count)
  free(__pyx_v_centers_count);
+063:     return feature_results
  __Pyx_XDECREF(__pyx_r);
  __Pyx_INCREF(__pyx_v_feature_results);
  __pyx_r = __pyx_v_feature_results;
  goto __pyx_L0;
 064: 
 065: 
 066: @cython.boundscheck(False)
 067: @cython.wraparound(False)
+068: cdef void update_col_all_mistakes(
static void __pyx_f_5d_imm_9splitters_10cut_finder_update_col_all_mistakes(__Pyx_memviewslice __pyx_v_X, __Pyx_memviewslice __pyx_v_y, __Pyx_memviewslice __pyx_v_centers, __Pyx_memviewslice __pyx_v_valid_centers, int *__pyx_v_centers_count, int __pyx_v_col, int __pyx_v_n, int __pyx_v_k, PyObject *__pyx_v_feature_results) {
  int __pyx_v_i;
  int __pyx_v_ix;
  int __pyx_v_ic;
  int __pyx_v_mistakes;
  __pyx_t_5d_imm_9splitters_10cut_finder_NP_FLOAT_t __pyx_v_prev_threshold;
  __pyx_t_5d_imm_9splitters_10cut_finder_NP_FLOAT_t __pyx_v_threshold;
  __pyx_t_5d_imm_9splitters_10cut_finder_NP_FLOAT_t __pyx_v_max_val;
  __Pyx_memviewslice __pyx_v_data_order = { 0, 0, { 0 }, { 0 }, { 0 } };
  __Pyx_memviewslice __pyx_v_centers_order = { 0, 0, { 0 }, { 0 }, { 0 } };
  int *__pyx_v_left_centers_count;
  int __pyx_v_curr_center_idx;
  int __pyx_v_is_center_threshold;
/* … */
  /* function exit code */
  goto __pyx_L0;
  __pyx_L1_error:;
  #ifdef WITH_THREAD
  __pyx_gilstate_save = __Pyx_PyGILState_Ensure();
  #endif
  __Pyx_XDECREF(__pyx_t_1);
  __Pyx_XDECREF(__pyx_t_2);
  __Pyx_XDECREF(__pyx_t_3);
  __Pyx_XDECREF(__pyx_t_4);
  __PYX_XCLEAR_MEMVIEW(&__pyx_t_5, 1);
  __Pyx_XDECREF(__pyx_t_6);
  __PYX_XCLEAR_MEMVIEW(&__pyx_t_8, 1);
  __Pyx_AddTraceback("d_imm.splitters.cut_finder.update_col_all_mistakes", __pyx_clineno, __pyx_lineno, __pyx_filename);
  #ifdef WITH_THREAD
  __Pyx_PyGILState_Release(__pyx_gilstate_save);
  #endif
  __pyx_L0:;
  __PYX_XCLEAR_MEMVIEW(&__pyx_v_data_order, 0);
  __PYX_XCLEAR_MEMVIEW(&__pyx_v_centers_order, 0);
  __Pyx_RefNannyFinishContextNogil()
}
 069:     NP_FLOAT_t[:,:] X, NP_INT_t[:] y, NP_FLOAT_t[:,:] centers,
 070:     NP_INT_t[:] valid_centers, int* centers_count,
 071:     int col, int n, int k,
 072:     list feature_results) nogil:
 073:     """
 074:     Helper function to calculate mistakes for a single column.
 075:     Appends the results as Python dictionaries to `feature_results`.
 076:     """
 077:     cdef int i
 078:     cdef int ix
 079:     cdef int ic
 080:     cdef int mistakes
 081:     cdef NP_FLOAT_t prev_threshold
 082:     cdef NP_FLOAT_t threshold
 083:     cdef NP_FLOAT_t max_val
 084:     cdef np.int64_t[:] data_order
 085:     cdef np.int64_t[:] centers_order
+086:     cdef int *left_centers_count = <int *> malloc(k * sizeof(int))
  __pyx_v_left_centers_count = ((int *)malloc((__pyx_v_k * (sizeof(int)))));
 087:     cdef int curr_center_idx
 088:     cdef bint is_center_threshold
 089: 
 090:     # Sort data points and centers
+091:     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_L5;
        }
        __pyx_L4_error: {
          #ifdef WITH_THREAD
          __Pyx_PyGILState_Release(__pyx_gilstate_save);
          #endif
          goto __pyx_L1_error;
        }
        __pyx_L5:;
      }
  }
+092:         data_order = np.asarray(X[:, col]).argsort()
        __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_n_s_np); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 92, __pyx_L4_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, 92, __pyx_L4_error)
        __Pyx_GOTREF(__pyx_t_4);
        __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
        __pyx_t_5.data = __pyx_v_X.data;
        __pyx_t_5.memview = __pyx_v_X.memview;
        __PYX_INC_MEMVIEW(&__pyx_t_5, 1);
        __pyx_t_5.shape[0] = __pyx_v_X.shape[0];
__pyx_t_5.strides[0] = __pyx_v_X.strides[0];
    __pyx_t_5.suboffsets[0] = -1;

{
    Py_ssize_t __pyx_tmp_idx = __pyx_v_col;
    Py_ssize_t __pyx_tmp_stride = __pyx_v_X.strides[1];
        __pyx_t_5.data += __pyx_tmp_idx * __pyx_tmp_stride;
}

__pyx_t_3 = __pyx_memoryview_fromslice(__pyx_t_5, 1, (PyObject *(*)(char *)) __pyx_memview_get_nn___pyx_t_5d_imm_9splitters_10cut_finder_NP_FLOAT_t, (int (*)(char *, PyObject *)) __pyx_memview_set_nn___pyx_t_5d_imm_9splitters_10cut_finder_NP_FLOAT_t, 0);; if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 92, __pyx_L4_error)
        __Pyx_GOTREF(__pyx_t_3);
        __PYX_XCLEAR_MEMVIEW(&__pyx_t_5, 1);
        __pyx_t_5.memview = NULL; __pyx_t_5.data = NULL;
        __pyx_t_6 = NULL;
        __pyx_t_7 = 0;
        #if CYTHON_UNPACK_METHODS
        if (unlikely(PyMethod_Check(__pyx_t_4))) {
          __pyx_t_6 = PyMethod_GET_SELF(__pyx_t_4);
          if (likely(__pyx_t_6)) {
            PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_4);
            __Pyx_INCREF(__pyx_t_6);
            __Pyx_INCREF(function);
            __Pyx_DECREF_SET(__pyx_t_4, function);
            __pyx_t_7 = 1;
          }
        }
        #endif
        {
          PyObject *__pyx_callargs[2] = {__pyx_t_6, __pyx_t_3};
          __pyx_t_2 = __Pyx_PyObject_FastCall(__pyx_t_4, __pyx_callargs+1-__pyx_t_7, 1+__pyx_t_7);
          __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
          __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
          if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 92, __pyx_L4_error)
          __Pyx_GOTREF(__pyx_t_2);
          __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
        }
        __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_argsort); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 92, __pyx_L4_error)
        __Pyx_GOTREF(__pyx_t_4);
        __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
        __pyx_t_2 = NULL;
        __pyx_t_7 = 0;
        #if CYTHON_UNPACK_METHODS
        if (likely(PyMethod_Check(__pyx_t_4))) {
          __pyx_t_2 = PyMethod_GET_SELF(__pyx_t_4);
          if (likely(__pyx_t_2)) {
            PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_4);
            __Pyx_INCREF(__pyx_t_2);
            __Pyx_INCREF(function);
            __Pyx_DECREF_SET(__pyx_t_4, function);
            __pyx_t_7 = 1;
          }
        }
        #endif
        {
          PyObject *__pyx_callargs[2] = {__pyx_t_2, NULL};
          __pyx_t_1 = __Pyx_PyObject_FastCall(__pyx_t_4, __pyx_callargs+1-__pyx_t_7, 0+__pyx_t_7);
          __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
          if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 92, __pyx_L4_error)
          __Pyx_GOTREF(__pyx_t_1);
          __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
        }
        __pyx_t_8 = __Pyx_PyObject_to_MemoryviewSlice_ds_nn___pyx_t_5numpy_int64_t(__pyx_t_1, PyBUF_WRITABLE); if (unlikely(!__pyx_t_8.memview)) __PYX_ERR(0, 92, __pyx_L4_error)
        __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
        __pyx_v_data_order = __pyx_t_8;
        __pyx_t_8.memview = NULL;
        __pyx_t_8.data = NULL;
+093:         centers_order = np.asarray(centers[:, col]).argsort()
        __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_np); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 93, __pyx_L4_error)
        __Pyx_GOTREF(__pyx_t_2);
        __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_asarray); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 93, __pyx_L4_error)
        __Pyx_GOTREF(__pyx_t_3);
        __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
        __pyx_t_5.data = __pyx_v_centers.data;
        __pyx_t_5.memview = __pyx_v_centers.memview;
        __PYX_INC_MEMVIEW(&__pyx_t_5, 1);
        __pyx_t_5.shape[0] = __pyx_v_centers.shape[0];
__pyx_t_5.strides[0] = __pyx_v_centers.strides[0];
    __pyx_t_5.suboffsets[0] = -1;

{
    Py_ssize_t __pyx_tmp_idx = __pyx_v_col;
    Py_ssize_t __pyx_tmp_stride = __pyx_v_centers.strides[1];
        __pyx_t_5.data += __pyx_tmp_idx * __pyx_tmp_stride;
}

__pyx_t_2 = __pyx_memoryview_fromslice(__pyx_t_5, 1, (PyObject *(*)(char *)) __pyx_memview_get_nn___pyx_t_5d_imm_9splitters_10cut_finder_NP_FLOAT_t, (int (*)(char *, PyObject *)) __pyx_memview_set_nn___pyx_t_5d_imm_9splitters_10cut_finder_NP_FLOAT_t, 0);; if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 93, __pyx_L4_error)
        __Pyx_GOTREF(__pyx_t_2);
        __PYX_XCLEAR_MEMVIEW(&__pyx_t_5, 1);
        __pyx_t_5.memview = NULL; __pyx_t_5.data = NULL;
        __pyx_t_6 = NULL;
        __pyx_t_7 = 0;
        #if CYTHON_UNPACK_METHODS
        if (unlikely(PyMethod_Check(__pyx_t_3))) {
          __pyx_t_6 = PyMethod_GET_SELF(__pyx_t_3);
          if (likely(__pyx_t_6)) {
            PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
            __Pyx_INCREF(__pyx_t_6);
            __Pyx_INCREF(function);
            __Pyx_DECREF_SET(__pyx_t_3, function);
            __pyx_t_7 = 1;
          }
        }
        #endif
        {
          PyObject *__pyx_callargs[2] = {__pyx_t_6, __pyx_t_2};
          __pyx_t_4 = __Pyx_PyObject_FastCall(__pyx_t_3, __pyx_callargs+1-__pyx_t_7, 1+__pyx_t_7);
          __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
          __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
          if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 93, __pyx_L4_error)
          __Pyx_GOTREF(__pyx_t_4);
          __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
        }
        __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_t_4, __pyx_n_s_argsort); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 93, __pyx_L4_error)
        __Pyx_GOTREF(__pyx_t_3);
        __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
        __pyx_t_4 = NULL;
        __pyx_t_7 = 0;
        #if CYTHON_UNPACK_METHODS
        if (likely(PyMethod_Check(__pyx_t_3))) {
          __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
          if (likely(__pyx_t_4)) {
            PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
            __Pyx_INCREF(__pyx_t_4);
            __Pyx_INCREF(function);
            __Pyx_DECREF_SET(__pyx_t_3, function);
            __pyx_t_7 = 1;
          }
        }
        #endif
        {
          PyObject *__pyx_callargs[2] = {__pyx_t_4, NULL};
          __pyx_t_1 = __Pyx_PyObject_FastCall(__pyx_t_3, __pyx_callargs+1-__pyx_t_7, 0+__pyx_t_7);
          __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
          if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 93, __pyx_L4_error)
          __Pyx_GOTREF(__pyx_t_1);
          __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
        }
        __pyx_t_8 = __Pyx_PyObject_to_MemoryviewSlice_ds_nn___pyx_t_5numpy_int64_t(__pyx_t_1, PyBUF_WRITABLE); if (unlikely(!__pyx_t_8.memview)) __PYX_ERR(0, 93, __pyx_L4_error)
        __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
        __pyx_v_centers_order = __pyx_t_8;
        __pyx_t_8.memview = NULL;
        __pyx_t_8.data = NULL;
      }
 094: 
 095:     # Find the maximum valid center value
+096:     max_val = -INFINITY
  __pyx_v_max_val = (-INFINITY);
+097:     for i in range(k):
  __pyx_t_9 = __pyx_v_k;
  __pyx_t_10 = __pyx_t_9;
  for (__pyx_t_11 = 0; __pyx_t_11 < __pyx_t_10; __pyx_t_11+=1) {
    __pyx_v_i = __pyx_t_11;
+098:         if valid_centers[i] == 1:
    __pyx_t_12 = __pyx_v_i;
    __pyx_t_13 = ((*((__pyx_t_5d_imm_9splitters_10cut_finder_NP_INT_t *) ( /* dim=0 */ (__pyx_v_valid_centers.data + __pyx_t_12 * __pyx_v_valid_centers.strides[0]) ))) == 1);
    if (__pyx_t_13) {
/* … */
    }
  }
+099:             if centers[i, col] > max_val:
      __pyx_t_12 = __pyx_v_i;
      __pyx_t_14 = __pyx_v_col;
      __pyx_t_13 = ((*((__pyx_t_5d_imm_9splitters_10cut_finder_NP_FLOAT_t *) ( /* dim=1 */ (( /* dim=0 */ (__pyx_v_centers.data + __pyx_t_12 * __pyx_v_centers.strides[0]) ) + __pyx_t_14 * __pyx_v_centers.strides[1]) ))) > __pyx_v_max_val);
      if (__pyx_t_13) {
/* … */
      }
+100:                 max_val = centers[i, col]
        __pyx_t_14 = __pyx_v_i;
        __pyx_t_12 = __pyx_v_col;
        __pyx_v_max_val = (*((__pyx_t_5d_imm_9splitters_10cut_finder_NP_FLOAT_t *) ( /* dim=1 */ (( /* dim=0 */ (__pyx_v_centers.data + __pyx_t_14 * __pyx_v_centers.strides[0]) ) + __pyx_t_12 * __pyx_v_centers.strides[1]) )));
 101: 
 102:     # Initialize mistakes and left_centers_count
+103:     for i in range(k):
  __pyx_t_9 = __pyx_v_k;
  __pyx_t_10 = __pyx_t_9;
  for (__pyx_t_11 = 0; __pyx_t_11 < __pyx_t_10; __pyx_t_11+=1) {
    __pyx_v_i = __pyx_t_11;
+104:         left_centers_count[i] = 0
    (__pyx_v_left_centers_count[__pyx_v_i]) = 0;
  }
 105: 
+106:     ix = 0
  __pyx_v_ix = 0;
+107:     ic = 0
  __pyx_v_ic = 0;
+108:     mistakes = 0
  __pyx_v_mistakes = 0;
 109: 
 110:     # Advance center index to the first valid one
+111:     while ic < k and valid_centers[centers_order[ic]] == 0:
  while (1) {
    __pyx_t_15 = (__pyx_v_ic < __pyx_v_k);
    if (__pyx_t_15) {
    } else {
      __pyx_t_13 = __pyx_t_15;
      goto __pyx_L14_bool_binop_done;
    }
    __pyx_t_12 = __pyx_v_ic;
    __pyx_t_16 = (*((__pyx_t_5numpy_int64_t *) ( /* dim=0 */ (__pyx_v_centers_order.data + __pyx_t_12 * __pyx_v_centers_order.strides[0]) )));
    __pyx_t_15 = ((*((__pyx_t_5d_imm_9splitters_10cut_finder_NP_INT_t *) ( /* dim=0 */ (__pyx_v_valid_centers.data + __pyx_t_16 * __pyx_v_valid_centers.strides[0]) ))) == 0);
    __pyx_t_13 = __pyx_t_15;
    __pyx_L14_bool_binop_done:;
    if (!__pyx_t_13) break;
+112:         ic += 1
    __pyx_v_ic = (__pyx_v_ic + 1);
  }
 113: 
 114:     # Handle the case where there are no valid centers
+115:     if ic >= k:
  __pyx_t_13 = (__pyx_v_ic >= __pyx_v_k);
  if (__pyx_t_13) {
/* … */
  }
+116:         free(left_centers_count)
    free(__pyx_v_left_centers_count);
+117:         return
    goto __pyx_L0;
 118: 
 119:     # The first threshold
+120:     threshold = centers[centers_order[ic], col]
  __pyx_t_12 = __pyx_v_ic;
  __pyx_t_16 = (*((__pyx_t_5numpy_int64_t *) ( /* dim=0 */ (__pyx_v_centers_order.data + __pyx_t_12 * __pyx_v_centers_order.strides[0]) )));
  __pyx_t_14 = __pyx_v_col;
  __pyx_v_threshold = (*((__pyx_t_5d_imm_9splitters_10cut_finder_NP_FLOAT_t *) ( /* dim=1 */ (( /* dim=0 */ (__pyx_v_centers.data + __pyx_t_16 * __pyx_v_centers.strides[0]) ) + __pyx_t_14 * __pyx_v_centers.strides[1]) )));
+121:     is_center_threshold = 1
  __pyx_v_is_center_threshold = 1;
 122: 
 123:     # Initialize mistakes and left-centers-counts for the first threshold
+124:     while ix < n and X[data_order[ix], col] <= threshold:
  while (1) {
    __pyx_t_15 = (__pyx_v_ix < __pyx_v_n);
    if (__pyx_t_15) {
    } else {
      __pyx_t_13 = __pyx_t_15;
      goto __pyx_L19_bool_binop_done;
    }
    __pyx_t_12 = __pyx_v_ix;
    __pyx_t_16 = (*((__pyx_t_5numpy_int64_t *) ( /* dim=0 */ (__pyx_v_data_order.data + __pyx_t_12 * __pyx_v_data_order.strides[0]) )));
    __pyx_t_14 = __pyx_v_col;
    __pyx_t_15 = ((*((__pyx_t_5d_imm_9splitters_10cut_finder_NP_FLOAT_t *) ( /* dim=1 */ (( /* dim=0 */ (__pyx_v_X.data + __pyx_t_16 * __pyx_v_X.strides[0]) ) + __pyx_t_14 * __pyx_v_X.strides[1]) ))) <= __pyx_v_threshold);
    __pyx_t_13 = __pyx_t_15;
    __pyx_L19_bool_binop_done:;
    if (!__pyx_t_13) break;
+125:         curr_center_idx = y[data_order[ix]]  # Center of the current data point
    __pyx_t_12 = __pyx_v_ix;
    __pyx_t_16 = (*((__pyx_t_5numpy_int64_t *) ( /* dim=0 */ (__pyx_v_data_order.data + __pyx_t_12 * __pyx_v_data_order.strides[0]) )));
    __pyx_v_curr_center_idx = (*((__pyx_t_5d_imm_9splitters_10cut_finder_NP_INT_t *) ( /* dim=0 */ (__pyx_v_y.data + __pyx_t_16 * __pyx_v_y.strides[0]) )));
+126:         left_centers_count[curr_center_idx] += 1
    __pyx_t_9 = __pyx_v_curr_center_idx;
    (__pyx_v_left_centers_count[__pyx_t_9]) = ((__pyx_v_left_centers_count[__pyx_t_9]) + 1);
+127:         if centers[curr_center_idx, col] >= threshold:
    __pyx_t_12 = __pyx_v_curr_center_idx;
    __pyx_t_14 = __pyx_v_col;
    __pyx_t_13 = ((*((__pyx_t_5d_imm_9splitters_10cut_finder_NP_FLOAT_t *) ( /* dim=1 */ (( /* dim=0 */ (__pyx_v_centers.data + __pyx_t_12 * __pyx_v_centers.strides[0]) ) + __pyx_t_14 * __pyx_v_centers.strides[1]) ))) >= __pyx_v_threshold);
    if (__pyx_t_13) {
/* … */
    }
+128:             mistakes += 1
      __pyx_v_mistakes = (__pyx_v_mistakes + 1);
+129:         ix += 1
    __pyx_v_ix = (__pyx_v_ix + 1);
  }
 130: 
 131:     # Store the result for this threshold
+132:     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_L24;
        }
        __pyx_L23_error: {
          #ifdef WITH_THREAD
          __Pyx_PyGILState_Release(__pyx_gilstate_save);
          #endif
          goto __pyx_L1_error;
        }
        __pyx_L24:;
      }
  }
+133:         feature_results.append({
        if (unlikely(__pyx_v_feature_results == Py_None)) {
          PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "append");
          __PYX_ERR(0, 133, __pyx_L23_error)
        }
/* … */
        __pyx_t_17 = __Pyx_PyList_Append(__pyx_v_feature_results, __pyx_t_1); if (unlikely(__pyx_t_17 == ((int)-1))) __PYX_ERR(0, 133, __pyx_L23_error)
        __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
      }
+134:             'feature': col,
        __pyx_t_1 = __Pyx_PyDict_NewPresized(3); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 134, __pyx_L23_error)
        __Pyx_GOTREF(__pyx_t_1);
        __pyx_t_3 = __Pyx_PyInt_From_int(__pyx_v_col); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 134, __pyx_L23_error)
        __Pyx_GOTREF(__pyx_t_3);
        if (PyDict_SetItem(__pyx_t_1, __pyx_n_s_feature, __pyx_t_3) < 0) __PYX_ERR(0, 134, __pyx_L23_error)
        __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+135:             'threshold': threshold,
        __pyx_t_3 = PyFloat_FromDouble(__pyx_v_threshold); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 135, __pyx_L23_error)
        __Pyx_GOTREF(__pyx_t_3);
        if (PyDict_SetItem(__pyx_t_1, __pyx_n_s_threshold, __pyx_t_3) < 0) __PYX_ERR(0, 134, __pyx_L23_error)
        __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+136:             'mistakes': mistakes
        __pyx_t_3 = __Pyx_PyInt_From_int(__pyx_v_mistakes); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 136, __pyx_L23_error)
        __Pyx_GOTREF(__pyx_t_3);
        if (PyDict_SetItem(__pyx_t_1, __pyx_n_s_mistakes, __pyx_t_3) < 0) __PYX_ERR(0, 134, __pyx_L23_error)
        __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
 137:         })
 138: 
 139:     # Main loop to iterate over all thresholds
+140:     while ix < n - 1 or ic < k:
  while (1) {
    __pyx_t_15 = (__pyx_v_ix < (__pyx_v_n - 1));
    if (!__pyx_t_15) {
    } else {
      __pyx_t_13 = __pyx_t_15;
      goto __pyx_L27_bool_binop_done;
    }
    __pyx_t_15 = (__pyx_v_ic < __pyx_v_k);
    __pyx_t_13 = __pyx_t_15;
    __pyx_L27_bool_binop_done:;
    if (!__pyx_t_13) break;
+141:         prev_threshold = threshold
    __pyx_v_prev_threshold = __pyx_v_threshold;
 142: 
+143:         if threshold >= max_val:
    __pyx_t_13 = (__pyx_v_threshold >= __pyx_v_max_val);
    if (__pyx_t_13) {
/* … */
    }
+144:             break
      goto __pyx_L26_break;
 145: 
 146:         # Process current threshold
+147:         if is_center_threshold == 0:  # Threshold is a data point
    __pyx_t_13 = (__pyx_v_is_center_threshold == 0);
    if (__pyx_t_13) {
/* … */
      goto __pyx_L30;
    }
+148:             curr_center_idx = y[data_order[ix]]
      __pyx_t_14 = __pyx_v_ix;
      __pyx_t_16 = (*((__pyx_t_5numpy_int64_t *) ( /* dim=0 */ (__pyx_v_data_order.data + __pyx_t_14 * __pyx_v_data_order.strides[0]) )));
      __pyx_v_curr_center_idx = (*((__pyx_t_5d_imm_9splitters_10cut_finder_NP_INT_t *) ( /* dim=0 */ (__pyx_v_y.data + __pyx_t_16 * __pyx_v_y.strides[0]) )));
+149:             left_centers_count[curr_center_idx] += 1
      __pyx_t_9 = __pyx_v_curr_center_idx;
      (__pyx_v_left_centers_count[__pyx_t_9]) = ((__pyx_v_left_centers_count[__pyx_t_9]) + 1);
 150: 
+151:             if centers[curr_center_idx, col] >= threshold:
      __pyx_t_14 = __pyx_v_curr_center_idx;
      __pyx_t_12 = __pyx_v_col;
      __pyx_t_13 = ((*((__pyx_t_5d_imm_9splitters_10cut_finder_NP_FLOAT_t *) ( /* dim=1 */ (( /* dim=0 */ (__pyx_v_centers.data + __pyx_t_14 * __pyx_v_centers.strides[0]) ) + __pyx_t_12 * __pyx_v_centers.strides[1]) ))) >= __pyx_v_threshold);
      if (__pyx_t_13) {
/* … */
        goto __pyx_L31;
      }
+152:                 mistakes += 1
        __pyx_v_mistakes = (__pyx_v_mistakes + 1);
+153:             elif centers[curr_center_idx, col] < threshold:
      __pyx_t_12 = __pyx_v_curr_center_idx;
      __pyx_t_14 = __pyx_v_col;
      __pyx_t_13 = ((*((__pyx_t_5d_imm_9splitters_10cut_finder_NP_FLOAT_t *) ( /* dim=1 */ (( /* dim=0 */ (__pyx_v_centers.data + __pyx_t_12 * __pyx_v_centers.strides[0]) ) + __pyx_t_14 * __pyx_v_centers.strides[1]) ))) < __pyx_v_threshold);
      if (__pyx_t_13) {
/* … */
      }
      __pyx_L31:;
+154:                 mistakes -= 1
        __pyx_v_mistakes = (__pyx_v_mistakes - 1);
 155: 
+156:             ix += 1
      __pyx_v_ix = (__pyx_v_ix + 1);
 157:         else:  # Threshold is a center
+158:             mistakes += centers_count[centers_order[ic]] - 2 * left_centers_count[centers_order[ic]]
    /*else*/ {
      __pyx_t_14 = __pyx_v_ic;
      __pyx_t_12 = __pyx_v_ic;
      __pyx_v_mistakes = (__pyx_v_mistakes + ((__pyx_v_centers_count[(*((__pyx_t_5numpy_int64_t *) ( /* dim=0 */ (__pyx_v_centers_order.data + __pyx_t_14 * __pyx_v_centers_order.strides[0]) )))]) - (2 * (__pyx_v_left_centers_count[(*((__pyx_t_5numpy_int64_t *) ( /* dim=0 */ (__pyx_v_centers_order.data + __pyx_t_12 * __pyx_v_centers_order.strides[0]) )))]))));
+159:             ic += 1
      __pyx_v_ic = (__pyx_v_ic + 1);
 160: 
 161:             # Safeguard against infinite loop for invalid centers
+162:             while ic < k and valid_centers[centers_order[ic]] == 0:
      while (1) {
        __pyx_t_15 = (__pyx_v_ic < __pyx_v_k);
        if (__pyx_t_15) {
        } else {
          __pyx_t_13 = __pyx_t_15;
          goto __pyx_L34_bool_binop_done;
        }
        __pyx_t_12 = __pyx_v_ic;
        __pyx_t_16 = (*((__pyx_t_5numpy_int64_t *) ( /* dim=0 */ (__pyx_v_centers_order.data + __pyx_t_12 * __pyx_v_centers_order.strides[0]) )));
        __pyx_t_15 = ((*((__pyx_t_5d_imm_9splitters_10cut_finder_NP_INT_t *) ( /* dim=0 */ (__pyx_v_valid_centers.data + __pyx_t_16 * __pyx_v_valid_centers.strides[0]) ))) == 0);
        __pyx_t_13 = __pyx_t_15;
        __pyx_L34_bool_binop_done:;
        if (!__pyx_t_13) break;
+163:                 ic += 1
        __pyx_v_ic = (__pyx_v_ic + 1);
      }
    }
    __pyx_L30:;
 164: 
 165:         # Update the next threshold
+166:         if ix < n and ic < k:
    __pyx_t_15 = (__pyx_v_ix < __pyx_v_n);
    if (__pyx_t_15) {
    } else {
      __pyx_t_13 = __pyx_t_15;
      goto __pyx_L37_bool_binop_done;
    }
    __pyx_t_15 = (__pyx_v_ic < __pyx_v_k);
    __pyx_t_13 = __pyx_t_15;
    __pyx_L37_bool_binop_done:;
    if (__pyx_t_13) {
/* … */
      goto __pyx_L36;
    }
+167:             if X[data_order[ix], col] <= centers[centers_order[ic], col]:
      __pyx_t_12 = __pyx_v_ix;
      __pyx_t_16 = (*((__pyx_t_5numpy_int64_t *) ( /* dim=0 */ (__pyx_v_data_order.data + __pyx_t_12 * __pyx_v_data_order.strides[0]) )));
      __pyx_t_14 = __pyx_v_col;
      __pyx_t_18 = __pyx_v_ic;
      __pyx_t_19 = (*((__pyx_t_5numpy_int64_t *) ( /* dim=0 */ (__pyx_v_centers_order.data + __pyx_t_18 * __pyx_v_centers_order.strides[0]) )));
      __pyx_t_20 = __pyx_v_col;
      __pyx_t_13 = ((*((__pyx_t_5d_imm_9splitters_10cut_finder_NP_FLOAT_t *) ( /* dim=1 */ (( /* dim=0 */ (__pyx_v_X.data + __pyx_t_16 * __pyx_v_X.strides[0]) ) + __pyx_t_14 * __pyx_v_X.strides[1]) ))) <= (*((__pyx_t_5d_imm_9splitters_10cut_finder_NP_FLOAT_t *) ( /* dim=1 */ (( /* dim=0 */ (__pyx_v_centers.data + __pyx_t_19 * __pyx_v_centers.strides[0]) ) + __pyx_t_20 * __pyx_v_centers.strides[1]) ))));
      if (__pyx_t_13) {
/* … */
        goto __pyx_L39;
      }
+168:                 threshold = X[data_order[ix], col]
        __pyx_t_18 = __pyx_v_ix;
        __pyx_t_19 = (*((__pyx_t_5numpy_int64_t *) ( /* dim=0 */ (__pyx_v_data_order.data + __pyx_t_18 * __pyx_v_data_order.strides[0]) )));
        __pyx_t_20 = __pyx_v_col;
        __pyx_v_threshold = (*((__pyx_t_5d_imm_9splitters_10cut_finder_NP_FLOAT_t *) ( /* dim=1 */ (( /* dim=0 */ (__pyx_v_X.data + __pyx_t_19 * __pyx_v_X.strides[0]) ) + __pyx_t_20 * __pyx_v_X.strides[1]) )));
+169:                 is_center_threshold = 0
        __pyx_v_is_center_threshold = 0;
 170:             else:
+171:                 threshold = centers[centers_order[ic], col]
      /*else*/ {
        __pyx_t_18 = __pyx_v_ic;
        __pyx_t_19 = (*((__pyx_t_5numpy_int64_t *) ( /* dim=0 */ (__pyx_v_centers_order.data + __pyx_t_18 * __pyx_v_centers_order.strides[0]) )));
        __pyx_t_20 = __pyx_v_col;
        __pyx_v_threshold = (*((__pyx_t_5d_imm_9splitters_10cut_finder_NP_FLOAT_t *) ( /* dim=1 */ (( /* dim=0 */ (__pyx_v_centers.data + __pyx_t_19 * __pyx_v_centers.strides[0]) ) + __pyx_t_20 * __pyx_v_centers.strides[1]) )));
+172:                 is_center_threshold = 1
        __pyx_v_is_center_threshold = 1;
      }
      __pyx_L39:;
+173:         elif ix < n:
    __pyx_t_13 = (__pyx_v_ix < __pyx_v_n);
    if (__pyx_t_13) {
/* … */
      goto __pyx_L36;
    }
+174:             threshold = X[data_order[ix], col]
      __pyx_t_18 = __pyx_v_ix;
      __pyx_t_19 = (*((__pyx_t_5numpy_int64_t *) ( /* dim=0 */ (__pyx_v_data_order.data + __pyx_t_18 * __pyx_v_data_order.strides[0]) )));
      __pyx_t_20 = __pyx_v_col;
      __pyx_v_threshold = (*((__pyx_t_5d_imm_9splitters_10cut_finder_NP_FLOAT_t *) ( /* dim=1 */ (( /* dim=0 */ (__pyx_v_X.data + __pyx_t_19 * __pyx_v_X.strides[0]) ) + __pyx_t_20 * __pyx_v_X.strides[1]) )));
+175:             is_center_threshold = 0
      __pyx_v_is_center_threshold = 0;
+176:         elif ic < k:
    __pyx_t_13 = (__pyx_v_ic < __pyx_v_k);
    if (__pyx_t_13) {
/* … */
      goto __pyx_L36;
    }
+177:             threshold = centers[centers_order[ic], col]
      __pyx_t_18 = __pyx_v_ic;
      __pyx_t_19 = (*((__pyx_t_5numpy_int64_t *) ( /* dim=0 */ (__pyx_v_centers_order.data + __pyx_t_18 * __pyx_v_centers_order.strides[0]) )));
      __pyx_t_20 = __pyx_v_col;
      __pyx_v_threshold = (*((__pyx_t_5d_imm_9splitters_10cut_finder_NP_FLOAT_t *) ( /* dim=1 */ (( /* dim=0 */ (__pyx_v_centers.data + __pyx_t_19 * __pyx_v_centers.strides[0]) ) + __pyx_t_20 * __pyx_v_centers.strides[1]) )));
+178:             is_center_threshold = 1
      __pyx_v_is_center_threshold = 1;
 179:         else:
+180:             break
    /*else*/ {
      goto __pyx_L26_break;
    }
    __pyx_L36:;
 181: 
 182:         # Store the result for this threshold
+183:         if prev_threshold != threshold:
    __pyx_t_13 = (__pyx_v_prev_threshold != __pyx_v_threshold);
    if (__pyx_t_13) {
/* … */
    }
  }
  __pyx_L26_break:;
+184:             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_L45;
            }
            __pyx_L44_error: {
              #ifdef WITH_THREAD
              __Pyx_PyGILState_Release(__pyx_gilstate_save);
              #endif
              goto __pyx_L1_error;
            }
            __pyx_L45:;
          }
      }
+185:                 feature_results.append({
            if (unlikely(__pyx_v_feature_results == Py_None)) {
              PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "append");
              __PYX_ERR(0, 185, __pyx_L44_error)
            }
/* … */
            __pyx_t_17 = __Pyx_PyList_Append(__pyx_v_feature_results, __pyx_t_1); if (unlikely(__pyx_t_17 == ((int)-1))) __PYX_ERR(0, 185, __pyx_L44_error)
            __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
          }
+186:                     'feature': col,
            __pyx_t_1 = __Pyx_PyDict_NewPresized(3); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 186, __pyx_L44_error)
            __Pyx_GOTREF(__pyx_t_1);
            __pyx_t_3 = __Pyx_PyInt_From_int(__pyx_v_col); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 186, __pyx_L44_error)
            __Pyx_GOTREF(__pyx_t_3);
            if (PyDict_SetItem(__pyx_t_1, __pyx_n_s_feature, __pyx_t_3) < 0) __PYX_ERR(0, 186, __pyx_L44_error)
            __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+187:                     'threshold': prev_threshold,
            __pyx_t_3 = PyFloat_FromDouble(__pyx_v_prev_threshold); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 187, __pyx_L44_error)
            __Pyx_GOTREF(__pyx_t_3);
            if (PyDict_SetItem(__pyx_t_1, __pyx_n_s_threshold, __pyx_t_3) < 0) __PYX_ERR(0, 186, __pyx_L44_error)
            __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+188:                     'mistakes': mistakes
            __pyx_t_3 = __Pyx_PyInt_From_int(__pyx_v_mistakes); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 188, __pyx_L44_error)
            __Pyx_GOTREF(__pyx_t_3);
            if (PyDict_SetItem(__pyx_t_1, __pyx_n_s_mistakes, __pyx_t_3) < 0) __PYX_ERR(0, 186, __pyx_L44_error)
            __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
 189:                 })
 190: 
+191:     free(left_centers_count)
  free(__pyx_v_left_centers_count);
 192: 
+193: @cython.boundscheck(False)
/* Python wrapper */
static PyObject *__pyx_pw_5d_imm_9splitters_10cut_finder_3get_all_mistakes_histogram(PyObject *__pyx_self, 
#if CYTHON_METH_FASTCALL
PyObject *const *__pyx_args, Py_ssize_t __pyx_nargs, PyObject *__pyx_kwds
#else
PyObject *__pyx_args, PyObject *__pyx_kwds
#endif
); /*proto*/
PyDoc_STRVAR(__pyx_doc_5d_imm_9splitters_10cut_finder_2get_all_mistakes_histogram, "\n    Main function to calculate mistakes for all features and thresholds.\n    Returns a list of Python dictionaries with 'feature', 'threshold', and 'mistakes'.\n    ");
static PyMethodDef __pyx_mdef_5d_imm_9splitters_10cut_finder_3get_all_mistakes_histogram = {"get_all_mistakes_histogram", (PyCFunction)(void*)(__Pyx_PyCFunction_FastCallWithKeywords)__pyx_pw_5d_imm_9splitters_10cut_finder_3get_all_mistakes_histogram, __Pyx_METH_FASTCALL|METH_KEYWORDS, __pyx_doc_5d_imm_9splitters_10cut_finder_2get_all_mistakes_histogram};
static PyObject *__pyx_pw_5d_imm_9splitters_10cut_finder_3get_all_mistakes_histogram(PyObject *__pyx_self, 
#if CYTHON_METH_FASTCALL
PyObject *const *__pyx_args, Py_ssize_t __pyx_nargs, PyObject *__pyx_kwds
#else
PyObject *__pyx_args, PyObject *__pyx_kwds
#endif
) {
  __Pyx_memviewslice __pyx_v_X = { 0, 0, { 0 }, { 0 }, { 0 } };
  __Pyx_memviewslice __pyx_v_y = { 0, 0, { 0 }, { 0 }, { 0 } };
  __Pyx_memviewslice __pyx_v_centers = { 0, 0, { 0 }, { 0 }, { 0 } };
  __Pyx_memviewslice __pyx_v_valid_centers = { 0, 0, { 0 }, { 0 }, { 0 } };
  __Pyx_memviewslice __pyx_v_valid_cols = { 0, 0, { 0 }, { 0 }, { 0 } };
  PyObject *__pyx_v_histogram = 0;
  int __pyx_v_njobs;
  int __pyx_v_sorted;
  #if !CYTHON_METH_FASTCALL
  CYTHON_UNUSED Py_ssize_t __pyx_nargs;
  #endif
  CYTHON_UNUSED PyObject *const *__pyx_kwvalues;
  PyObject *__pyx_r = 0;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("get_all_mistakes_histogram (wrapper)", 0);
  #if !CYTHON_METH_FASTCALL
  #if CYTHON_ASSUME_SAFE_MACROS
  __pyx_nargs = PyTuple_GET_SIZE(__pyx_args);
  #else
  __pyx_nargs = PyTuple_Size(__pyx_args); if (unlikely(__pyx_nargs < 0)) return NULL;
  #endif
  #endif
  __pyx_kwvalues = __Pyx_KwValues_FASTCALL(__pyx_args, __pyx_nargs);
  {
    PyObject **__pyx_pyargnames[] = {&__pyx_n_s_X,&__pyx_n_s_y,&__pyx_n_s_centers,&__pyx_n_s_valid_centers,&__pyx_n_s_valid_cols,&__pyx_n_s_histogram,&__pyx_n_s_njobs,&__pyx_n_s_sorted,0};
  PyObject* values[8] = {0,0,0,0,0,0,0,0};
    if (__pyx_kwds) {
      Py_ssize_t kw_args;
      switch (__pyx_nargs) {
        case  8: values[7] = __Pyx_Arg_FASTCALL(__pyx_args, 7);
        CYTHON_FALLTHROUGH;
        case  7: values[6] = __Pyx_Arg_FASTCALL(__pyx_args, 6);
        CYTHON_FALLTHROUGH;
        case  6: values[5] = __Pyx_Arg_FASTCALL(__pyx_args, 5);
        CYTHON_FALLTHROUGH;
        case  5: values[4] = __Pyx_Arg_FASTCALL(__pyx_args, 4);
        CYTHON_FALLTHROUGH;
        case  4: values[3] = __Pyx_Arg_FASTCALL(__pyx_args, 3);
        CYTHON_FALLTHROUGH;
        case  3: values[2] = __Pyx_Arg_FASTCALL(__pyx_args, 2);
        CYTHON_FALLTHROUGH;
        case  2: values[1] = __Pyx_Arg_FASTCALL(__pyx_args, 1);
        CYTHON_FALLTHROUGH;
        case  1: values[0] = __Pyx_Arg_FASTCALL(__pyx_args, 0);
        CYTHON_FALLTHROUGH;
        case  0: break;
        default: goto __pyx_L5_argtuple_error;
      }
      kw_args = __Pyx_NumKwargs_FASTCALL(__pyx_kwds);
      switch (__pyx_nargs) {
        case  0:
        if (likely((values[0] = __Pyx_GetKwValue_FASTCALL(__pyx_kwds, __pyx_kwvalues, __pyx_n_s_X)) != 0)) {
          (void)__Pyx_Arg_NewRef_FASTCALL(values[0]);
          kw_args--;
        }
        else if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 193, __pyx_L3_error)
        else goto __pyx_L5_argtuple_error;
        CYTHON_FALLTHROUGH;
        case  1:
        if (likely((values[1] = __Pyx_GetKwValue_FASTCALL(__pyx_kwds, __pyx_kwvalues, __pyx_n_s_y)) != 0)) {
          (void)__Pyx_Arg_NewRef_FASTCALL(values[1]);
          kw_args--;
        }
        else if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 193, __pyx_L3_error)
        else {
          __Pyx_RaiseArgtupleInvalid("get_all_mistakes_histogram", 0, 7, 8, 1); __PYX_ERR(0, 193, __pyx_L3_error)
        }
        CYTHON_FALLTHROUGH;
        case  2:
        if (likely((values[2] = __Pyx_GetKwValue_FASTCALL(__pyx_kwds, __pyx_kwvalues, __pyx_n_s_centers)) != 0)) {
          (void)__Pyx_Arg_NewRef_FASTCALL(values[2]);
          kw_args--;
        }
        else if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 193, __pyx_L3_error)
        else {
          __Pyx_RaiseArgtupleInvalid("get_all_mistakes_histogram", 0, 7, 8, 2); __PYX_ERR(0, 193, __pyx_L3_error)
        }
        CYTHON_FALLTHROUGH;
        case  3:
        if (likely((values[3] = __Pyx_GetKwValue_FASTCALL(__pyx_kwds, __pyx_kwvalues, __pyx_n_s_valid_centers)) != 0)) {
          (void)__Pyx_Arg_NewRef_FASTCALL(values[3]);
          kw_args--;
        }
        else if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 193, __pyx_L3_error)
        else {
          __Pyx_RaiseArgtupleInvalid("get_all_mistakes_histogram", 0, 7, 8, 3); __PYX_ERR(0, 193, __pyx_L3_error)
        }
        CYTHON_FALLTHROUGH;
        case  4:
        if (likely((values[4] = __Pyx_GetKwValue_FASTCALL(__pyx_kwds, __pyx_kwvalues, __pyx_n_s_valid_cols)) != 0)) {
          (void)__Pyx_Arg_NewRef_FASTCALL(values[4]);
          kw_args--;
        }
        else if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 193, __pyx_L3_error)
        else {
          __Pyx_RaiseArgtupleInvalid("get_all_mistakes_histogram", 0, 7, 8, 4); __PYX_ERR(0, 193, __pyx_L3_error)
        }
        CYTHON_FALLTHROUGH;
        case  5:
        if (likely((values[5] = __Pyx_GetKwValue_FASTCALL(__pyx_kwds, __pyx_kwvalues, __pyx_n_s_histogram)) != 0)) {
          (void)__Pyx_Arg_NewRef_FASTCALL(values[5]);
          kw_args--;
        }
        else if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 193, __pyx_L3_error)
        else {
          __Pyx_RaiseArgtupleInvalid("get_all_mistakes_histogram", 0, 7, 8, 5); __PYX_ERR(0, 193, __pyx_L3_error)
        }
        CYTHON_FALLTHROUGH;
        case  6:
        if (likely((values[6] = __Pyx_GetKwValue_FASTCALL(__pyx_kwds, __pyx_kwvalues, __pyx_n_s_njobs)) != 0)) {
          (void)__Pyx_Arg_NewRef_FASTCALL(values[6]);
          kw_args--;
        }
        else if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 193, __pyx_L3_error)
        else {
          __Pyx_RaiseArgtupleInvalid("get_all_mistakes_histogram", 0, 7, 8, 6); __PYX_ERR(0, 193, __pyx_L3_error)
        }
        CYTHON_FALLTHROUGH;
        case  7:
        if (kw_args > 0) {
          PyObject* value = __Pyx_GetKwValue_FASTCALL(__pyx_kwds, __pyx_kwvalues, __pyx_n_s_sorted);
          if (value) { values[7] = __Pyx_Arg_NewRef_FASTCALL(value); kw_args--; }
          else if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 193, __pyx_L3_error)
        }
      }
      if (unlikely(kw_args > 0)) {
        const Py_ssize_t kwd_pos_args = __pyx_nargs;
        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_kwvalues, __pyx_pyargnames, 0, values + 0, kwd_pos_args, "get_all_mistakes_histogram") < 0)) __PYX_ERR(0, 193, __pyx_L3_error)
      }
    } else {
      switch (__pyx_nargs) {
        case  8: values[7] = __Pyx_Arg_FASTCALL(__pyx_args, 7);
        CYTHON_FALLTHROUGH;
        case  7: values[6] = __Pyx_Arg_FASTCALL(__pyx_args, 6);
        values[5] = __Pyx_Arg_FASTCALL(__pyx_args, 5);
        values[4] = __Pyx_Arg_FASTCALL(__pyx_args, 4);
        values[3] = __Pyx_Arg_FASTCALL(__pyx_args, 3);
        values[2] = __Pyx_Arg_FASTCALL(__pyx_args, 2);
        values[1] = __Pyx_Arg_FASTCALL(__pyx_args, 1);
        values[0] = __Pyx_Arg_FASTCALL(__pyx_args, 0);
        break;
        default: goto __pyx_L5_argtuple_error;
      }
    }
    __pyx_v_X = __Pyx_PyObject_to_MemoryviewSlice_dsds_nn___pyx_t_5d_imm_9splitters_10cut_finder_NP_FLOAT_t(values[0], PyBUF_WRITABLE); if (unlikely(!__pyx_v_X.memview)) __PYX_ERR(0, 196, __pyx_L3_error)
    __pyx_v_y = __Pyx_PyObject_to_MemoryviewSlice_ds_nn___pyx_t_5d_imm_9splitters_10cut_finder_NP_INT_t(values[1], PyBUF_WRITABLE); if (unlikely(!__pyx_v_y.memview)) __PYX_ERR(0, 196, __pyx_L3_error)
    __pyx_v_centers = __Pyx_PyObject_to_MemoryviewSlice_dsds_nn___pyx_t_5d_imm_9splitters_10cut_finder_NP_FLOAT_t(values[2], PyBUF_WRITABLE); if (unlikely(!__pyx_v_centers.memview)) __PYX_ERR(0, 196, __pyx_L3_error)
    __pyx_v_valid_centers = __Pyx_PyObject_to_MemoryviewSlice_ds_nn___pyx_t_5d_imm_9splitters_10cut_finder_NP_INT_t(values[3], PyBUF_WRITABLE); if (unlikely(!__pyx_v_valid_centers.memview)) __PYX_ERR(0, 197, __pyx_L3_error)
    __pyx_v_valid_cols = __Pyx_PyObject_to_MemoryviewSlice_ds_nn___pyx_t_5d_imm_9splitters_10cut_finder_NP_INT_t(values[4], PyBUF_WRITABLE); if (unlikely(!__pyx_v_valid_cols.memview)) __PYX_ERR(0, 197, __pyx_L3_error)
    __pyx_v_histogram = ((PyObject*)values[5]);
    __pyx_v_njobs = __Pyx_PyInt_As_int(values[6]); if (unlikely((__pyx_v_njobs == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 197, __pyx_L3_error)
    if (values[7]) {
      __pyx_v_sorted = __Pyx_PyObject_IsTrue(values[7]); if (unlikely((__pyx_v_sorted == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 197, __pyx_L3_error)
    } else {
/* … */
  /* function exit code */
  goto __pyx_L0;
  __pyx_L1_error:;
  __pyx_r = NULL;
  __pyx_L0:;
  __PYX_XCLEAR_MEMVIEW(&__pyx_v_X, 1);
  __PYX_XCLEAR_MEMVIEW(&__pyx_v_y, 1);
  __PYX_XCLEAR_MEMVIEW(&__pyx_v_centers, 1);
  __PYX_XCLEAR_MEMVIEW(&__pyx_v_valid_centers, 1);
  __PYX_XCLEAR_MEMVIEW(&__pyx_v_valid_cols, 1);
  {
    Py_ssize_t __pyx_temp;
    for (__pyx_temp=0; __pyx_temp < (Py_ssize_t)(sizeof(values)/sizeof(values[0])); ++__pyx_temp) {
      __Pyx_Arg_XDECREF_FASTCALL(values[__pyx_temp]);
    }
  }
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}

static PyObject *__pyx_pf_5d_imm_9splitters_10cut_finder_2get_all_mistakes_histogram(CYTHON_UNUSED PyObject *__pyx_self, __Pyx_memviewslice __pyx_v_X, __Pyx_memviewslice __pyx_v_y, __Pyx_memviewslice __pyx_v_centers, __Pyx_memviewslice __pyx_v_valid_centers, __Pyx_memviewslice __pyx_v_valid_cols, PyObject *__pyx_v_histogram, int __pyx_v_njobs, int __pyx_v_sorted) {
  int __pyx_v_n;
  int __pyx_v_k;
  int __pyx_v_d;
  PyObject *__pyx_v_feature_results = 0;
  int __pyx_v_col;
  PyObject *__pyx_r = NULL;
/* … */
  /* function exit code */
  __pyx_L1_error:;
  __Pyx_XDECREF(__pyx_t_1);
  __Pyx_AddTraceback("d_imm.splitters.cut_finder.get_all_mistakes_histogram", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __pyx_r = NULL;
  __pyx_L0:;
  __Pyx_XDECREF(__pyx_v_feature_results);
  __Pyx_XGIVEREF(__pyx_r);
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}
/* … */
  __pyx_tuple__25 = PyTuple_Pack(13, __pyx_n_s_X, __pyx_n_s_y, __pyx_n_s_centers, __pyx_n_s_valid_centers, __pyx_n_s_valid_cols, __pyx_n_s_histogram, __pyx_n_s_njobs, __pyx_n_s_sorted, __pyx_n_s_n, __pyx_n_s_k, __pyx_n_s_d, __pyx_n_s_feature_results, __pyx_n_s_col); if (unlikely(!__pyx_tuple__25)) __PYX_ERR(0, 193, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_tuple__25);
  __Pyx_GIVEREF(__pyx_tuple__25);
/* … */
  __pyx_t_4 = PyTuple_New(1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 193, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  __Pyx_GIVEREF(__pyx_t_7);
  if (__Pyx_PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_7)) __PYX_ERR(0, 193, __pyx_L1_error);
  __pyx_t_7 = 0;
  __pyx_t_7 = __Pyx_CyFunction_New(&__pyx_mdef_5d_imm_9splitters_10cut_finder_3get_all_mistakes_histogram, 0, __pyx_n_s_get_all_mistakes_histogram, NULL, __pyx_n_s_d_imm_splitters_cut_finder, __pyx_d, ((PyObject *)__pyx_codeobj__26)); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 193, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_7);
  __Pyx_CyFunction_SetDefaultsTuple(__pyx_t_7, __pyx_t_4);
  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
  if (PyDict_SetItem(__pyx_d, __pyx_n_s_get_all_mistakes_histogram, __pyx_t_7) < 0) __PYX_ERR(0, 193, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
 194: @cython.wraparound(False)
 195: def get_all_mistakes_histogram(
 196:     NP_FLOAT_t[:,:] X, NP_INT_t[:] y, NP_FLOAT_t[:,:] centers,
+197:     NP_INT_t[:] valid_centers, NP_INT_t[:] valid_cols, list histogram, int njobs, bint sorted=True
      __pyx_v_sorted = ((int)((int)1));
    }
  }
  goto __pyx_L6_skip;
  __pyx_L5_argtuple_error:;
  __Pyx_RaiseArgtupleInvalid("get_all_mistakes_histogram", 0, 7, 8, __pyx_nargs); __PYX_ERR(0, 193, __pyx_L3_error)
  __pyx_L6_skip:;
  goto __pyx_L4_argument_unpacking_done;
  __pyx_L3_error:;
  {
    Py_ssize_t __pyx_temp;
    for (__pyx_temp=0; __pyx_temp < (Py_ssize_t)(sizeof(values)/sizeof(values[0])); ++__pyx_temp) {
      __Pyx_Arg_XDECREF_FASTCALL(values[__pyx_temp]);
    }
  }
  __PYX_XCLEAR_MEMVIEW(&__pyx_v_X, 1);
  __PYX_XCLEAR_MEMVIEW(&__pyx_v_y, 1);
  __PYX_XCLEAR_MEMVIEW(&__pyx_v_centers, 1);
  __PYX_XCLEAR_MEMVIEW(&__pyx_v_valid_centers, 1);
  __PYX_XCLEAR_MEMVIEW(&__pyx_v_valid_cols, 1);
  __Pyx_AddTraceback("d_imm.splitters.cut_finder.get_all_mistakes_histogram", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __Pyx_RefNannyFinishContext();
  return NULL;
  __pyx_L4_argument_unpacking_done:;
  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_histogram), (&PyList_Type), 1, "histogram", 1))) __PYX_ERR(0, 197, __pyx_L1_error)
  __pyx_r = __pyx_pf_5d_imm_9splitters_10cut_finder_2get_all_mistakes_histogram(__pyx_self, __pyx_v_X, __pyx_v_y, __pyx_v_centers, __pyx_v_valid_centers, __pyx_v_valid_cols, __pyx_v_histogram, __pyx_v_njobs, __pyx_v_sorted);
/* … */
  __pyx_t_7 = __Pyx_PyBool_FromLong(((int)1)); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 197, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_7);
 198: ):
 199:     """
 200:     Main function to calculate mistakes for all features and thresholds.
 201:     Returns a list of Python dictionaries with 'feature', 'threshold', and 'mistakes'.
 202:     """
+203:     cdef int n = X.shape[0]
  __pyx_v_n = (__pyx_v_X.shape[0]);
+204:     cdef int k = centers.shape[0]
  __pyx_v_k = (__pyx_v_centers.shape[0]);
+205:     cdef int d = valid_cols.shape[0]
  __pyx_v_d = (__pyx_v_valid_cols.shape[0]);
+206:     cdef list feature_results = []
  __pyx_t_1 = PyList_New(0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 206, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_v_feature_results = ((PyObject*)__pyx_t_1);
  __pyx_t_1 = 0;
 207:     cdef int col
 208: 
+209:     if njobs is None or njobs <= 1:
  __pyx_t_1 = __Pyx_PyInt_From_int(__pyx_v_njobs); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 209, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_3 = (__pyx_t_1 == Py_None);
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  if (!__pyx_t_3) {
  } else {
    __pyx_t_2 = __pyx_t_3;
    goto __pyx_L4_bool_binop_done;
  }
  __pyx_t_3 = (__pyx_v_njobs <= 1);
  __pyx_t_2 = __pyx_t_3;
  __pyx_L4_bool_binop_done:;
  if (__pyx_t_2) {
/* … */
    goto __pyx_L3;
  }
 210:         # Iterate over valid columns
+211:         for col in range(d):
    __pyx_t_4 = __pyx_v_d;
    __pyx_t_5 = __pyx_t_4;
    for (__pyx_t_6 = 0; __pyx_t_6 < __pyx_t_5; __pyx_t_6+=1) {
      __pyx_v_col = __pyx_t_6;
+212:             if valid_cols[col] == 1:
      __pyx_t_7 = __pyx_v_col;
      __pyx_t_2 = ((*((__pyx_t_5d_imm_9splitters_10cut_finder_NP_INT_t *) ( /* dim=0 */ (__pyx_v_valid_cols.data + __pyx_t_7 * __pyx_v_valid_cols.strides[0]) ))) == 1);
      if (__pyx_t_2) {
/* … */
      }
    }
+213:                 if sorted:
        if (__pyx_v_sorted) {
/* … */
          goto __pyx_L9;
        }
+214:                     update_col_all_mistakes_histogram_sorted(
          __pyx_f_5d_imm_9splitters_10cut_finder_update_col_all_mistakes_histogram_sorted(__pyx_v_X, __pyx_v_y, __pyx_v_centers, __pyx_v_valid_centers, __pyx_v_col, __pyx_v_n, __pyx_v_k, __pyx_v_feature_results, ((PyObject*)__pyx_t_1)); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 214, __pyx_L1_error)
          __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 215:                         X, y, centers, valid_centers,
+216:                         col, n, k, feature_results, histogram[col]
          if (unlikely(__pyx_v_histogram == Py_None)) {
            PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable");
            __PYX_ERR(0, 216, __pyx_L1_error)
          }
          if (!(likely(PyList_CheckExact(PyList_GET_ITEM(__pyx_v_histogram, __pyx_v_col)))||((PyList_GET_ITEM(__pyx_v_histogram, __pyx_v_col)) == Py_None) || __Pyx_RaiseUnexpectedTypeError("list", PyList_GET_ITEM(__pyx_v_histogram, __pyx_v_col)))) __PYX_ERR(0, 216, __pyx_L1_error)
          __pyx_t_1 = PyList_GET_ITEM(__pyx_v_histogram, __pyx_v_col);
          __Pyx_INCREF(__pyx_t_1);
 217:                     )
 218:                 else:
+219:                     update_col_all_mistakes_histogram_unsorted(
        /*else*/ {
/* … */
          __pyx_f_5d_imm_9splitters_10cut_finder_update_col_all_mistakes_histogram_unsorted(__pyx_v_X, __pyx_v_y, __pyx_v_centers, __pyx_v_valid_centers, __pyx_v_col, __pyx_v_n, __pyx_v_k, __pyx_v_feature_results, ((PyObject*)__pyx_t_1)); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 219, __pyx_L1_error)
          __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
        }
        __pyx_L9:;
 220:                         X, y, centers, valid_centers,
+221:                         col, n, k, feature_results, histogram[col]
          if (unlikely(__pyx_v_histogram == Py_None)) {
            PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable");
            __PYX_ERR(0, 221, __pyx_L1_error)
          }
          if (!(likely(PyList_CheckExact(PyList_GET_ITEM(__pyx_v_histogram, __pyx_v_col)))||((PyList_GET_ITEM(__pyx_v_histogram, __pyx_v_col)) == Py_None) || __Pyx_RaiseUnexpectedTypeError("list", PyList_GET_ITEM(__pyx_v_histogram, __pyx_v_col)))) __PYX_ERR(0, 221, __pyx_L1_error)
          __pyx_t_1 = PyList_GET_ITEM(__pyx_v_histogram, __pyx_v_col);
          __Pyx_INCREF(__pyx_t_1);
 222:                     )
 223:     else:
 224:         #Parallelize the process
+225:         for col in prange(d, num_threads=njobs, schedule='dynamic', nogil=True):
  /*else*/ {
    {
        #ifdef WITH_THREAD
        PyThreadState *_save;
        _save = NULL;
        Py_UNBLOCK_THREADS
        __Pyx_FastGIL_Remember();
        #endif
        /*try:*/ {
          __pyx_t_4 = __pyx_v_d;
          {
              #if ((defined(__APPLE__) || defined(__OSX__)) && (defined(__GNUC__) && (__GNUC__ > 2 || (__GNUC__ == 2 && (__GNUC_MINOR__ > 95)))))
                  #undef likely
                  #undef unlikely
                  #define likely(x)   (x)
                  #define unlikely(x) (x)
              #endif
              __pyx_t_6 = (__pyx_t_4 - 0 + 1 - 1/abs(1)) / 1;
              if (__pyx_t_6 > 0)
              {
                  #ifdef _OPENMP
                  #pragma omp parallel
                  #endif /* _OPENMP */
                  {
                      #ifdef _OPENMP
                      #pragma omp for firstprivate(__pyx_v_col) lastprivate(__pyx_v_col) schedule(dynamic)          __pyx_t_4 = __pyx_v_d;
          {
              #if ((defined(__APPLE__) || defined(__OSX__)) && (defined(__GNUC__) && (__GNUC__ > 2 || (__GNUC__ == 2 && (__GNUC_MINOR__ > 95)))))
                  #undef likely
                  #undef unlikely
                  #define likely(x)   (x)
                  #define unlikely(x) (x)
              #endif
              __pyx_t_6 = (__pyx_t_4 - 0 + 1 - 1/abs(1)) / 1;
              if (__pyx_t_6 > 0)
              {
                  #ifdef _OPENMP
                  #pragma omp parallel
                  #endif /* _OPENMP */
                  {
                      #ifdef _OPENMP
                      #pragma omp for firstprivate(__pyx_v_col) lastprivate(__pyx_v_col) schedule(dynamic) num_threads(__pyx_v_njobs)
                      #endif /* _OPENMP */
                      for (__pyx_t_5 = 0; __pyx_t_5 < __pyx_t_6; __pyx_t_5++){
                          {
                              __pyx_v_col = (int)(0 + 1 * __pyx_t_5);
/* … */
        /*finally:*/ {
          /*normal exit:*/{
            #ifdef WITH_THREAD
            __Pyx_FastGIL_Forget();
            Py_BLOCK_THREADS
            #endif
            goto __pyx_L12;
          }
          __pyx_L11_error: {
            #ifdef WITH_THREAD
            __Pyx_FastGIL_Forget();
            Py_BLOCK_THREADS
            #endif
            goto __pyx_L1_error;
          }
          __pyx_L12:;
        }
    }
  }
  __pyx_L3:;
+226:             if valid_cols[col] == 1:
                              __pyx_t_7 = __pyx_v_col;
                              __pyx_t_2 = ((*((__pyx_t_5d_imm_9splitters_10cut_finder_NP_INT_t *) ( /* dim=0 */ (__pyx_v_valid_cols.data + __pyx_t_7 * __pyx_v_valid_cols.strides[0]) ))) == 1);
                              if (__pyx_t_2) {
/* … */
                              }
                              goto __pyx_L25;
                              __pyx_L15_error:;
                              {
                                  #ifdef WITH_THREAD
                                  PyGILState_STATE __pyx_gilstate_save = __Pyx_PyGILState_Ensure();
                                  #endif
                                  #ifdef _OPENMP
                                  #pragma omp flush(__pyx_parallel_exc_type)
                                  #endif /* _OPENMP */
                                  if (!__pyx_parallel_exc_type) {
                                    __Pyx_ErrFetchWithState(&__pyx_parallel_exc_type, &__pyx_parallel_exc_value, &__pyx_parallel_exc_tb);
                                    __pyx_parallel_filename = __pyx_filename; __pyx_parallel_lineno = __pyx_lineno; __pyx_parallel_clineno = __pyx_clineno;
                                    __Pyx_GOTREF(__pyx_parallel_exc_type);
                                  }
                                  #ifdef WITH_THREAD
                                  __Pyx_PyGILState_Release(__pyx_gilstate_save);
                                  #endif
                              }
                              __pyx_parallel_why = 4;
                              goto __pyx_L24;
                              __pyx_L24:;
                              #ifdef _OPENMP
                              #pragma omp critical(__pyx_parallel_lastprivates1)
                              #endif /* _OPENMP */
                              {
                                  __pyx_parallel_temp0 = __pyx_v_col;
                              }
                              __pyx_L25:;
                              #ifdef _OPENMP
                              #pragma omp flush(__pyx_parallel_why)
                              #endif /* _OPENMP */
                          }
                      }
                      #ifdef _OPENMP
                      Py_END_ALLOW_THREADS
                      #else
{
#ifdef WITH_THREAD
                      PyGILState_STATE __pyx_gilstate_save = __Pyx_PyGILState_Ensure();
                      #endif
                      #endif /* _OPENMP */
                      /* Clean up any temporaries */
                      __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0;
                      #ifdef WITH_THREAD
                      __Pyx_PyGILState_Release(__pyx_gilstate_save);
                      #endif
                      #ifndef _OPENMP
}
#endif /* _OPENMP */
                  }
              }
              if (__pyx_parallel_exc_type) {
                /* This may have been overridden by a continue, break or return in another thread. Prefer the error. */
                __pyx_parallel_why = 4;
              }
              if (__pyx_parallel_why) {
                __pyx_v_col = __pyx_parallel_temp0;
                switch (__pyx_parallel_why) {
                      case 4:
                  {
                      #ifdef WITH_THREAD
                      PyGILState_STATE __pyx_gilstate_save = __Pyx_PyGILState_Ensure();
                      #endif
                      __Pyx_GIVEREF(__pyx_parallel_exc_type);
                      __Pyx_ErrRestoreWithState(__pyx_parallel_exc_type, __pyx_parallel_exc_value, __pyx_parallel_exc_tb);
                      __pyx_filename = __pyx_parallel_filename; __pyx_lineno = __pyx_parallel_lineno; __pyx_clineno = __pyx_parallel_clineno;
                      #ifdef WITH_THREAD
                      __Pyx_PyGILState_Release(__pyx_gilstate_save);
                      #endif
                  }
                  goto __pyx_L11_error;
                }
              }
          }
          #if ((defined(__APPLE__) || defined(__OSX__)) && (defined(__GNUC__) && (__GNUC__ > 2 || (__GNUC__ == 2 && (__GNUC_MINOR__ > 95)))))
              #undef likely
              #undef unlikely
              #define likely(x)   __builtin_expect(!!(x), 1)
              #define unlikely(x) __builtin_expect(!!(x), 0)
          #endif
        }
 227:                 # Ensure GIL is acquired before calling Python-dependent functions
+228:                 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_L22;
                                      }
                                      __pyx_L21_error: {
                                        #ifdef WITH_THREAD
                                        __Pyx_PyGILState_Release(__pyx_gilstate_save);
                                        #endif
                                        goto __pyx_L15_error;
                                      }
                                      __pyx_L22:;
                                    }
                                }
+229:                     print("Running in parallel")
                                      __pyx_t_1 = __Pyx_PyObject_Call(__pyx_builtin_print, __pyx_tuple__11, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 229, __pyx_L21_error)
                                      __Pyx_GOTREF(__pyx_t_1);
                                      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
/* … */
  __pyx_tuple__11 = PyTuple_Pack(1, __pyx_kp_s_Running_in_parallel); if (unlikely(!__pyx_tuple__11)) __PYX_ERR(0, 229, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_tuple__11);
  __Pyx_GIVEREF(__pyx_tuple__11);
+230:                     if sorted:
                                      if (__pyx_v_sorted) {
/* … */
                                        goto __pyx_L23;
                                      }
+231:                         update_col_all_mistakes_histogram_sorted(
                                        __pyx_f_5d_imm_9splitters_10cut_finder_update_col_all_mistakes_histogram_sorted(__pyx_v_X, __pyx_v_y, __pyx_v_centers, __pyx_v_valid_centers, __pyx_v_col, __pyx_v_n, __pyx_v_k, __pyx_v_feature_results, ((PyObject*)__pyx_t_1)); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 231, __pyx_L21_error)
                                        __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 232:                             X, y, centers, valid_centers,
+233:                             col, n, k, feature_results, histogram[col]
                                        if (unlikely(__pyx_v_histogram == Py_None)) {
                                          PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable");
                                          __PYX_ERR(0, 233, __pyx_L21_error)
                                        }
                                        if (!(likely(PyList_CheckExact(PyList_GET_ITEM(__pyx_v_histogram, __pyx_v_col)))||((PyList_GET_ITEM(__pyx_v_histogram, __pyx_v_col)) == Py_None) || __Pyx_RaiseUnexpectedTypeError("list", PyList_GET_ITEM(__pyx_v_histogram, __pyx_v_col)))) __PYX_ERR(0, 233, __pyx_L21_error)
                                        __pyx_t_1 = PyList_GET_ITEM(__pyx_v_histogram, __pyx_v_col);
                                        __Pyx_INCREF(__pyx_t_1);
 234:                         )
 235:                     else:
+236:                         update_col_all_mistakes_histogram_unsorted(
                                      /*else*/ {
/* … */
                                        __pyx_f_5d_imm_9splitters_10cut_finder_update_col_all_mistakes_histogram_unsorted(__pyx_v_X, __pyx_v_y, __pyx_v_centers, __pyx_v_valid_centers, __pyx_v_col, __pyx_v_n, __pyx_v_k, __pyx_v_feature_results, ((PyObject*)__pyx_t_1)); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 236, __pyx_L21_error)
                                        __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
                                      }
                                      __pyx_L23:;
                                    }
 237:                             X, y, centers, valid_centers,
+238:                             col, n, k, feature_results, histogram[col]
                                        if (unlikely(__pyx_v_histogram == Py_None)) {
                                          PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable");
                                          __PYX_ERR(0, 238, __pyx_L21_error)
                                        }
                                        if (!(likely(PyList_CheckExact(PyList_GET_ITEM(__pyx_v_histogram, __pyx_v_col)))||((PyList_GET_ITEM(__pyx_v_histogram, __pyx_v_col)) == Py_None) || __Pyx_RaiseUnexpectedTypeError("list", PyList_GET_ITEM(__pyx_v_histogram, __pyx_v_col)))) __PYX_ERR(0, 238, __pyx_L21_error)
                                        __pyx_t_1 = PyList_GET_ITEM(__pyx_v_histogram, __pyx_v_col);
                                        __Pyx_INCREF(__pyx_t_1);
 239:                         )
 240: 
+241:     return feature_results
  __Pyx_XDECREF(__pyx_r);
  __Pyx_INCREF(__pyx_v_feature_results);
  __pyx_r = __pyx_v_feature_results;
  goto __pyx_L0;
 242: 
 243: 
 244: @cython.boundscheck(False)
 245: @cython.wraparound(False)
+246: cdef void update_col_all_mistakes_histogram_sorted(
static void __pyx_f_5d_imm_9splitters_10cut_finder_update_col_all_mistakes_histogram_sorted(__Pyx_memviewslice __pyx_v_X, __Pyx_memviewslice __pyx_v_y, __Pyx_memviewslice __pyx_v_centers, __Pyx_memviewslice __pyx_v_valid_centers, int __pyx_v_col, int __pyx_v_n, int __pyx_v_k, PyObject *__pyx_v_feature_results, PyObject *__pyx_v_histogram) {
  int __pyx_v_i;
  int __pyx_v_ix;
  CYTHON_UNUSED int __pyx_v_ic;
  int __pyx_v_mistakes;
  __pyx_t_5d_imm_9splitters_10cut_finder_NP_FLOAT_t __pyx_v_threshold;
  __Pyx_memviewslice __pyx_v_data_order = { 0, 0, { 0 }, { 0 }, { 0 } };
  CYTHON_UNUSED __Pyx_memviewslice __pyx_v_centers_order = { 0, 0, { 0 }, { 0 }, { 0 } };
  int __pyx_v_num_thresholds;
  __pyx_t_5d_imm_9splitters_10cut_finder_NP_FLOAT_t *__pyx_v_combined_thresholds;
  __pyx_t_5d_imm_9splitters_10cut_finder_NP_FLOAT_t __pyx_v_max_val;
  __pyx_t_5d_imm_9splitters_10cut_finder_NP_FLOAT_t __pyx_v_min_val;
  PyObject *__pyx_v_unique_thresholds = NULL;
  PyObject *__pyx_v_split = NULL;
  PyObject *__pyx_v_sorted_thresholds = NULL;
/* … */
  /* function exit code */
  goto __pyx_L0;
  __pyx_L1_error:;
  #ifdef WITH_THREAD
  __pyx_gilstate_save = __Pyx_PyGILState_Ensure();
  #endif
  __Pyx_XDECREF(__pyx_t_7);
  __Pyx_XDECREF(__pyx_t_8);
  __Pyx_XDECREF(__pyx_t_9);
  __Pyx_XDECREF(__pyx_t_10);
  __PYX_XCLEAR_MEMVIEW(&__pyx_t_11, 1);
  __Pyx_XDECREF(__pyx_t_12);
  __PYX_XCLEAR_MEMVIEW(&__pyx_t_14, 1);
  __Pyx_AddTraceback("d_imm.splitters.cut_finder.update_col_all_mistakes_histogram_sorted", __pyx_clineno, __pyx_lineno, __pyx_filename);
  #ifdef WITH_THREAD
  __Pyx_PyGILState_Release(__pyx_gilstate_save);
  #endif
  __pyx_L0:;
  __PYX_XCLEAR_MEMVIEW(&__pyx_v_data_order, 0);
  __PYX_XCLEAR_MEMVIEW(&__pyx_v_centers_order, 0);
  #ifdef WITH_THREAD
  __pyx_gilstate_save = __Pyx_PyGILState_Ensure();
  #endif
  __Pyx_XDECREF(__pyx_v_unique_thresholds);
  __Pyx_XDECREF(__pyx_v_split);
  __Pyx_XDECREF(__pyx_v_sorted_thresholds);
  __Pyx_RefNannyFinishContext();
  #ifdef WITH_THREAD
  __Pyx_PyGILState_Release(__pyx_gilstate_save);
  #endif
}
 247:     NP_FLOAT_t[:,:] X, NP_INT_t[:] y, NP_FLOAT_t[:,:] centers,
 248:     NP_INT_t[:] valid_centers,
 249:     int col, int n, int k,
 250:     list feature_results, list histogram) nogil:  # Marked as noexcept
 251:     """
 252:     Helper function to calculate mistakes for a single column using histogram-based and center-based thresholds.
 253:     Appends the results as Python dictionaries to feature_results.
 254:     """
 255:     cdef int i
+256:     cdef int ix = 0
  __pyx_v_ix = 0;
+257:     cdef int ic = 0
  __pyx_v_ic = 0;
+258:     cdef int mistakes = 0
  __pyx_v_mistakes = 0;
 259:     cdef NP_FLOAT_t threshold
 260:     cdef np.int64_t[:] data_order
 261:     cdef np.int64_t[:] centers_order
 262:     cdef int num_thresholds
 263:     cdef NP_FLOAT_t *combined_thresholds
 264:     cdef NP_FLOAT_t max_val
 265:     cdef NP_FLOAT_t min_val
 266: 
 267:     # Find the maximum and minimum valid center values
+268:     max_val = -INFINITY
  __pyx_v_max_val = (-INFINITY);
+269:     min_val = INFINITY
  __pyx_v_min_val = INFINITY;
 270: 
+271:     for i in range(k):
  __pyx_t_1 = __pyx_v_k;
  __pyx_t_2 = __pyx_t_1;
  for (__pyx_t_3 = 0; __pyx_t_3 < __pyx_t_2; __pyx_t_3+=1) {
    __pyx_v_i = __pyx_t_3;
+272:         if valid_centers[i] == 1:
    __pyx_t_4 = __pyx_v_i;
    __pyx_t_5 = ((*((__pyx_t_5d_imm_9splitters_10cut_finder_NP_INT_t *) ( /* dim=0 */ (__pyx_v_valid_centers.data + __pyx_t_4 * __pyx_v_valid_centers.strides[0]) ))) == 1);
    if (__pyx_t_5) {
/* … */
    }
  }
+273:             if centers[i, col] > max_val:
      __pyx_t_4 = __pyx_v_i;
      __pyx_t_6 = __pyx_v_col;
      __pyx_t_5 = ((*((__pyx_t_5d_imm_9splitters_10cut_finder_NP_FLOAT_t *) ( /* dim=1 */ (( /* dim=0 */ (__pyx_v_centers.data + __pyx_t_4 * __pyx_v_centers.strides[0]) ) + __pyx_t_6 * __pyx_v_centers.strides[1]) ))) > __pyx_v_max_val);
      if (__pyx_t_5) {
/* … */
      }
+274:                 max_val = centers[i, col]
        __pyx_t_6 = __pyx_v_i;
        __pyx_t_4 = __pyx_v_col;
        __pyx_v_max_val = (*((__pyx_t_5d_imm_9splitters_10cut_finder_NP_FLOAT_t *) ( /* dim=1 */ (( /* dim=0 */ (__pyx_v_centers.data + __pyx_t_6 * __pyx_v_centers.strides[0]) ) + __pyx_t_4 * __pyx_v_centers.strides[1]) )));
+275:             if centers[i, col] < min_val:
      __pyx_t_4 = __pyx_v_i;
      __pyx_t_6 = __pyx_v_col;
      __pyx_t_5 = ((*((__pyx_t_5d_imm_9splitters_10cut_finder_NP_FLOAT_t *) ( /* dim=1 */ (( /* dim=0 */ (__pyx_v_centers.data + __pyx_t_4 * __pyx_v_centers.strides[0]) ) + __pyx_t_6 * __pyx_v_centers.strides[1]) ))) < __pyx_v_min_val);
      if (__pyx_t_5) {
/* … */
      }
+276:                 min_val = centers[i, col]
        __pyx_t_6 = __pyx_v_i;
        __pyx_t_4 = __pyx_v_col;
        __pyx_v_min_val = (*((__pyx_t_5d_imm_9splitters_10cut_finder_NP_FLOAT_t *) ( /* dim=1 */ (( /* dim=0 */ (__pyx_v_centers.data + __pyx_t_6 * __pyx_v_centers.strides[0]) ) + __pyx_t_4 * __pyx_v_centers.strides[1]) )));
 277: 
 278:     # Sorting and threshold combination
+279:     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_L10;
        }
        __pyx_L9_error: {
          #ifdef WITH_THREAD
          __Pyx_PyGILState_Release(__pyx_gilstate_save);
          #endif
          goto __pyx_L1_error;
        }
        __pyx_L10:;
      }
  }
+280:         data_order = np.asarray(X[:, col]).argsort()
        __Pyx_GetModuleGlobalName(__pyx_t_9, __pyx_n_s_np); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 280, __pyx_L9_error)
        __Pyx_GOTREF(__pyx_t_9);
        __pyx_t_10 = __Pyx_PyObject_GetAttrStr(__pyx_t_9, __pyx_n_s_asarray); if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 280, __pyx_L9_error)
        __Pyx_GOTREF(__pyx_t_10);
        __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
        __pyx_t_11.data = __pyx_v_X.data;
        __pyx_t_11.memview = __pyx_v_X.memview;
        __PYX_INC_MEMVIEW(&__pyx_t_11, 1);
        __pyx_t_11.shape[0] = __pyx_v_X.shape[0];
__pyx_t_11.strides[0] = __pyx_v_X.strides[0];
    __pyx_t_11.suboffsets[0] = -1;

{
    Py_ssize_t __pyx_tmp_idx = __pyx_v_col;
    Py_ssize_t __pyx_tmp_stride = __pyx_v_X.strides[1];
        __pyx_t_11.data += __pyx_tmp_idx * __pyx_tmp_stride;
}

__pyx_t_9 = __pyx_memoryview_fromslice(__pyx_t_11, 1, (PyObject *(*)(char *)) __pyx_memview_get_nn___pyx_t_5d_imm_9splitters_10cut_finder_NP_FLOAT_t, (int (*)(char *, PyObject *)) __pyx_memview_set_nn___pyx_t_5d_imm_9splitters_10cut_finder_NP_FLOAT_t, 0);; if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 280, __pyx_L9_error)
        __Pyx_GOTREF(__pyx_t_9);
        __PYX_XCLEAR_MEMVIEW(&__pyx_t_11, 1);
        __pyx_t_11.memview = NULL; __pyx_t_11.data = NULL;
        __pyx_t_12 = NULL;
        __pyx_t_13 = 0;
        #if CYTHON_UNPACK_METHODS
        if (unlikely(PyMethod_Check(__pyx_t_10))) {
          __pyx_t_12 = PyMethod_GET_SELF(__pyx_t_10);
          if (likely(__pyx_t_12)) {
            PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_10);
            __Pyx_INCREF(__pyx_t_12);
            __Pyx_INCREF(function);
            __Pyx_DECREF_SET(__pyx_t_10, function);
            __pyx_t_13 = 1;
          }
        }
        #endif
        {
          PyObject *__pyx_callargs[2] = {__pyx_t_12, __pyx_t_9};
          __pyx_t_8 = __Pyx_PyObject_FastCall(__pyx_t_10, __pyx_callargs+1-__pyx_t_13, 1+__pyx_t_13);
          __Pyx_XDECREF(__pyx_t_12); __pyx_t_12 = 0;
          __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
          if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 280, __pyx_L9_error)
          __Pyx_GOTREF(__pyx_t_8);
          __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0;
        }
        __pyx_t_10 = __Pyx_PyObject_GetAttrStr(__pyx_t_8, __pyx_n_s_argsort); if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 280, __pyx_L9_error)
        __Pyx_GOTREF(__pyx_t_10);
        __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
        __pyx_t_8 = NULL;
        __pyx_t_13 = 0;
        #if CYTHON_UNPACK_METHODS
        if (likely(PyMethod_Check(__pyx_t_10))) {
          __pyx_t_8 = PyMethod_GET_SELF(__pyx_t_10);
          if (likely(__pyx_t_8)) {
            PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_10);
            __Pyx_INCREF(__pyx_t_8);
            __Pyx_INCREF(function);
            __Pyx_DECREF_SET(__pyx_t_10, function);
            __pyx_t_13 = 1;
          }
        }
        #endif
        {
          PyObject *__pyx_callargs[2] = {__pyx_t_8, NULL};
          __pyx_t_7 = __Pyx_PyObject_FastCall(__pyx_t_10, __pyx_callargs+1-__pyx_t_13, 0+__pyx_t_13);
          __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0;
          if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 280, __pyx_L9_error)
          __Pyx_GOTREF(__pyx_t_7);
          __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0;
        }
        __pyx_t_14 = __Pyx_PyObject_to_MemoryviewSlice_ds_nn___pyx_t_5numpy_int64_t(__pyx_t_7, PyBUF_WRITABLE); if (unlikely(!__pyx_t_14.memview)) __PYX_ERR(0, 280, __pyx_L9_error)
        __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
        __pyx_v_data_order = __pyx_t_14;
        __pyx_t_14.memview = NULL;
        __pyx_t_14.data = NULL;
+281:         centers_order = np.asarray(centers[:, col]).argsort()
        __Pyx_GetModuleGlobalName(__pyx_t_8, __pyx_n_s_np); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 281, __pyx_L9_error)
        __Pyx_GOTREF(__pyx_t_8);
        __pyx_t_9 = __Pyx_PyObject_GetAttrStr(__pyx_t_8, __pyx_n_s_asarray); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 281, __pyx_L9_error)
        __Pyx_GOTREF(__pyx_t_9);
        __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
        __pyx_t_11.data = __pyx_v_centers.data;
        __pyx_t_11.memview = __pyx_v_centers.memview;
        __PYX_INC_MEMVIEW(&__pyx_t_11, 1);
        __pyx_t_11.shape[0] = __pyx_v_centers.shape[0];
__pyx_t_11.strides[0] = __pyx_v_centers.strides[0];
    __pyx_t_11.suboffsets[0] = -1;

{
    Py_ssize_t __pyx_tmp_idx = __pyx_v_col;
    Py_ssize_t __pyx_tmp_stride = __pyx_v_centers.strides[1];
        __pyx_t_11.data += __pyx_tmp_idx * __pyx_tmp_stride;
}

__pyx_t_8 = __pyx_memoryview_fromslice(__pyx_t_11, 1, (PyObject *(*)(char *)) __pyx_memview_get_nn___pyx_t_5d_imm_9splitters_10cut_finder_NP_FLOAT_t, (int (*)(char *, PyObject *)) __pyx_memview_set_nn___pyx_t_5d_imm_9splitters_10cut_finder_NP_FLOAT_t, 0);; if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 281, __pyx_L9_error)
        __Pyx_GOTREF(__pyx_t_8);
        __PYX_XCLEAR_MEMVIEW(&__pyx_t_11, 1);
        __pyx_t_11.memview = NULL; __pyx_t_11.data = NULL;
        __pyx_t_12 = NULL;
        __pyx_t_13 = 0;
        #if CYTHON_UNPACK_METHODS
        if (unlikely(PyMethod_Check(__pyx_t_9))) {
          __pyx_t_12 = PyMethod_GET_SELF(__pyx_t_9);
          if (likely(__pyx_t_12)) {
            PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_9);
            __Pyx_INCREF(__pyx_t_12);
            __Pyx_INCREF(function);
            __Pyx_DECREF_SET(__pyx_t_9, function);
            __pyx_t_13 = 1;
          }
        }
        #endif
        {
          PyObject *__pyx_callargs[2] = {__pyx_t_12, __pyx_t_8};
          __pyx_t_10 = __Pyx_PyObject_FastCall(__pyx_t_9, __pyx_callargs+1-__pyx_t_13, 1+__pyx_t_13);
          __Pyx_XDECREF(__pyx_t_12); __pyx_t_12 = 0;
          __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
          if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 281, __pyx_L9_error)
          __Pyx_GOTREF(__pyx_t_10);
          __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
        }
        __pyx_t_9 = __Pyx_PyObject_GetAttrStr(__pyx_t_10, __pyx_n_s_argsort); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 281, __pyx_L9_error)
        __Pyx_GOTREF(__pyx_t_9);
        __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0;
        __pyx_t_10 = NULL;
        __pyx_t_13 = 0;
        #if CYTHON_UNPACK_METHODS
        if (likely(PyMethod_Check(__pyx_t_9))) {
          __pyx_t_10 = PyMethod_GET_SELF(__pyx_t_9);
          if (likely(__pyx_t_10)) {
            PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_9);
            __Pyx_INCREF(__pyx_t_10);
            __Pyx_INCREF(function);
            __Pyx_DECREF_SET(__pyx_t_9, function);
            __pyx_t_13 = 1;
          }
        }
        #endif
        {
          PyObject *__pyx_callargs[2] = {__pyx_t_10, NULL};
          __pyx_t_7 = __Pyx_PyObject_FastCall(__pyx_t_9, __pyx_callargs+1-__pyx_t_13, 0+__pyx_t_13);
          __Pyx_XDECREF(__pyx_t_10); __pyx_t_10 = 0;
          if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 281, __pyx_L9_error)
          __Pyx_GOTREF(__pyx_t_7);
          __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
        }
        __pyx_t_14 = __Pyx_PyObject_to_MemoryviewSlice_ds_nn___pyx_t_5numpy_int64_t(__pyx_t_7, PyBUF_WRITABLE); if (unlikely(!__pyx_t_14.memview)) __PYX_ERR(0, 281, __pyx_L9_error)
        __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
        __pyx_v_centers_order = __pyx_t_14;
        __pyx_t_14.memview = NULL;
        __pyx_t_14.data = NULL;
 282: 
 283:         # Combine histogram-based and center-based thresholds
+284:         unique_thresholds = set()
        __pyx_t_7 = PySet_New(0); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 284, __pyx_L9_error)
        __Pyx_GOTREF(__pyx_t_7);
        __pyx_v_unique_thresholds = ((PyObject*)__pyx_t_7);
        __pyx_t_7 = 0;
+285:         for split in histogram:
        if (unlikely(__pyx_v_histogram == Py_None)) {
          PyErr_SetString(PyExc_TypeError, "'NoneType' object is not iterable");
          __PYX_ERR(0, 285, __pyx_L9_error)
        }
        __pyx_t_7 = __pyx_v_histogram; __Pyx_INCREF(__pyx_t_7);
        __pyx_t_15 = 0;
        for (;;) {
          {
            Py_ssize_t __pyx_temp = __Pyx_PyList_GET_SIZE(__pyx_t_7);
            #if !CYTHON_ASSUME_SAFE_MACROS
            if (unlikely((__pyx_temp < 0))) __PYX_ERR(0, 285, __pyx_L9_error)
            #endif
            if (__pyx_t_15 >= __pyx_temp) break;
          }
          #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
          __pyx_t_9 = PyList_GET_ITEM(__pyx_t_7, __pyx_t_15); __Pyx_INCREF(__pyx_t_9); __pyx_t_15++; if (unlikely((0 < 0))) __PYX_ERR(0, 285, __pyx_L9_error)
          #else
          __pyx_t_9 = __Pyx_PySequence_ITEM(__pyx_t_7, __pyx_t_15); __pyx_t_15++; if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 285, __pyx_L9_error)
          __Pyx_GOTREF(__pyx_t_9);
          #endif
          __Pyx_XDECREF_SET(__pyx_v_split, __pyx_t_9);
          __pyx_t_9 = 0;
/* … */
        }
        __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
+286:             if min_val <= split.threshold < max_val:
          __pyx_t_9 = PyFloat_FromDouble(__pyx_v_min_val); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 286, __pyx_L9_error)
          __Pyx_GOTREF(__pyx_t_9);
          __pyx_t_10 = __Pyx_PyObject_GetAttrStr(__pyx_v_split, __pyx_n_s_threshold); if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 286, __pyx_L9_error)
          __Pyx_GOTREF(__pyx_t_10);
          __pyx_t_8 = PyObject_RichCompare(__pyx_t_9, __pyx_t_10, Py_LE); __Pyx_XGOTREF(__pyx_t_8); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 286, __pyx_L9_error)
          if (__Pyx_PyObject_IsTrue(__pyx_t_8)) {
            __Pyx_DECREF(__pyx_t_8);
            __pyx_t_12 = PyFloat_FromDouble(__pyx_v_max_val); if (unlikely(!__pyx_t_12)) __PYX_ERR(0, 286, __pyx_L9_error)
            __Pyx_GOTREF(__pyx_t_12);
            __pyx_t_8 = PyObject_RichCompare(__pyx_t_10, __pyx_t_12, Py_LT); __Pyx_XGOTREF(__pyx_t_8); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 286, __pyx_L9_error)
            __Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;
          }
          __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
          __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0;
          __pyx_t_5 = __Pyx_PyObject_IsTrue(__pyx_t_8); if (unlikely((__pyx_t_5 < 0))) __PYX_ERR(0, 286, __pyx_L9_error)
          __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
          if (__pyx_t_5) {
/* … */
          }
+287:                 unique_thresholds.add(split.threshold)
            __pyx_t_8 = __Pyx_PyObject_GetAttrStr(__pyx_v_split, __pyx_n_s_threshold); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 287, __pyx_L9_error)
            __Pyx_GOTREF(__pyx_t_8);
            __pyx_t_16 = PySet_Add(__pyx_v_unique_thresholds, __pyx_t_8); if (unlikely(__pyx_t_16 == ((int)-1))) __PYX_ERR(0, 287, __pyx_L9_error)
            __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
 288: 
+289:         for i in range(k):
        __pyx_t_1 = __pyx_v_k;
        __pyx_t_2 = __pyx_t_1;
        for (__pyx_t_3 = 0; __pyx_t_3 < __pyx_t_2; __pyx_t_3+=1) {
          __pyx_v_i = __pyx_t_3;
+290:             if valid_centers[i] == 1 and centers[i, col]!=max_val:
          __pyx_t_4 = __pyx_v_i;
          __pyx_t_17 = ((*((__pyx_t_5d_imm_9splitters_10cut_finder_NP_INT_t *) ( /* dim=0 */ (__pyx_v_valid_centers.data + __pyx_t_4 * __pyx_v_valid_centers.strides[0]) ))) == 1);
          if (__pyx_t_17) {
          } else {
            __pyx_t_5 = __pyx_t_17;
            goto __pyx_L18_bool_binop_done;
          }
          __pyx_t_4 = __pyx_v_i;
          __pyx_t_6 = __pyx_v_col;
          __pyx_t_17 = ((*((__pyx_t_5d_imm_9splitters_10cut_finder_NP_FLOAT_t *) ( /* dim=1 */ (( /* dim=0 */ (__pyx_v_centers.data + __pyx_t_4 * __pyx_v_centers.strides[0]) ) + __pyx_t_6 * __pyx_v_centers.strides[1]) ))) != __pyx_v_max_val);
          __pyx_t_5 = __pyx_t_17;
          __pyx_L18_bool_binop_done:;
          if (__pyx_t_5) {
/* … */
          }
        }
+291:                 unique_thresholds.add(centers[i, col])
            __pyx_t_6 = __pyx_v_i;
            __pyx_t_4 = __pyx_v_col;
            __pyx_t_7 = PyFloat_FromDouble((*((__pyx_t_5d_imm_9splitters_10cut_finder_NP_FLOAT_t *) ( /* dim=1 */ (( /* dim=0 */ (__pyx_v_centers.data + __pyx_t_6 * __pyx_v_centers.strides[0]) ) + __pyx_t_4 * __pyx_v_centers.strides[1]) )))); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 291, __pyx_L9_error)
            __Pyx_GOTREF(__pyx_t_7);
            __pyx_t_16 = PySet_Add(__pyx_v_unique_thresholds, __pyx_t_7); if (unlikely(__pyx_t_16 == ((int)-1))) __PYX_ERR(0, 291, __pyx_L9_error)
            __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
 292: 
+293:         sorted_thresholds = sorted(unique_thresholds)
        __pyx_t_8 = PySequence_List(__pyx_v_unique_thresholds); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 293, __pyx_L9_error)
        __Pyx_GOTREF(__pyx_t_8);
        __pyx_t_7 = ((PyObject*)__pyx_t_8);
        __pyx_t_8 = 0;
        __pyx_t_16 = PyList_Sort(__pyx_t_7); if (unlikely(__pyx_t_16 == ((int)-1))) __PYX_ERR(0, 293, __pyx_L9_error)
        __pyx_v_sorted_thresholds = ((PyObject*)__pyx_t_7);
        __pyx_t_7 = 0;
 294: 
+295:         num_thresholds = len(sorted_thresholds)
        __pyx_t_15 = __Pyx_PyList_GET_SIZE(__pyx_v_sorted_thresholds); if (unlikely(__pyx_t_15 == ((Py_ssize_t)-1))) __PYX_ERR(0, 295, __pyx_L9_error)
        __pyx_v_num_thresholds = __pyx_t_15;
+296:         combined_thresholds = <NP_FLOAT_t *> malloc(num_thresholds * sizeof(NP_FLOAT_t))
        __pyx_v_combined_thresholds = ((__pyx_t_5d_imm_9splitters_10cut_finder_NP_FLOAT_t *)malloc((__pyx_v_num_thresholds * (sizeof(__pyx_t_5d_imm_9splitters_10cut_finder_NP_FLOAT_t)))));
 297: 
+298:         for i in range(num_thresholds):
        __pyx_t_1 = __pyx_v_num_thresholds;
        __pyx_t_2 = __pyx_t_1;
        for (__pyx_t_3 = 0; __pyx_t_3 < __pyx_t_2; __pyx_t_3+=1) {
          __pyx_v_i = __pyx_t_3;
+299:             combined_thresholds[i] = sorted_thresholds[i]
          __pyx_t_18 = __pyx_PyFloat_AsDouble(PyList_GET_ITEM(__pyx_v_sorted_thresholds, __pyx_v_i)); if (unlikely((__pyx_t_18 == ((npy_float64)-1)) && PyErr_Occurred())) __PYX_ERR(0, 299, __pyx_L9_error)
          (__pyx_v_combined_thresholds[__pyx_v_i]) = __pyx_t_18;
        }
      }
 300: 
 301:     # Process each threshold
+302:     for i in range(num_thresholds):
  __pyx_t_1 = __pyx_v_num_thresholds;
  __pyx_t_2 = __pyx_t_1;
  for (__pyx_t_3 = 0; __pyx_t_3 < __pyx_t_2; __pyx_t_3+=1) {
    __pyx_v_i = __pyx_t_3;
+303:         mistakes = 0
    __pyx_v_mistakes = 0;
+304:         ix = 0
    __pyx_v_ix = 0;
+305:         threshold = combined_thresholds[i]
    __pyx_v_threshold = (__pyx_v_combined_thresholds[__pyx_v_i]);
 306: 
 307:         # Count mistakes
+308:         while ix < n:
    while (1) {
      __pyx_t_5 = (__pyx_v_ix < __pyx_v_n);
      if (!__pyx_t_5) break;
+309:             if X[data_order[ix], col] <= threshold:
      __pyx_t_4 = __pyx_v_ix;
      __pyx_t_19 = (*((__pyx_t_5numpy_int64_t *) ( /* dim=0 */ (__pyx_v_data_order.data + __pyx_t_4 * __pyx_v_data_order.strides[0]) )));
      __pyx_t_6 = __pyx_v_col;
      __pyx_t_5 = ((*((__pyx_t_5d_imm_9splitters_10cut_finder_NP_FLOAT_t *) ( /* dim=1 */ (( /* dim=0 */ (__pyx_v_X.data + __pyx_t_19 * __pyx_v_X.strides[0]) ) + __pyx_t_6 * __pyx_v_X.strides[1]) ))) <= __pyx_v_threshold);
      if (__pyx_t_5) {
/* … */
        goto __pyx_L26;
      }
+310:                 if centers[y[data_order[ix]], col] > threshold:
        __pyx_t_4 = __pyx_v_ix;
        __pyx_t_19 = (*((__pyx_t_5numpy_int64_t *) ( /* dim=0 */ (__pyx_v_data_order.data + __pyx_t_4 * __pyx_v_data_order.strides[0]) )));
        __pyx_t_6 = (*((__pyx_t_5d_imm_9splitters_10cut_finder_NP_INT_t *) ( /* dim=0 */ (__pyx_v_y.data + __pyx_t_19 * __pyx_v_y.strides[0]) )));
        __pyx_t_20 = __pyx_v_col;
        __pyx_t_5 = ((*((__pyx_t_5d_imm_9splitters_10cut_finder_NP_FLOAT_t *) ( /* dim=1 */ (( /* dim=0 */ (__pyx_v_centers.data + __pyx_t_6 * __pyx_v_centers.strides[0]) ) + __pyx_t_20 * __pyx_v_centers.strides[1]) ))) > __pyx_v_threshold);
        if (__pyx_t_5) {
/* … */
        }
+311:                     mistakes += 1
          __pyx_v_mistakes = (__pyx_v_mistakes + 1);
 312:             else:
+313:                 if centers[y[data_order[ix]], col] <= threshold:
      /*else*/ {
        __pyx_t_4 = __pyx_v_ix;
        __pyx_t_19 = (*((__pyx_t_5numpy_int64_t *) ( /* dim=0 */ (__pyx_v_data_order.data + __pyx_t_4 * __pyx_v_data_order.strides[0]) )));
        __pyx_t_20 = (*((__pyx_t_5d_imm_9splitters_10cut_finder_NP_INT_t *) ( /* dim=0 */ (__pyx_v_y.data + __pyx_t_19 * __pyx_v_y.strides[0]) )));
        __pyx_t_6 = __pyx_v_col;
        __pyx_t_5 = ((*((__pyx_t_5d_imm_9splitters_10cut_finder_NP_FLOAT_t *) ( /* dim=1 */ (( /* dim=0 */ (__pyx_v_centers.data + __pyx_t_20 * __pyx_v_centers.strides[0]) ) + __pyx_t_6 * __pyx_v_centers.strides[1]) ))) <= __pyx_v_threshold);
        if (__pyx_t_5) {
/* … */
        }
      }
      __pyx_L26:;
+314:                     mistakes += 1
          __pyx_v_mistakes = (__pyx_v_mistakes + 1);
+315:             ix += 1
      __pyx_v_ix = (__pyx_v_ix + 1);
    }
 316: 
 317:         # Store result
+318:         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_L33;
          }
          __pyx_L32_error: {
            #ifdef WITH_THREAD
            __Pyx_PyGILState_Release(__pyx_gilstate_save);
            #endif
            goto __pyx_L1_error;
          }
          __pyx_L33:;
        }
    }
  }
+319:             feature_results.append({
          if (unlikely(__pyx_v_feature_results == Py_None)) {
            PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "append");
            __PYX_ERR(0, 319, __pyx_L32_error)
          }
/* … */
          __pyx_t_16 = __Pyx_PyList_Append(__pyx_v_feature_results, __pyx_t_7); if (unlikely(__pyx_t_16 == ((int)-1))) __PYX_ERR(0, 319, __pyx_L32_error)
          __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
        }
+320:                 'feature': col,
          __pyx_t_7 = __Pyx_PyDict_NewPresized(3); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 320, __pyx_L32_error)
          __Pyx_GOTREF(__pyx_t_7);
          __pyx_t_8 = __Pyx_PyInt_From_int(__pyx_v_col); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 320, __pyx_L32_error)
          __Pyx_GOTREF(__pyx_t_8);
          if (PyDict_SetItem(__pyx_t_7, __pyx_n_s_feature, __pyx_t_8) < 0) __PYX_ERR(0, 320, __pyx_L32_error)
          __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
+321:                 'threshold': threshold,
          __pyx_t_8 = PyFloat_FromDouble(__pyx_v_threshold); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 321, __pyx_L32_error)
          __Pyx_GOTREF(__pyx_t_8);
          if (PyDict_SetItem(__pyx_t_7, __pyx_n_s_threshold, __pyx_t_8) < 0) __PYX_ERR(0, 320, __pyx_L32_error)
          __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
+322:                 'mistakes': mistakes
          __pyx_t_8 = __Pyx_PyInt_From_int(__pyx_v_mistakes); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 322, __pyx_L32_error)
          __Pyx_GOTREF(__pyx_t_8);
          if (PyDict_SetItem(__pyx_t_7, __pyx_n_s_mistakes, __pyx_t_8) < 0) __PYX_ERR(0, 320, __pyx_L32_error)
          __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
 323:             })
 324: 
+325:     free(combined_thresholds)
  free(__pyx_v_combined_thresholds);
 326: 
 327: 
 328: @cython.boundscheck(False)
 329: @cython.wraparound(False)
+330: cdef void update_col_all_mistakes_histogram_unsorted(
static void __pyx_f_5d_imm_9splitters_10cut_finder_update_col_all_mistakes_histogram_unsorted(__Pyx_memviewslice __pyx_v_X, __Pyx_memviewslice __pyx_v_y, __Pyx_memviewslice __pyx_v_centers, __Pyx_memviewslice __pyx_v_valid_centers, int __pyx_v_col, int __pyx_v_n, int __pyx_v_k, PyObject *__pyx_v_feature_results, PyObject *__pyx_v_histogram) {
  int __pyx_v_i;
  int __pyx_v_ix;
  CYTHON_UNUSED int __pyx_v_ic;
  int __pyx_v_mistakes;
  __pyx_t_5d_imm_9splitters_10cut_finder_NP_FLOAT_t __pyx_v_threshold;
  CYTHON_UNUSED __Pyx_memviewslice __pyx_v_centers_order = { 0, 0, { 0 }, { 0 }, { 0 } };
  int __pyx_v_num_thresholds;
  __pyx_t_5d_imm_9splitters_10cut_finder_NP_FLOAT_t *__pyx_v_combined_thresholds;
  __pyx_t_5d_imm_9splitters_10cut_finder_NP_FLOAT_t __pyx_v_max_val;
  __pyx_t_5d_imm_9splitters_10cut_finder_NP_FLOAT_t __pyx_v_min_val;
  PyObject *__pyx_v_unique_thresholds = NULL;
  PyObject *__pyx_v_split = NULL;
  PyObject *__pyx_v_sorted_thresholds = NULL;
/* … */
  /* function exit code */
  goto __pyx_L0;
  __pyx_L1_error:;
  #ifdef WITH_THREAD
  __pyx_gilstate_save = __Pyx_PyGILState_Ensure();
  #endif
  __Pyx_XDECREF(__pyx_t_7);
  __Pyx_XDECREF(__pyx_t_8);
  __Pyx_XDECREF(__pyx_t_9);
  __Pyx_XDECREF(__pyx_t_10);
  __PYX_XCLEAR_MEMVIEW(&__pyx_t_11, 1);
  __Pyx_XDECREF(__pyx_t_12);
  __PYX_XCLEAR_MEMVIEW(&__pyx_t_14, 1);
  __Pyx_AddTraceback("d_imm.splitters.cut_finder.update_col_all_mistakes_histogram_unsorted", __pyx_clineno, __pyx_lineno, __pyx_filename);
  #ifdef WITH_THREAD
  __Pyx_PyGILState_Release(__pyx_gilstate_save);
  #endif
  __pyx_L0:;
  __PYX_XCLEAR_MEMVIEW(&__pyx_v_centers_order, 0);
  #ifdef WITH_THREAD
  __pyx_gilstate_save = __Pyx_PyGILState_Ensure();
  #endif
  __Pyx_XDECREF(__pyx_v_unique_thresholds);
  __Pyx_XDECREF(__pyx_v_split);
  __Pyx_XDECREF(__pyx_v_sorted_thresholds);
  __Pyx_RefNannyFinishContext();
  #ifdef WITH_THREAD
  __Pyx_PyGILState_Release(__pyx_gilstate_save);
  #endif
}
 331:     NP_FLOAT_t[:,:] X, NP_INT_t[:] y, NP_FLOAT_t[:,:] centers,
 332:     NP_INT_t[:] valid_centers,
 333:     int col, int n, int k,
 334:     list feature_results, list histogram) nogil:  # Marked as noexcept
 335:     """
 336:     Helper function to calculate mistakes for a single column using histogram-based and center-based thresholds.
 337:     Appends the results as Python dictionaries to feature_results.
 338:     """
 339:     cdef int i
+340:     cdef int ix = 0
  __pyx_v_ix = 0;
+341:     cdef int ic = 0
  __pyx_v_ic = 0;
+342:     cdef int mistakes = 0
  __pyx_v_mistakes = 0;
 343:     cdef NP_FLOAT_t threshold
 344:     cdef np.int64_t[:] centers_order
 345:     cdef int num_thresholds
 346:     cdef NP_FLOAT_t *combined_thresholds
 347:     cdef NP_FLOAT_t max_val
 348:     cdef NP_FLOAT_t min_val
 349: 
 350:     # Find the maximum and minimum valid center values
+351:     max_val = -INFINITY
  __pyx_v_max_val = (-INFINITY);
+352:     min_val = INFINITY
  __pyx_v_min_val = INFINITY;
 353: 
+354:     for i in range(k):
  __pyx_t_1 = __pyx_v_k;
  __pyx_t_2 = __pyx_t_1;
  for (__pyx_t_3 = 0; __pyx_t_3 < __pyx_t_2; __pyx_t_3+=1) {
    __pyx_v_i = __pyx_t_3;
+355:         if valid_centers[i] == 1:
    __pyx_t_4 = __pyx_v_i;
    __pyx_t_5 = ((*((__pyx_t_5d_imm_9splitters_10cut_finder_NP_INT_t *) ( /* dim=0 */ (__pyx_v_valid_centers.data + __pyx_t_4 * __pyx_v_valid_centers.strides[0]) ))) == 1);
    if (__pyx_t_5) {
/* … */
    }
  }
+356:             if centers[i, col] > max_val:
      __pyx_t_4 = __pyx_v_i;
      __pyx_t_6 = __pyx_v_col;
      __pyx_t_5 = ((*((__pyx_t_5d_imm_9splitters_10cut_finder_NP_FLOAT_t *) ( /* dim=1 */ (( /* dim=0 */ (__pyx_v_centers.data + __pyx_t_4 * __pyx_v_centers.strides[0]) ) + __pyx_t_6 * __pyx_v_centers.strides[1]) ))) > __pyx_v_max_val);
      if (__pyx_t_5) {
/* … */
      }
+357:                 max_val = centers[i, col]
        __pyx_t_6 = __pyx_v_i;
        __pyx_t_4 = __pyx_v_col;
        __pyx_v_max_val = (*((__pyx_t_5d_imm_9splitters_10cut_finder_NP_FLOAT_t *) ( /* dim=1 */ (( /* dim=0 */ (__pyx_v_centers.data + __pyx_t_6 * __pyx_v_centers.strides[0]) ) + __pyx_t_4 * __pyx_v_centers.strides[1]) )));
+358:             if centers[i, col] < min_val:
      __pyx_t_4 = __pyx_v_i;
      __pyx_t_6 = __pyx_v_col;
      __pyx_t_5 = ((*((__pyx_t_5d_imm_9splitters_10cut_finder_NP_FLOAT_t *) ( /* dim=1 */ (( /* dim=0 */ (__pyx_v_centers.data + __pyx_t_4 * __pyx_v_centers.strides[0]) ) + __pyx_t_6 * __pyx_v_centers.strides[1]) ))) < __pyx_v_min_val);
      if (__pyx_t_5) {
/* … */
      }
+359:                 min_val = centers[i, col]
        __pyx_t_6 = __pyx_v_i;
        __pyx_t_4 = __pyx_v_col;
        __pyx_v_min_val = (*((__pyx_t_5d_imm_9splitters_10cut_finder_NP_FLOAT_t *) ( /* dim=1 */ (( /* dim=0 */ (__pyx_v_centers.data + __pyx_t_6 * __pyx_v_centers.strides[0]) ) + __pyx_t_4 * __pyx_v_centers.strides[1]) )));
 360: 
 361:     # Sorting and threshold combination
+362:     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_L10;
        }
        __pyx_L9_error: {
          #ifdef WITH_THREAD
          __Pyx_PyGILState_Release(__pyx_gilstate_save);
          #endif
          goto __pyx_L1_error;
        }
        __pyx_L10:;
      }
  }
+363:         centers_order = np.asarray(centers[:, col]).argsort()
        __Pyx_GetModuleGlobalName(__pyx_t_9, __pyx_n_s_np); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 363, __pyx_L9_error)
        __Pyx_GOTREF(__pyx_t_9);
        __pyx_t_10 = __Pyx_PyObject_GetAttrStr(__pyx_t_9, __pyx_n_s_asarray); if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 363, __pyx_L9_error)
        __Pyx_GOTREF(__pyx_t_10);
        __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
        __pyx_t_11.data = __pyx_v_centers.data;
        __pyx_t_11.memview = __pyx_v_centers.memview;
        __PYX_INC_MEMVIEW(&__pyx_t_11, 1);
        __pyx_t_11.shape[0] = __pyx_v_centers.shape[0];
__pyx_t_11.strides[0] = __pyx_v_centers.strides[0];
    __pyx_t_11.suboffsets[0] = -1;

{
    Py_ssize_t __pyx_tmp_idx = __pyx_v_col;
    Py_ssize_t __pyx_tmp_stride = __pyx_v_centers.strides[1];
        __pyx_t_11.data += __pyx_tmp_idx * __pyx_tmp_stride;
}

__pyx_t_9 = __pyx_memoryview_fromslice(__pyx_t_11, 1, (PyObject *(*)(char *)) __pyx_memview_get_nn___pyx_t_5d_imm_9splitters_10cut_finder_NP_FLOAT_t, (int (*)(char *, PyObject *)) __pyx_memview_set_nn___pyx_t_5d_imm_9splitters_10cut_finder_NP_FLOAT_t, 0);; if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 363, __pyx_L9_error)
        __Pyx_GOTREF(__pyx_t_9);
        __PYX_XCLEAR_MEMVIEW(&__pyx_t_11, 1);
        __pyx_t_11.memview = NULL; __pyx_t_11.data = NULL;
        __pyx_t_12 = NULL;
        __pyx_t_13 = 0;
        #if CYTHON_UNPACK_METHODS
        if (unlikely(PyMethod_Check(__pyx_t_10))) {
          __pyx_t_12 = PyMethod_GET_SELF(__pyx_t_10);
          if (likely(__pyx_t_12)) {
            PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_10);
            __Pyx_INCREF(__pyx_t_12);
            __Pyx_INCREF(function);
            __Pyx_DECREF_SET(__pyx_t_10, function);
            __pyx_t_13 = 1;
          }
        }
        #endif
        {
          PyObject *__pyx_callargs[2] = {__pyx_t_12, __pyx_t_9};
          __pyx_t_8 = __Pyx_PyObject_FastCall(__pyx_t_10, __pyx_callargs+1-__pyx_t_13, 1+__pyx_t_13);
          __Pyx_XDECREF(__pyx_t_12); __pyx_t_12 = 0;
          __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
          if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 363, __pyx_L9_error)
          __Pyx_GOTREF(__pyx_t_8);
          __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0;
        }
        __pyx_t_10 = __Pyx_PyObject_GetAttrStr(__pyx_t_8, __pyx_n_s_argsort); if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 363, __pyx_L9_error)
        __Pyx_GOTREF(__pyx_t_10);
        __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
        __pyx_t_8 = NULL;
        __pyx_t_13 = 0;
        #if CYTHON_UNPACK_METHODS
        if (likely(PyMethod_Check(__pyx_t_10))) {
          __pyx_t_8 = PyMethod_GET_SELF(__pyx_t_10);
          if (likely(__pyx_t_8)) {
            PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_10);
            __Pyx_INCREF(__pyx_t_8);
            __Pyx_INCREF(function);
            __Pyx_DECREF_SET(__pyx_t_10, function);
            __pyx_t_13 = 1;
          }
        }
        #endif
        {
          PyObject *__pyx_callargs[2] = {__pyx_t_8, NULL};
          __pyx_t_7 = __Pyx_PyObject_FastCall(__pyx_t_10, __pyx_callargs+1-__pyx_t_13, 0+__pyx_t_13);
          __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0;
          if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 363, __pyx_L9_error)
          __Pyx_GOTREF(__pyx_t_7);
          __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0;
        }
        __pyx_t_14 = __Pyx_PyObject_to_MemoryviewSlice_ds_nn___pyx_t_5numpy_int64_t(__pyx_t_7, PyBUF_WRITABLE); if (unlikely(!__pyx_t_14.memview)) __PYX_ERR(0, 363, __pyx_L9_error)
        __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
        __pyx_v_centers_order = __pyx_t_14;
        __pyx_t_14.memview = NULL;
        __pyx_t_14.data = NULL;
 364: 
 365:         # Combine histogram-based and center-based thresholds
+366:         unique_thresholds = set()
        __pyx_t_7 = PySet_New(0); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 366, __pyx_L9_error)
        __Pyx_GOTREF(__pyx_t_7);
        __pyx_v_unique_thresholds = ((PyObject*)__pyx_t_7);
        __pyx_t_7 = 0;
+367:         for split in histogram:
        if (unlikely(__pyx_v_histogram == Py_None)) {
          PyErr_SetString(PyExc_TypeError, "'NoneType' object is not iterable");
          __PYX_ERR(0, 367, __pyx_L9_error)
        }
        __pyx_t_7 = __pyx_v_histogram; __Pyx_INCREF(__pyx_t_7);
        __pyx_t_15 = 0;
        for (;;) {
          {
            Py_ssize_t __pyx_temp = __Pyx_PyList_GET_SIZE(__pyx_t_7);
            #if !CYTHON_ASSUME_SAFE_MACROS
            if (unlikely((__pyx_temp < 0))) __PYX_ERR(0, 367, __pyx_L9_error)
            #endif
            if (__pyx_t_15 >= __pyx_temp) break;
          }
          #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
          __pyx_t_10 = PyList_GET_ITEM(__pyx_t_7, __pyx_t_15); __Pyx_INCREF(__pyx_t_10); __pyx_t_15++; if (unlikely((0 < 0))) __PYX_ERR(0, 367, __pyx_L9_error)
          #else
          __pyx_t_10 = __Pyx_PySequence_ITEM(__pyx_t_7, __pyx_t_15); __pyx_t_15++; if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 367, __pyx_L9_error)
          __Pyx_GOTREF(__pyx_t_10);
          #endif
          __Pyx_XDECREF_SET(__pyx_v_split, __pyx_t_10);
          __pyx_t_10 = 0;
/* … */
        }
        __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
+368:             if min_val <= split.threshold < max_val:
          __pyx_t_10 = PyFloat_FromDouble(__pyx_v_min_val); if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 368, __pyx_L9_error)
          __Pyx_GOTREF(__pyx_t_10);
          __pyx_t_8 = __Pyx_PyObject_GetAttrStr(__pyx_v_split, __pyx_n_s_threshold); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 368, __pyx_L9_error)
          __Pyx_GOTREF(__pyx_t_8);
          __pyx_t_9 = PyObject_RichCompare(__pyx_t_10, __pyx_t_8, Py_LE); __Pyx_XGOTREF(__pyx_t_9); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 368, __pyx_L9_error)
          if (__Pyx_PyObject_IsTrue(__pyx_t_9)) {
            __Pyx_DECREF(__pyx_t_9);
            __pyx_t_12 = PyFloat_FromDouble(__pyx_v_max_val); if (unlikely(!__pyx_t_12)) __PYX_ERR(0, 368, __pyx_L9_error)
            __Pyx_GOTREF(__pyx_t_12);
            __pyx_t_9 = PyObject_RichCompare(__pyx_t_8, __pyx_t_12, Py_LT); __Pyx_XGOTREF(__pyx_t_9); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 368, __pyx_L9_error)
            __Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;
          }
          __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0;
          __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
          __pyx_t_5 = __Pyx_PyObject_IsTrue(__pyx_t_9); if (unlikely((__pyx_t_5 < 0))) __PYX_ERR(0, 368, __pyx_L9_error)
          __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
          if (__pyx_t_5) {
/* … */
          }
+369:                 unique_thresholds.add(split.threshold)
            __pyx_t_9 = __Pyx_PyObject_GetAttrStr(__pyx_v_split, __pyx_n_s_threshold); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 369, __pyx_L9_error)
            __Pyx_GOTREF(__pyx_t_9);
            __pyx_t_16 = PySet_Add(__pyx_v_unique_thresholds, __pyx_t_9); if (unlikely(__pyx_t_16 == ((int)-1))) __PYX_ERR(0, 369, __pyx_L9_error)
            __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
 370: 
+371:         for i in range(k):
        __pyx_t_1 = __pyx_v_k;
        __pyx_t_2 = __pyx_t_1;
        for (__pyx_t_3 = 0; __pyx_t_3 < __pyx_t_2; __pyx_t_3+=1) {
          __pyx_v_i = __pyx_t_3;
+372:             if valid_centers[i] == 1 and centers[i, col]!=max_val:
          __pyx_t_4 = __pyx_v_i;
          __pyx_t_17 = ((*((__pyx_t_5d_imm_9splitters_10cut_finder_NP_INT_t *) ( /* dim=0 */ (__pyx_v_valid_centers.data + __pyx_t_4 * __pyx_v_valid_centers.strides[0]) ))) == 1);
          if (__pyx_t_17) {
          } else {
            __pyx_t_5 = __pyx_t_17;
            goto __pyx_L18_bool_binop_done;
          }
          __pyx_t_4 = __pyx_v_i;
          __pyx_t_6 = __pyx_v_col;
          __pyx_t_17 = ((*((__pyx_t_5d_imm_9splitters_10cut_finder_NP_FLOAT_t *) ( /* dim=1 */ (( /* dim=0 */ (__pyx_v_centers.data + __pyx_t_4 * __pyx_v_centers.strides[0]) ) + __pyx_t_6 * __pyx_v_centers.strides[1]) ))) != __pyx_v_max_val);
          __pyx_t_5 = __pyx_t_17;
          __pyx_L18_bool_binop_done:;
          if (__pyx_t_5) {
/* … */
          }
        }
+373:                 unique_thresholds.add(centers[i, col])
            __pyx_t_6 = __pyx_v_i;
            __pyx_t_4 = __pyx_v_col;
            __pyx_t_7 = PyFloat_FromDouble((*((__pyx_t_5d_imm_9splitters_10cut_finder_NP_FLOAT_t *) ( /* dim=1 */ (( /* dim=0 */ (__pyx_v_centers.data + __pyx_t_6 * __pyx_v_centers.strides[0]) ) + __pyx_t_4 * __pyx_v_centers.strides[1]) )))); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 373, __pyx_L9_error)
            __Pyx_GOTREF(__pyx_t_7);
            __pyx_t_16 = PySet_Add(__pyx_v_unique_thresholds, __pyx_t_7); if (unlikely(__pyx_t_16 == ((int)-1))) __PYX_ERR(0, 373, __pyx_L9_error)
            __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
 374: 
+375:         sorted_thresholds = sorted(unique_thresholds)
        __pyx_t_9 = PySequence_List(__pyx_v_unique_thresholds); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 375, __pyx_L9_error)
        __Pyx_GOTREF(__pyx_t_9);
        __pyx_t_7 = ((PyObject*)__pyx_t_9);
        __pyx_t_9 = 0;
        __pyx_t_16 = PyList_Sort(__pyx_t_7); if (unlikely(__pyx_t_16 == ((int)-1))) __PYX_ERR(0, 375, __pyx_L9_error)
        __pyx_v_sorted_thresholds = ((PyObject*)__pyx_t_7);
        __pyx_t_7 = 0;
 376: 
+377:         num_thresholds = len(sorted_thresholds)
        __pyx_t_15 = __Pyx_PyList_GET_SIZE(__pyx_v_sorted_thresholds); if (unlikely(__pyx_t_15 == ((Py_ssize_t)-1))) __PYX_ERR(0, 377, __pyx_L9_error)
        __pyx_v_num_thresholds = __pyx_t_15;
+378:         combined_thresholds = <NP_FLOAT_t *> malloc(num_thresholds * sizeof(NP_FLOAT_t))
        __pyx_v_combined_thresholds = ((__pyx_t_5d_imm_9splitters_10cut_finder_NP_FLOAT_t *)malloc((__pyx_v_num_thresholds * (sizeof(__pyx_t_5d_imm_9splitters_10cut_finder_NP_FLOAT_t)))));
 379: 
+380:         for i in range(num_thresholds):
        __pyx_t_1 = __pyx_v_num_thresholds;
        __pyx_t_2 = __pyx_t_1;
        for (__pyx_t_3 = 0; __pyx_t_3 < __pyx_t_2; __pyx_t_3+=1) {
          __pyx_v_i = __pyx_t_3;
+381:             combined_thresholds[i] = sorted_thresholds[i]
          __pyx_t_18 = __pyx_PyFloat_AsDouble(PyList_GET_ITEM(__pyx_v_sorted_thresholds, __pyx_v_i)); if (unlikely((__pyx_t_18 == ((npy_float64)-1)) && PyErr_Occurred())) __PYX_ERR(0, 381, __pyx_L9_error)
          (__pyx_v_combined_thresholds[__pyx_v_i]) = __pyx_t_18;
        }
      }
 382: 
 383:     # Process each threshold
+384:     for i in range(num_thresholds):
  __pyx_t_1 = __pyx_v_num_thresholds;
  __pyx_t_2 = __pyx_t_1;
  for (__pyx_t_3 = 0; __pyx_t_3 < __pyx_t_2; __pyx_t_3+=1) {
    __pyx_v_i = __pyx_t_3;
+385:         mistakes = 0
    __pyx_v_mistakes = 0;
+386:         ix = 0
    __pyx_v_ix = 0;
+387:         threshold = combined_thresholds[i]
    __pyx_v_threshold = (__pyx_v_combined_thresholds[__pyx_v_i]);
 388: 
 389:         # Count mistakes
+390:         while ix < n:
    while (1) {
      __pyx_t_5 = (__pyx_v_ix < __pyx_v_n);
      if (!__pyx_t_5) break;
+391:             if X[ix, col] <= threshold:
      __pyx_t_4 = __pyx_v_ix;
      __pyx_t_6 = __pyx_v_col;
      __pyx_t_5 = ((*((__pyx_t_5d_imm_9splitters_10cut_finder_NP_FLOAT_t *) ( /* dim=1 */ (( /* dim=0 */ (__pyx_v_X.data + __pyx_t_4 * __pyx_v_X.strides[0]) ) + __pyx_t_6 * __pyx_v_X.strides[1]) ))) <= __pyx_v_threshold);
      if (__pyx_t_5) {
/* … */
        goto __pyx_L26;
      }
+392:                 if centers[y[ix], col] > threshold:
        __pyx_t_6 = __pyx_v_ix;
        __pyx_t_4 = (*((__pyx_t_5d_imm_9splitters_10cut_finder_NP_INT_t *) ( /* dim=0 */ (__pyx_v_y.data + __pyx_t_6 * __pyx_v_y.strides[0]) )));
        __pyx_t_19 = __pyx_v_col;
        __pyx_t_5 = ((*((__pyx_t_5d_imm_9splitters_10cut_finder_NP_FLOAT_t *) ( /* dim=1 */ (( /* dim=0 */ (__pyx_v_centers.data + __pyx_t_4 * __pyx_v_centers.strides[0]) ) + __pyx_t_19 * __pyx_v_centers.strides[1]) ))) > __pyx_v_threshold);
        if (__pyx_t_5) {
/* … */
        }
+393:                     mistakes += 1
          __pyx_v_mistakes = (__pyx_v_mistakes + 1);
 394:             else:
+395:                 if centers[y[ix], col] <= threshold:
      /*else*/ {
        __pyx_t_6 = __pyx_v_ix;
        __pyx_t_19 = (*((__pyx_t_5d_imm_9splitters_10cut_finder_NP_INT_t *) ( /* dim=0 */ (__pyx_v_y.data + __pyx_t_6 * __pyx_v_y.strides[0]) )));
        __pyx_t_4 = __pyx_v_col;
        __pyx_t_5 = ((*((__pyx_t_5d_imm_9splitters_10cut_finder_NP_FLOAT_t *) ( /* dim=1 */ (( /* dim=0 */ (__pyx_v_centers.data + __pyx_t_19 * __pyx_v_centers.strides[0]) ) + __pyx_t_4 * __pyx_v_centers.strides[1]) ))) <= __pyx_v_threshold);
        if (__pyx_t_5) {
/* … */
        }
      }
      __pyx_L26:;
+396:                     mistakes += 1
          __pyx_v_mistakes = (__pyx_v_mistakes + 1);
+397:             ix += 1
      __pyx_v_ix = (__pyx_v_ix + 1);
    }
 398: 
 399:         # Store result
+400:         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_L33;
          }
          __pyx_L32_error: {
            #ifdef WITH_THREAD
            __Pyx_PyGILState_Release(__pyx_gilstate_save);
            #endif
            goto __pyx_L1_error;
          }
          __pyx_L33:;
        }
    }
  }
+401:             feature_results.append({
          if (unlikely(__pyx_v_feature_results == Py_None)) {
            PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "append");
            __PYX_ERR(0, 401, __pyx_L32_error)
          }
/* … */
          __pyx_t_16 = __Pyx_PyList_Append(__pyx_v_feature_results, __pyx_t_7); if (unlikely(__pyx_t_16 == ((int)-1))) __PYX_ERR(0, 401, __pyx_L32_error)
          __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
        }
+402:                 'feature': col,
          __pyx_t_7 = __Pyx_PyDict_NewPresized(3); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 402, __pyx_L32_error)
          __Pyx_GOTREF(__pyx_t_7);
          __pyx_t_9 = __Pyx_PyInt_From_int(__pyx_v_col); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 402, __pyx_L32_error)
          __Pyx_GOTREF(__pyx_t_9);
          if (PyDict_SetItem(__pyx_t_7, __pyx_n_s_feature, __pyx_t_9) < 0) __PYX_ERR(0, 402, __pyx_L32_error)
          __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
+403:                 'threshold': threshold,
          __pyx_t_9 = PyFloat_FromDouble(__pyx_v_threshold); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 403, __pyx_L32_error)
          __Pyx_GOTREF(__pyx_t_9);
          if (PyDict_SetItem(__pyx_t_7, __pyx_n_s_threshold, __pyx_t_9) < 0) __PYX_ERR(0, 402, __pyx_L32_error)
          __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
+404:                 'mistakes': mistakes
          __pyx_t_9 = __Pyx_PyInt_From_int(__pyx_v_mistakes); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 404, __pyx_L32_error)
          __Pyx_GOTREF(__pyx_t_9);
          if (PyDict_SetItem(__pyx_t_7, __pyx_n_s_mistakes, __pyx_t_9) < 0) __PYX_ERR(0, 402, __pyx_L32_error)
          __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
 405:             })
 406: 
+407:     free(combined_thresholds)
  free(__pyx_v_combined_thresholds);