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);