Generated by Cython 3.0.10

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

    +001: cimport cython

      __pyx_t_4 = __Pyx_PyDict_NewPresized(0); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_4);
      if (PyDict_SetItem(__pyx_d, __pyx_n_s_test, __pyx_t_4) < 0) __PYX_ERR(0, 1, __pyx_L1_error)
      __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;

     002: from libc.stdlib cimport malloc, free

     003: from libc.math cimport ceil

    +004: import gudhi as gd

      __pyx_t_7 = __Pyx_ImportDottedModule(__pyx_n_s_gudhi, NULL); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 4, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_7);
      if (PyDict_SetItem(__pyx_d, __pyx_n_s_gd, __pyx_t_7) < 0) __PYX_ERR(0, 4, __pyx_L1_error)
      __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;

    +005: import numpy as np

      __pyx_t_7 = __Pyx_ImportDottedModule(__pyx_n_s_numpy, NULL); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 5, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_7);
      if (PyDict_SetItem(__pyx_d, __pyx_n_s_np, __pyx_t_7) < 0) __PYX_ERR(0, 5, __pyx_L1_error)
      __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;

     006: cimport numpy as cnp

    +007: cnp.import_array()

      __pyx_t_9 = __pyx_f_5numpy_import_array(); if (unlikely(__pyx_t_9 == ((int)-1))) __PYX_ERR(0, 7, __pyx_L1_error)

     008:

     009:

    +010: dtype_float = np.float32

      __Pyx_GetModuleGlobalName(__pyx_t_7, __pyx_n_s_np); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 10, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_7);
      __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_t_7, __pyx_n_s_float32); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 10, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_4);
      __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
      if (PyDict_SetItem(__pyx_d, __pyx_n_s_dtype_float, __pyx_t_4) < 0) __PYX_ERR(0, 10, __pyx_L1_error)
      __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;

     011:

     012:

    +013: cdef class RipsEccBackbone:

    struct __pyx_obj_3ecc_RipsEccBackbone {
      PyObject_HEAD
      struct __pyx_vtabstruct_3ecc_RipsEccBackbone *__pyx_vtab;
      float max_edge_length;
      float resolution;
      float impulse;
      Py_ssize_t steps;
      Py_ssize_t max_dim;
    };
    /* … */
    struct __pyx_vtabstruct_3ecc_RipsEccBackbone {
      __pyx_ctuple_float__ptr__and_float__ptr (*_cal_edge_grad)(__Pyx_memviewslice, __Pyx_memviewslice, float, int);
    };
    static struct __pyx_vtabstruct_3ecc_RipsEccBackbone *__pyx_vtabptr_3ecc_RipsEccBackbone;
    static CYTHON_INLINE __pyx_ctuple_float__ptr__and_float__ptr __pyx_f_3ecc_15RipsEccBackbone__cal_edge_grad(__Pyx_memviewslice, __Pyx_memviewslice, float, int);

     014:     cdef float max_edge_length, resolution, impulse

     015:     cdef Py_ssize_t steps, max_dim

     016:

    +017:     def __init__(self, float max_edge_length=2, Py_ssize_t max_dim=1, Py_ssize_t steps=32, float impulse=10):

    /* Python wrapper */
    static int __pyx_pw_3ecc_15RipsEccBackbone_1__init__(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
    static int __pyx_pw_3ecc_15RipsEccBackbone_1__init__(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
      float __pyx_v_max_edge_length;
      Py_ssize_t __pyx_v_max_dim;
      Py_ssize_t __pyx_v_steps;
      float __pyx_v_impulse;
      CYTHON_UNUSED Py_ssize_t __pyx_nargs;
      CYTHON_UNUSED PyObject *const *__pyx_kwvalues;
      int __pyx_r;
      __Pyx_RefNannyDeclarations
      __Pyx_RefNannySetupContext("__init__ (wrapper)", 0);
      #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 -1;
      #endif
      __pyx_kwvalues = __Pyx_KwValues_VARARGS(__pyx_args, __pyx_nargs);
      {
        PyObject **__pyx_pyargnames[] = {&__pyx_n_s_max_edge_length,&__pyx_n_s_max_dim,&__pyx_n_s_steps,&__pyx_n_s_impulse,0};
      PyObject* values[4] = {0,0,0,0};
        if (__pyx_kwds) {
          Py_ssize_t kw_args;
          switch (__pyx_nargs) {
            case  4: values[3] = __Pyx_Arg_VARARGS(__pyx_args, 3);
            CYTHON_FALLTHROUGH;
            case  3: values[2] = __Pyx_Arg_VARARGS(__pyx_args, 2);
            CYTHON_FALLTHROUGH;
            case  2: values[1] = __Pyx_Arg_VARARGS(__pyx_args, 1);
            CYTHON_FALLTHROUGH;
            case  1: values[0] = __Pyx_Arg_VARARGS(__pyx_args, 0);
            CYTHON_FALLTHROUGH;
            case  0: break;
            default: goto __pyx_L5_argtuple_error;
          }
          kw_args = __Pyx_NumKwargs_VARARGS(__pyx_kwds);
          switch (__pyx_nargs) {
            case  0:
            if (kw_args > 0) {
              PyObject* value = __Pyx_GetKwValue_VARARGS(__pyx_kwds, __pyx_kwvalues, __pyx_n_s_max_edge_length);
              if (value) { values[0] = __Pyx_Arg_NewRef_VARARGS(value); kw_args--; }
              else if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 17, __pyx_L3_error)
            }
            CYTHON_FALLTHROUGH;
            case  1:
            if (kw_args > 0) {
              PyObject* value = __Pyx_GetKwValue_VARARGS(__pyx_kwds, __pyx_kwvalues, __pyx_n_s_max_dim);
              if (value) { values[1] = __Pyx_Arg_NewRef_VARARGS(value); kw_args--; }
              else if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 17, __pyx_L3_error)
            }
            CYTHON_FALLTHROUGH;
            case  2:
            if (kw_args > 0) {
              PyObject* value = __Pyx_GetKwValue_VARARGS(__pyx_kwds, __pyx_kwvalues, __pyx_n_s_steps);
              if (value) { values[2] = __Pyx_Arg_NewRef_VARARGS(value); kw_args--; }
              else if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 17, __pyx_L3_error)
            }
            CYTHON_FALLTHROUGH;
            case  3:
            if (kw_args > 0) {
              PyObject* value = __Pyx_GetKwValue_VARARGS(__pyx_kwds, __pyx_kwvalues, __pyx_n_s_impulse);
              if (value) { values[3] = __Pyx_Arg_NewRef_VARARGS(value); kw_args--; }
              else if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 17, __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, "__init__") < 0)) __PYX_ERR(0, 17, __pyx_L3_error)
          }
        } else {
          switch (__pyx_nargs) {
            case  4: values[3] = __Pyx_Arg_VARARGS(__pyx_args, 3);
            CYTHON_FALLTHROUGH;
            case  3: values[2] = __Pyx_Arg_VARARGS(__pyx_args, 2);
            CYTHON_FALLTHROUGH;
            case  2: values[1] = __Pyx_Arg_VARARGS(__pyx_args, 1);
            CYTHON_FALLTHROUGH;
            case  1: values[0] = __Pyx_Arg_VARARGS(__pyx_args, 0);
            CYTHON_FALLTHROUGH;
            case  0: break;
            default: goto __pyx_L5_argtuple_error;
          }
        }
        if (values[0]) {
          __pyx_v_max_edge_length = __pyx_PyFloat_AsFloat(values[0]); if (unlikely((__pyx_v_max_edge_length == (float)-1) && PyErr_Occurred())) __PYX_ERR(0, 17, __pyx_L3_error)
        } else {
          __pyx_v_max_edge_length = ((float)2.0);
        }
        if (values[1]) {
          __pyx_v_max_dim = __Pyx_PyIndex_AsSsize_t(values[1]); if (unlikely((__pyx_v_max_dim == (Py_ssize_t)-1) && PyErr_Occurred())) __PYX_ERR(0, 17, __pyx_L3_error)
        } else {
          __pyx_v_max_dim = ((Py_ssize_t)1);
        }
        if (values[2]) {
          __pyx_v_steps = __Pyx_PyIndex_AsSsize_t(values[2]); if (unlikely((__pyx_v_steps == (Py_ssize_t)-1) && PyErr_Occurred())) __PYX_ERR(0, 17, __pyx_L3_error)
        } else {
          __pyx_v_steps = ((Py_ssize_t)32);
        }
        if (values[3]) {
          __pyx_v_impulse = __pyx_PyFloat_AsFloat(values[3]); if (unlikely((__pyx_v_impulse == (float)-1) && PyErr_Occurred())) __PYX_ERR(0, 17, __pyx_L3_error)
        } else {
          __pyx_v_impulse = ((float)10.0);
        }
      }
      goto __pyx_L6_skip;
      __pyx_L5_argtuple_error:;
      __Pyx_RaiseArgtupleInvalid("__init__", 0, 0, 4, __pyx_nargs); __PYX_ERR(0, 17, __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_VARARGS(values[__pyx_temp]);
        }
      }
      __Pyx_AddTraceback("ecc.RipsEccBackbone.__init__", __pyx_clineno, __pyx_lineno, __pyx_filename);
      __Pyx_RefNannyFinishContext();
      return -1;
      __pyx_L4_argument_unpacking_done:;
      __pyx_r = __pyx_pf_3ecc_15RipsEccBackbone___init__(((struct __pyx_obj_3ecc_RipsEccBackbone *)__pyx_v_self), __pyx_v_max_edge_length, __pyx_v_max_dim, __pyx_v_steps, __pyx_v_impulse);
      int __pyx_lineno = 0;
      const char *__pyx_filename = NULL;
      int __pyx_clineno = 0;

      /* function exit code */
      {
        Py_ssize_t __pyx_temp;
        for (__pyx_temp=0; __pyx_temp < (Py_ssize_t)(sizeof(values)/sizeof(values[0])); ++__pyx_temp) {
          __Pyx_Arg_XDECREF_VARARGS(values[__pyx_temp]);
        }
      }
      __Pyx_RefNannyFinishContext();
      return __pyx_r;
    }

    static int __pyx_pf_3ecc_15RipsEccBackbone___init__(struct __pyx_obj_3ecc_RipsEccBackbone *__pyx_v_self, float __pyx_v_max_edge_length, Py_ssize_t __pyx_v_max_dim, Py_ssize_t __pyx_v_steps, float __pyx_v_impulse) {
      int __pyx_r;
    /* … */
      /* function exit code */
      __pyx_r = 0;
      goto __pyx_L0;
      __pyx_L1_error:;
      __Pyx_AddTraceback("ecc.RipsEccBackbone.__init__", __pyx_clineno, __pyx_lineno, __pyx_filename);
      __pyx_r = -1;
      __pyx_L0:;
      return __pyx_r;
    }

    +018:         self.max_edge_length = max_edge_length

      __pyx_v_self->max_edge_length = __pyx_v_max_edge_length;

    +019:         self.max_dim = max_dim

      __pyx_v_self->max_dim = __pyx_v_max_dim;

    +020:         self.steps = steps

      __pyx_v_self->steps = __pyx_v_steps;

    +021:         self.resolution = self.max_edge_length / (self.steps - 1)

      __pyx_t_1 = (__pyx_v_self->steps - 1);
      if (unlikely(__pyx_t_1 == 0)) {
        PyErr_SetString(PyExc_ZeroDivisionError, "float division");
        __PYX_ERR(0, 21, __pyx_L1_error)
      }
      __pyx_v_self->resolution = (__pyx_v_self->max_edge_length / ((float)__pyx_t_1));

    +022:         self.impulse = impulse

      __pyx_v_self->impulse = __pyx_v_impulse;

     023:

    +024:     @cython.boundscheck(False)      # turn off bounds-checking for entire function

    /* Python wrapper */
    static PyObject *__pyx_pw_3ecc_15RipsEccBackbone_3cal_ecc(PyObject *__pyx_v_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_3ecc_15RipsEccBackbone_2cal_ecc, "_summary_\n\n        Args:\n            x (numpy.ndarray): Point cloud of shape [B, P, D]\n            backprop (bool): Whether or not the input requires gradient calculation.\n\n        Returns:\n            _type_: _description_\n        ");
    static PyMethodDef __pyx_mdef_3ecc_15RipsEccBackbone_3cal_ecc = {"cal_ecc", (PyCFunction)(void*)(__Pyx_PyCFunction_FastCallWithKeywords)__pyx_pw_3ecc_15RipsEccBackbone_3cal_ecc, __Pyx_METH_FASTCALL|METH_KEYWORDS, __pyx_doc_3ecc_15RipsEccBackbone_2cal_ecc};
    static PyObject *__pyx_pw_3ecc_15RipsEccBackbone_3cal_ecc(PyObject *__pyx_v_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
    ) {
      PyObject *__pyx_v_x = 0;
      int __pyx_v_backprop;
      #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("cal_ecc (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_backprop,0};
      PyObject* values[2] = {0,0};
        if (__pyx_kwds) {
          Py_ssize_t kw_args;
          switch (__pyx_nargs) {
            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, 24, __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_backprop)) != 0)) {
              (void)__Pyx_Arg_NewRef_FASTCALL(values[1]);
              kw_args--;
            }
            else if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 24, __pyx_L3_error)
            else {
              __Pyx_RaiseArgtupleInvalid("cal_ecc", 1, 2, 2, 1); __PYX_ERR(0, 24, __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, "cal_ecc") < 0)) __PYX_ERR(0, 24, __pyx_L3_error)
          }
        } else if (unlikely(__pyx_nargs != 2)) {
          goto __pyx_L5_argtuple_error;
        } else {
          values[0] = __Pyx_Arg_FASTCALL(__pyx_args, 0);
          values[1] = __Pyx_Arg_FASTCALL(__pyx_args, 1);
        }
        __pyx_v_x = values[0];
        __pyx_v_backprop = __Pyx_PyObject_IsTrue(values[1]); if (unlikely((__pyx_v_backprop == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 27, __pyx_L3_error)
      }
      goto __pyx_L6_skip;
      __pyx_L5_argtuple_error:;
      __Pyx_RaiseArgtupleInvalid("cal_ecc", 1, 2, 2, __pyx_nargs); __PYX_ERR(0, 24, __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_AddTraceback("ecc.RipsEccBackbone.cal_ecc", __pyx_clineno, __pyx_lineno, __pyx_filename);
      __Pyx_RefNannyFinishContext();
      return NULL;
      __pyx_L4_argument_unpacking_done:;
      __pyx_r = __pyx_pf_3ecc_15RipsEccBackbone_2cal_ecc(((struct __pyx_obj_3ecc_RipsEccBackbone *)__pyx_v_self), __pyx_v_x, __pyx_v_backprop);
      int __pyx_lineno = 0;
      const char *__pyx_filename = NULL;
      int __pyx_clineno = 0;

      /* function exit code */
      {
        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_3ecc_15RipsEccBackbone_2cal_ecc(struct __pyx_obj_3ecc_RipsEccBackbone *__pyx_v_self, PyObject *__pyx_v_x, int __pyx_v_backprop) {
      Py_ssize_t __pyx_v_batch_size;
      Py_ssize_t __pyx_v_d;
      Py_ssize_t __pyx_v_b;
      Py_ssize_t __pyx_v_dim;
      Py_ssize_t __pyx_v_t;
      Py_ssize_t __pyx_v_vtx_idx_1;
      Py_ssize_t __pyx_v_vtx_idx_2;
      Py_ssize_t __pyx_v_i;
      float __pyx_v_filt;
      __Pyx_memviewslice __pyx_v_vtx_1 = { 0, 0, { 0 }, { 0 }, { 0 } };
      __Pyx_memviewslice __pyx_v_vtx_2 = { 0, 0, { 0 }, { 0 }, { 0 } };
      float *__pyx_v_grad_1;
      float *__pyx_v_grad_2;
      CYTHON_UNUSED PyObject *__pyx_v__ = NULL;
      __Pyx_memviewslice __pyx_v_x_view = { 0, 0, { 0 }, { 0 }, { 0 } };
      PyObject *__pyx_v_ecc = NULL;
      __Pyx_memviewslice __pyx_v_ecc_view = { 0, 0, { 0 }, { 0 }, { 0 } };
      PyObject *__pyx_v_grad_local = NULL;
      __Pyx_memviewslice __pyx_v_grad_local_view = { 0, 0, { 0 }, { 0 }, { 0 } };
      PyObject *__pyx_v_skeleton = NULL;
      PyObject *__pyx_v_st = NULL;
      PyObject *__pyx_v_vtx_idx = NULL;
      PyObject *__pyx_r = NULL;
    /* … */
      /* function exit code */
      __pyx_L1_error:;
      __Pyx_XDECREF(__pyx_t_1);
      __Pyx_XDECREF(__pyx_t_2);
      __Pyx_XDECREF(__pyx_t_3);
      __Pyx_XDECREF(__pyx_t_4);
      __Pyx_XDECREF(__pyx_t_5);
      __PYX_XCLEAR_MEMVIEW(&__pyx_t_9, 1);
      __PYX_XCLEAR_MEMVIEW(&__pyx_t_10, 1);
      __PYX_XCLEAR_MEMVIEW(&__pyx_t_11, 1);
      __PYX_XCLEAR_MEMVIEW(&__pyx_t_23, 1);
      __Pyx_AddTraceback("ecc.RipsEccBackbone.cal_ecc", __pyx_clineno, __pyx_lineno, __pyx_filename);
      __pyx_r = NULL;
      __pyx_L0:;
      __PYX_XCLEAR_MEMVIEW(&__pyx_v_vtx_1, 1);
      __PYX_XCLEAR_MEMVIEW(&__pyx_v_vtx_2, 1);
      __Pyx_XDECREF(__pyx_v__);
      __PYX_XCLEAR_MEMVIEW(&__pyx_v_x_view, 1);
      __Pyx_XDECREF(__pyx_v_ecc);
      __PYX_XCLEAR_MEMVIEW(&__pyx_v_ecc_view, 1);
      __Pyx_XDECREF(__pyx_v_grad_local);
      __PYX_XCLEAR_MEMVIEW(&__pyx_v_grad_local_view, 1);
      __Pyx_XDECREF(__pyx_v_skeleton);
      __Pyx_XDECREF(__pyx_v_st);
      __Pyx_XDECREF(__pyx_v_vtx_idx);
      __Pyx_XGIVEREF(__pyx_r);
      __Pyx_RefNannyFinishContext();
      return __pyx_r;
    }
    /* … */
      __pyx_tuple__24 = PyTuple_Pack(25, __pyx_n_s_self, __pyx_n_s_x, __pyx_n_s_backprop, __pyx_n_s_batch_size, __pyx_n_s_d, __pyx_n_s_b, __pyx_n_s_dim, __pyx_n_s_t, __pyx_n_s_vtx_idx_1, __pyx_n_s_vtx_idx_2, __pyx_n_s_i, __pyx_n_s_filt, __pyx_n_s_vtx_1, __pyx_n_s_vtx_2, __pyx_n_s_grad_1, __pyx_n_s_grad_2, __pyx_n_s__23, __pyx_n_s_x_view, __pyx_n_s_ecc, __pyx_n_s_ecc_view, __pyx_n_s_grad_local, __pyx_n_s_grad_local_view, __pyx_n_s_skeleton, __pyx_n_s_st, __pyx_n_s_vtx_idx); if (unlikely(!__pyx_tuple__24)) __PYX_ERR(0, 24, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_tuple__24);
      __Pyx_GIVEREF(__pyx_tuple__24);
    /* … */
      __pyx_t_4 = __Pyx_CyFunction_New(&__pyx_mdef_3ecc_15RipsEccBackbone_3cal_ecc, __Pyx_CYFUNCTION_CCLASS, __pyx_n_s_RipsEccBackbone_cal_ecc, NULL, __pyx_n_s_ecc, __pyx_d, ((PyObject *)__pyx_codeobj__25)); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 24, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_4);
      if (__Pyx_SetItemOnTypeDict((PyObject *)__pyx_ptype_3ecc_RipsEccBackbone, __pyx_n_s_cal_ecc, __pyx_t_4) < 0) __PYX_ERR(0, 24, __pyx_L1_error)
      __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
      PyType_Modified(__pyx_ptype_3ecc_RipsEccBackbone);
      __pyx_codeobj__25 = (PyObject*)__Pyx_PyCode_New(3, 0, 0, 25, 0, CO_OPTIMIZED|CO_NEWLOCALS, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__24, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_ecc_pyx, __pyx_n_s_cal_ecc, 24, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__25)) __PYX_ERR(0, 24, __pyx_L1_error)

     025:     @cython.wraparound(False)       # turn off negative index wrapping for entire function

     026:     @cython.cdivision(True)         # turn off checking for division by zero

     027:     def cal_ecc(self, object x, bint backprop):

     028:         """_summary_

     029:

     030:         Args:

     031:             x (numpy.ndarray): Point cloud of shape [B, P, D]

     032:             backprop (bool): Whether or not the input requires gradient calculation.

     033:

     034:         Returns:

     035:             _type_: _description_

     036:         """

     037:         cdef Py_ssize_t batch_size, d, b, dim, t, vtx_idx_1, vtx_idx_2, i

     038:         cdef float filt

     039:         cdef float[:] vtx_1, vtx_2

    +040:         cdef float* grad_1 = NULL

      __pyx_v_grad_1 = NULL;

    +041:         cdef float* grad_2 = NULL

      __pyx_v_grad_2 = NULL;

     042:

    +043:         batch_size, _, d = x.shape

      __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_x, __pyx_n_s_shape); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 43, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_1);
      if ((likely(PyTuple_CheckExact(__pyx_t_1))) || (PyList_CheckExact(__pyx_t_1))) {
        PyObject* sequence = __pyx_t_1;
        Py_ssize_t size = __Pyx_PySequence_SIZE(sequence);
        if (unlikely(size != 3)) {
          if (size > 3) __Pyx_RaiseTooManyValuesError(3);
          else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size);
          __PYX_ERR(0, 43, __pyx_L1_error)
        }
        #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
        if (likely(PyTuple_CheckExact(sequence))) {
          __pyx_t_2 = PyTuple_GET_ITEM(sequence, 0);
          __pyx_t_3 = PyTuple_GET_ITEM(sequence, 1);
          __pyx_t_4 = PyTuple_GET_ITEM(sequence, 2);
        } else {
          __pyx_t_2 = PyList_GET_ITEM(sequence, 0);
          __pyx_t_3 = PyList_GET_ITEM(sequence, 1);
          __pyx_t_4 = PyList_GET_ITEM(sequence, 2);
        }
        __Pyx_INCREF(__pyx_t_2);
        __Pyx_INCREF(__pyx_t_3);
        __Pyx_INCREF(__pyx_t_4);
        #else
        __pyx_t_2 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 43, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_2);
        __pyx_t_3 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 43, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_3);
        __pyx_t_4 = PySequence_ITEM(sequence, 2); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 43, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_4);
        #endif
        __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
      } else {
        Py_ssize_t index = -1;
        __pyx_t_5 = PyObject_GetIter(__pyx_t_1); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 43, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_5);
        __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
        __pyx_t_6 = __Pyx_PyObject_GetIterNextFunc(__pyx_t_5);
        index = 0; __pyx_t_2 = __pyx_t_6(__pyx_t_5); if (unlikely(!__pyx_t_2)) goto __pyx_L3_unpacking_failed;
        __Pyx_GOTREF(__pyx_t_2);
        index = 1; __pyx_t_3 = __pyx_t_6(__pyx_t_5); if (unlikely(!__pyx_t_3)) goto __pyx_L3_unpacking_failed;
        __Pyx_GOTREF(__pyx_t_3);
        index = 2; __pyx_t_4 = __pyx_t_6(__pyx_t_5); if (unlikely(!__pyx_t_4)) goto __pyx_L3_unpacking_failed;
        __Pyx_GOTREF(__pyx_t_4);
        if (__Pyx_IternextUnpackEndCheck(__pyx_t_6(__pyx_t_5), 3) < 0) __PYX_ERR(0, 43, __pyx_L1_error)
        __pyx_t_6 = NULL;
        __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
        goto __pyx_L4_unpacking_done;
        __pyx_L3_unpacking_failed:;
        __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
        __pyx_t_6 = NULL;
        if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index);
        __PYX_ERR(0, 43, __pyx_L1_error)
        __pyx_L4_unpacking_done:;
      }
      __pyx_t_7 = __Pyx_PyIndex_AsSsize_t(__pyx_t_2); if (unlikely((__pyx_t_7 == (Py_ssize_t)-1) && PyErr_Occurred())) __PYX_ERR(0, 43, __pyx_L1_error)
      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
      __pyx_t_8 = __Pyx_PyIndex_AsSsize_t(__pyx_t_4); if (unlikely((__pyx_t_8 == (Py_ssize_t)-1) && PyErr_Occurred())) __PYX_ERR(0, 43, __pyx_L1_error)
      __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
      __pyx_v_batch_size = __pyx_t_7;
      __pyx_v__ = __pyx_t_3;
      __pyx_t_3 = 0;
      __pyx_v_d = __pyx_t_8;

     044:

    +045:         cdef float[:, :, :] x_view = x

      __pyx_t_9 = __Pyx_PyObject_to_MemoryviewSlice_dsdsds_float(__pyx_v_x, PyBUF_WRITABLE); if (unlikely(!__pyx_t_9.memview)) __PYX_ERR(0, 45, __pyx_L1_error)
      __pyx_v_x_view = __pyx_t_9;
      __pyx_t_9.memview = NULL;
      __pyx_t_9.data = NULL;

     046:

    +047:         ecc = np.zeros((batch_size, self.steps), dtype=dtype_float)

      __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_np); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 47, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_1);
      __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_zeros); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 47, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_4);
      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
      __pyx_t_1 = PyInt_FromSsize_t(__pyx_v_batch_size); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 47, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_1);
      __pyx_t_3 = PyInt_FromSsize_t(__pyx_v_self->steps); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 47, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_3);
      __pyx_t_2 = PyTuple_New(2); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 47, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_2);
      __Pyx_GIVEREF(__pyx_t_1);
      if (__Pyx_PyTuple_SET_ITEM(__pyx_t_2, 0, __pyx_t_1)) __PYX_ERR(0, 47, __pyx_L1_error);
      __Pyx_GIVEREF(__pyx_t_3);
      if (__Pyx_PyTuple_SET_ITEM(__pyx_t_2, 1, __pyx_t_3)) __PYX_ERR(0, 47, __pyx_L1_error);
      __pyx_t_1 = 0;
      __pyx_t_3 = 0;
      __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 47, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_3);
      __Pyx_GIVEREF(__pyx_t_2);
      if (__Pyx_PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_2)) __PYX_ERR(0, 47, __pyx_L1_error);
      __pyx_t_2 = 0;
      __pyx_t_2 = __Pyx_PyDict_NewPresized(1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 47, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_2);
      __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_dtype_float); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 47, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_1);
      if (PyDict_SetItem(__pyx_t_2, __pyx_n_s_dtype, __pyx_t_1) < 0) __PYX_ERR(0, 47, __pyx_L1_error)
      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
      __pyx_t_1 = __Pyx_PyObject_Call(__pyx_t_4, __pyx_t_3, __pyx_t_2); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 47, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_1);
      __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
      __pyx_v_ecc = __pyx_t_1;
      __pyx_t_1 = 0;

    +048:         cdef float[:, :] ecc_view = ecc

      __pyx_t_10 = __Pyx_PyObject_to_MemoryviewSlice_dsds_float(__pyx_v_ecc, PyBUF_WRITABLE); if (unlikely(!__pyx_t_10.memview)) __PYX_ERR(0, 48, __pyx_L1_error)
      __pyx_v_ecc_view = __pyx_t_10;
      __pyx_t_10.memview = NULL;
      __pyx_t_10.data = NULL;

     049:

    +050:         grad_local = np.zeros((*x.shape, self.steps), dtype=dtype_float) if backprop else None    # shape: [B, P, D, steps]

      if (__pyx_v_backprop) {
        __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_np); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 50, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_2);
        __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_zeros); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 50, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_3);
        __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
        __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_v_x, __pyx_n_s_shape); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 50, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_4);
        __pyx_t_2 = __Pyx_PySequence_ListKeepNew(__pyx_t_4); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 50, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_2);
        __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
        __pyx_t_4 = PyInt_FromSsize_t(__pyx_v_self->steps); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 50, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_4);
        if (__Pyx_ListComp_Append(__pyx_t_2, __pyx_t_4) < 0) __PYX_ERR(0, 50, __pyx_L1_error)
        __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
        {
          PyObject *__pyx_temp = PyList_AsTuple(__pyx_t_2);
          __Pyx_DECREF(__pyx_t_2);
          __pyx_t_2 = __pyx_temp; if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 50, __pyx_L1_error)
          __Pyx_GOTREF(__pyx_t_2);
        }
        __pyx_t_4 = PyTuple_New(1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 50, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_4);
        __Pyx_GIVEREF(__pyx_t_2);
        if (__Pyx_PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_2)) __PYX_ERR(0, 50, __pyx_L1_error);
        __pyx_t_2 = 0;
        __pyx_t_2 = __Pyx_PyDict_NewPresized(1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 50, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_2);
        __Pyx_GetModuleGlobalName(__pyx_t_5, __pyx_n_s_dtype_float); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 50, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_5);
        if (PyDict_SetItem(__pyx_t_2, __pyx_n_s_dtype, __pyx_t_5) < 0) __PYX_ERR(0, 50, __pyx_L1_error)
        __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
        __pyx_t_5 = __Pyx_PyObject_Call(__pyx_t_3, __pyx_t_4, __pyx_t_2); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 50, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_5);
        __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
        __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
        __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
        __pyx_t_1 = __pyx_t_5;
        __pyx_t_5 = 0;
      } else {
        __Pyx_INCREF(Py_None);
        __pyx_t_1 = Py_None;
      }
      __pyx_v_grad_local = __pyx_t_1;
      __pyx_t_1 = 0;

    +051:         cdef float[:, :, :, :] grad_local_view = grad_local

      __pyx_t_11 = __Pyx_PyObject_to_MemoryviewSlice_dsdsdsds_float(__pyx_v_grad_local, PyBUF_WRITABLE); if (unlikely(!__pyx_t_11.memview)) __PYX_ERR(0, 51, __pyx_L1_error)
      __pyx_v_grad_local_view = __pyx_t_11;
      __pyx_t_11.memview = NULL;
      __pyx_t_11.data = NULL;

     052:

    +053:         for b in range(batch_size):

      __pyx_t_8 = __pyx_v_batch_size;
      __pyx_t_7 = __pyx_t_8;
      for (__pyx_t_12 = 0; __pyx_t_12 < __pyx_t_7; __pyx_t_12+=1) {
        __pyx_v_b = __pyx_t_12;

    +054:             skeleton = gd.RipsComplex(points=x[b], max_edge_length=self.max_edge_length)

        __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_gd); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 54, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_1);
        __pyx_t_5 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_RipsComplex); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 54, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_5);
        __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
        __pyx_t_1 = __Pyx_PyDict_NewPresized(2); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 54, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_1);
        __pyx_t_2 = __Pyx_GetItemInt(__pyx_v_x, __pyx_v_b, Py_ssize_t, 1, PyInt_FromSsize_t, 0, 0, 0); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 54, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_2);
        if (PyDict_SetItem(__pyx_t_1, __pyx_n_s_points, __pyx_t_2) < 0) __PYX_ERR(0, 54, __pyx_L1_error)
        __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
        __pyx_t_2 = PyFloat_FromDouble(__pyx_v_self->max_edge_length); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 54, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_2);
        if (PyDict_SetItem(__pyx_t_1, __pyx_n_s_max_edge_length, __pyx_t_2) < 0) __PYX_ERR(0, 54, __pyx_L1_error)
        __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
        __pyx_t_2 = __Pyx_PyObject_Call(__pyx_t_5, __pyx_empty_tuple, __pyx_t_1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 54, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_2);
        __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
        __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
        __Pyx_XDECREF_SET(__pyx_v_skeleton, __pyx_t_2);
        __pyx_t_2 = 0;

    +055:             st = skeleton.create_simplex_tree(max_dimension=self.max_dim)

        __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_v_skeleton, __pyx_n_s_create_simplex_tree); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 55, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_2);
        __pyx_t_1 = __Pyx_PyDict_NewPresized(1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 55, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_1);
        __pyx_t_5 = PyInt_FromSsize_t(__pyx_v_self->max_dim); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 55, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_5);
        if (PyDict_SetItem(__pyx_t_1, __pyx_n_s_max_dimension, __pyx_t_5) < 0) __PYX_ERR(0, 55, __pyx_L1_error)
        __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
        __pyx_t_5 = __Pyx_PyObject_Call(__pyx_t_2, __pyx_empty_tuple, __pyx_t_1); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 55, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_5);
        __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
        __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
        __Pyx_XDECREF_SET(__pyx_v_st, __pyx_t_5);
        __pyx_t_5 = 0;

    +056:             for vtx_idx, filt in st.get_filtration():

        __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_st, __pyx_n_s_get_filtration); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 56, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_1);
        __pyx_t_2 = NULL;
        __pyx_t_13 = 0;
        #if CYTHON_UNPACK_METHODS
        if (likely(PyMethod_Check(__pyx_t_1))) {
          __pyx_t_2 = PyMethod_GET_SELF(__pyx_t_1);
          if (likely(__pyx_t_2)) {
            PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_1);
            __Pyx_INCREF(__pyx_t_2);
            __Pyx_INCREF(function);
            __Pyx_DECREF_SET(__pyx_t_1, function);
            __pyx_t_13 = 1;
          }
        }
        #endif
        {
          PyObject *__pyx_callargs[2] = {__pyx_t_2, NULL};
          __pyx_t_5 = __Pyx_PyObject_FastCall(__pyx_t_1, __pyx_callargs+1-__pyx_t_13, 0+__pyx_t_13);
          __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
          if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 56, __pyx_L1_error)
          __Pyx_GOTREF(__pyx_t_5);
          __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
        }
        if (likely(PyList_CheckExact(__pyx_t_5)) || PyTuple_CheckExact(__pyx_t_5)) {
          __pyx_t_1 = __pyx_t_5; __Pyx_INCREF(__pyx_t_1);
          __pyx_t_14 = 0;
          __pyx_t_15 = NULL;
        } else {
          __pyx_t_14 = -1; __pyx_t_1 = PyObject_GetIter(__pyx_t_5); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 56, __pyx_L1_error)
          __Pyx_GOTREF(__pyx_t_1);
          __pyx_t_15 = __Pyx_PyObject_GetIterNextFunc(__pyx_t_1); if (unlikely(!__pyx_t_15)) __PYX_ERR(0, 56, __pyx_L1_error)
        }
        __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
        for (;;) {
          if (likely(!__pyx_t_15)) {
            if (likely(PyList_CheckExact(__pyx_t_1))) {
              {
                Py_ssize_t __pyx_temp = __Pyx_PyList_GET_SIZE(__pyx_t_1);
                #if !CYTHON_ASSUME_SAFE_MACROS
                if (unlikely((__pyx_temp < 0))) __PYX_ERR(0, 56, __pyx_L1_error)
                #endif
                if (__pyx_t_14 >= __pyx_temp) break;
              }
              #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
              __pyx_t_5 = PyList_GET_ITEM(__pyx_t_1, __pyx_t_14); __Pyx_INCREF(__pyx_t_5); __pyx_t_14++; if (unlikely((0 < 0))) __PYX_ERR(0, 56, __pyx_L1_error)
              #else
              __pyx_t_5 = __Pyx_PySequence_ITEM(__pyx_t_1, __pyx_t_14); __pyx_t_14++; if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 56, __pyx_L1_error)
              __Pyx_GOTREF(__pyx_t_5);
              #endif
            } else {
              {
                Py_ssize_t __pyx_temp = __Pyx_PyTuple_GET_SIZE(__pyx_t_1);
                #if !CYTHON_ASSUME_SAFE_MACROS
                if (unlikely((__pyx_temp < 0))) __PYX_ERR(0, 56, __pyx_L1_error)
                #endif
                if (__pyx_t_14 >= __pyx_temp) break;
              }
              #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
              __pyx_t_5 = PyTuple_GET_ITEM(__pyx_t_1, __pyx_t_14); __Pyx_INCREF(__pyx_t_5); __pyx_t_14++; if (unlikely((0 < 0))) __PYX_ERR(0, 56, __pyx_L1_error)
              #else
              __pyx_t_5 = __Pyx_PySequence_ITEM(__pyx_t_1, __pyx_t_14); __pyx_t_14++; if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 56, __pyx_L1_error)
              __Pyx_GOTREF(__pyx_t_5);
              #endif
            }
          } else {
            __pyx_t_5 = __pyx_t_15(__pyx_t_1);
            if (unlikely(!__pyx_t_5)) {
              PyObject* exc_type = PyErr_Occurred();
              if (exc_type) {
                if (likely(__Pyx_PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) PyErr_Clear();
                else __PYX_ERR(0, 56, __pyx_L1_error)
              }
              break;
            }
            __Pyx_GOTREF(__pyx_t_5);
          }
          if ((likely(PyTuple_CheckExact(__pyx_t_5))) || (PyList_CheckExact(__pyx_t_5))) {
            PyObject* sequence = __pyx_t_5;
            Py_ssize_t size = __Pyx_PySequence_SIZE(sequence);
            if (unlikely(size != 2)) {
              if (size > 2) __Pyx_RaiseTooManyValuesError(2);
              else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size);
              __PYX_ERR(0, 56, __pyx_L1_error)
            }
            #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
            if (likely(PyTuple_CheckExact(sequence))) {
              __pyx_t_2 = PyTuple_GET_ITEM(sequence, 0);
              __pyx_t_4 = PyTuple_GET_ITEM(sequence, 1);
            } else {
              __pyx_t_2 = PyList_GET_ITEM(sequence, 0);
              __pyx_t_4 = PyList_GET_ITEM(sequence, 1);
            }
            __Pyx_INCREF(__pyx_t_2);
            __Pyx_INCREF(__pyx_t_4);
            #else
            __pyx_t_2 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 56, __pyx_L1_error)
            __Pyx_GOTREF(__pyx_t_2);
            __pyx_t_4 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 56, __pyx_L1_error)
            __Pyx_GOTREF(__pyx_t_4);
            #endif
            __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
          } else {
            Py_ssize_t index = -1;
            __pyx_t_3 = PyObject_GetIter(__pyx_t_5); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 56, __pyx_L1_error)
            __Pyx_GOTREF(__pyx_t_3);
            __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
            __pyx_t_6 = __Pyx_PyObject_GetIterNextFunc(__pyx_t_3);
            index = 0; __pyx_t_2 = __pyx_t_6(__pyx_t_3); if (unlikely(!__pyx_t_2)) goto __pyx_L9_unpacking_failed;
            __Pyx_GOTREF(__pyx_t_2);
            index = 1; __pyx_t_4 = __pyx_t_6(__pyx_t_3); if (unlikely(!__pyx_t_4)) goto __pyx_L9_unpacking_failed;
            __Pyx_GOTREF(__pyx_t_4);
            if (__Pyx_IternextUnpackEndCheck(__pyx_t_6(__pyx_t_3), 2) < 0) __PYX_ERR(0, 56, __pyx_L1_error)
            __pyx_t_6 = NULL;
            __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
            goto __pyx_L10_unpacking_done;
            __pyx_L9_unpacking_failed:;
            __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
            __pyx_t_6 = NULL;
            if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index);
            __PYX_ERR(0, 56, __pyx_L1_error)
            __pyx_L10_unpacking_done:;
          }
          __pyx_t_16 = __pyx_PyFloat_AsFloat(__pyx_t_4); if (unlikely((__pyx_t_16 == (float)-1) && PyErr_Occurred())) __PYX_ERR(0, 56, __pyx_L1_error)
          __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
          __Pyx_XDECREF_SET(__pyx_v_vtx_idx, __pyx_t_2);
          __pyx_t_2 = 0;
          __pyx_v_filt = __pyx_t_16;
    /* … */
          __pyx_L7_continue:;
        }
        __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
        goto __pyx_L18_for_end;
        __pyx_L8_break:;
        __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
        goto __pyx_L18_for_end;
        __pyx_L18_for_end:;

    +057:                 if filt > self.max_edge_length:

          __pyx_t_17 = (__pyx_v_filt > __pyx_v_self->max_edge_length);
          if (__pyx_t_17) {
    /* … */
          }

    +058:                     break

            goto __pyx_L8_break;

    +059:                 dim = len(vtx_idx) - 1  # dimension of simplex

          __pyx_t_18 = PyObject_Length(__pyx_v_vtx_idx); if (unlikely(__pyx_t_18 == ((Py_ssize_t)-1))) __PYX_ERR(0, 59, __pyx_L1_error)
          __pyx_v_dim = (__pyx_t_18 - 1);

    +060:                 t = max(<Py_ssize_t>ceil(filt / self.resolution), 0)

          __pyx_t_19 = 0;
          __pyx_t_18 = ((Py_ssize_t)ceil((__pyx_v_filt / __pyx_v_self->resolution)));
          __pyx_t_17 = (__pyx_t_19 > __pyx_t_18);
          if (__pyx_t_17) {
            __pyx_t_20 = __pyx_t_19;
          } else {
            __pyx_t_20 = __pyx_t_18;
          }
          __pyx_v_t = __pyx_t_20;

    +061:                 ecc_view[b, t] += (-1.)**dim

          __pyx_t_21 = __pyx_v_b;
          __pyx_t_22 = __pyx_v_t;
          *((float *) ( /* dim=1 */ (( /* dim=0 */ (__pyx_v_ecc_view.data + __pyx_t_21 * __pyx_v_ecc_view.strides[0]) ) + __pyx_t_22 * __pyx_v_ecc_view.strides[1]) )) += pow(-1., ((double)__pyx_v_dim));

     062:

     063:                 # calculation of gradient only for inputs that require gradient

    +064:                 if backprop:

          if (__pyx_v_backprop) {
    /* … */
          }

     065:                     # vertex

    +066:                     if dim == 0:

            switch (__pyx_v_dim) {
              case 0:
    /* … */
              break;
              case 1:

    +067:                         continue

              goto __pyx_L7_continue;

     068:                     # edge

    +069:                     elif dim == 1:

              break;
              default:

    +070:                         if grad_1 != NULL:

              __pyx_t_17 = (__pyx_v_grad_1 != NULL);
              if (__pyx_t_17) {
    /* … */
              }

    +071:                             free(grad_1)

                free(__pyx_v_grad_1);

    +072:                             free(grad_2)

                free(__pyx_v_grad_2);

     073:

    +074:                         vtx_idx_1 = vtx_idx[0]

              __pyx_t_5 = __Pyx_GetItemInt(__pyx_v_vtx_idx, 0, long, 1, __Pyx_PyInt_From_long, 0, 0, 0); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 74, __pyx_L1_error)
              __Pyx_GOTREF(__pyx_t_5);
              __pyx_t_20 = __Pyx_PyIndex_AsSsize_t(__pyx_t_5); if (unlikely((__pyx_t_20 == (Py_ssize_t)-1) && PyErr_Occurred())) __PYX_ERR(0, 74, __pyx_L1_error)
              __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
              __pyx_v_vtx_idx_1 = __pyx_t_20;

    +075:                         vtx_idx_2 = vtx_idx[1]

              __pyx_t_5 = __Pyx_GetItemInt(__pyx_v_vtx_idx, 1, long, 1, __Pyx_PyInt_From_long, 0, 0, 0); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 75, __pyx_L1_error)
              __Pyx_GOTREF(__pyx_t_5);
              __pyx_t_20 = __Pyx_PyIndex_AsSsize_t(__pyx_t_5); if (unlikely((__pyx_t_20 == (Py_ssize_t)-1) && PyErr_Occurred())) __PYX_ERR(0, 75, __pyx_L1_error)
              __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
              __pyx_v_vtx_idx_2 = __pyx_t_20;

    +076:                         vtx_1 = x_view[b, vtx_idx_1]    # shape: (d, )

              __pyx_t_23.data = __pyx_v_x_view.data;
              __pyx_t_23.memview = __pyx_v_x_view.memview;
              __PYX_INC_MEMVIEW(&__pyx_t_23, 1);
              {
        Py_ssize_t __pyx_tmp_idx = __pyx_v_b;
        Py_ssize_t __pyx_tmp_stride = __pyx_v_x_view.strides[0];
            __pyx_t_23.data += __pyx_tmp_idx * __pyx_tmp_stride;
    }

    {
        Py_ssize_t __pyx_tmp_idx = __pyx_v_vtx_idx_1;
        Py_ssize_t __pyx_tmp_stride = __pyx_v_x_view.strides[1];
            __pyx_t_23.data += __pyx_tmp_idx * __pyx_tmp_stride;
    }

    __pyx_t_23.shape[0] = __pyx_v_x_view.shape[2];
    __pyx_t_23.strides[0] = __pyx_v_x_view.strides[2];
        __pyx_t_23.suboffsets[0] = -1;

    __PYX_XCLEAR_MEMVIEW(&__pyx_v_vtx_1, 1);
              __pyx_v_vtx_1 = __pyx_t_23;
              __pyx_t_23.memview = NULL;
              __pyx_t_23.data = NULL;

    +077:                         vtx_2 = x_view[b, vtx_idx_2]    # shape: (d, )

              __pyx_t_23.data = __pyx_v_x_view.data;
              __pyx_t_23.memview = __pyx_v_x_view.memview;
              __PYX_INC_MEMVIEW(&__pyx_t_23, 1);
              {
        Py_ssize_t __pyx_tmp_idx = __pyx_v_b;
        Py_ssize_t __pyx_tmp_stride = __pyx_v_x_view.strides[0];
            __pyx_t_23.data += __pyx_tmp_idx * __pyx_tmp_stride;
    }

    {
        Py_ssize_t __pyx_tmp_idx = __pyx_v_vtx_idx_2;
        Py_ssize_t __pyx_tmp_stride = __pyx_v_x_view.strides[1];
            __pyx_t_23.data += __pyx_tmp_idx * __pyx_tmp_stride;
    }

    __pyx_t_23.shape[0] = __pyx_v_x_view.shape[2];
    __pyx_t_23.strides[0] = __pyx_v_x_view.strides[2];
        __pyx_t_23.suboffsets[0] = -1;

    __PYX_XCLEAR_MEMVIEW(&__pyx_v_vtx_2, 1);
              __pyx_v_vtx_2 = __pyx_t_23;
              __pyx_t_23.memview = NULL;
              __pyx_t_23.data = NULL;

     078:

    +079:                         grad_1, grad_2 = RipsEccBackbone._cal_edge_grad(vtx_1, vtx_2, filt, d)

              __pyx_t_24 = __pyx_f_3ecc_15RipsEccBackbone__cal_edge_grad(__pyx_v_vtx_1, __pyx_v_vtx_2, __pyx_v_filt, __pyx_v_d); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 79, __pyx_L1_error)
              __pyx_t_25 = __pyx_t_24.f0;
              __pyx_t_26 = __pyx_t_24.f1;
              __pyx_v_grad_1 = __pyx_t_25;
              __pyx_v_grad_2 = __pyx_t_26;

     080:

    +081:                         for i in range(d):

              __pyx_t_20 = __pyx_v_d;
              __pyx_t_18 = __pyx_t_20;
              for (__pyx_t_27 = 0; __pyx_t_27 < __pyx_t_18; __pyx_t_27+=1) {
                __pyx_v_i = __pyx_t_27;

    +082:                             grad_local_view[b, vtx_idx_1, i, t] += grad_1[i] * self.impulse

                __pyx_t_22 = __pyx_v_b;
                __pyx_t_21 = __pyx_v_vtx_idx_1;
                __pyx_t_28 = __pyx_v_i;
                __pyx_t_29 = __pyx_v_t;
                *((float *) ( /* dim=3 */ (( /* dim=2 */ (( /* dim=1 */ (( /* dim=0 */ (__pyx_v_grad_local_view.data + __pyx_t_22 * __pyx_v_grad_local_view.strides[0]) ) + __pyx_t_21 * __pyx_v_grad_local_view.strides[1]) ) + __pyx_t_28 * __pyx_v_grad_local_view.strides[2]) ) + __pyx_t_29 * __pyx_v_grad_local_view.strides[3]) )) += ((__pyx_v_grad_1[__pyx_v_i]) * __pyx_v_self->impulse);

    +083:                             grad_local_view[b, vtx_idx_2, i, t] += grad_2[i] * self.impulse

                __pyx_t_29 = __pyx_v_b;
                __pyx_t_28 = __pyx_v_vtx_idx_2;
                __pyx_t_21 = __pyx_v_i;
                __pyx_t_22 = __pyx_v_t;
                *((float *) ( /* dim=3 */ (( /* dim=2 */ (( /* dim=1 */ (( /* dim=0 */ (__pyx_v_grad_local_view.data + __pyx_t_29 * __pyx_v_grad_local_view.strides[0]) ) + __pyx_t_28 * __pyx_v_grad_local_view.strides[1]) ) + __pyx_t_21 * __pyx_v_grad_local_view.strides[2]) ) + __pyx_t_22 * __pyx_v_grad_local_view.strides[3]) )) += ((__pyx_v_grad_2[__pyx_v_i]) * __pyx_v_self->impulse);
              }

     084:                     # triangle or higher dimensional simplex

     085:                     else:

    +086:                         for i in range(d):

              __pyx_t_20 = __pyx_v_d;
              __pyx_t_18 = __pyx_t_20;
              for (__pyx_t_27 = 0; __pyx_t_27 < __pyx_t_18; __pyx_t_27+=1) {
                __pyx_v_i = __pyx_t_27;

    +087:                             grad_local_view[b, vtx_idx_1, i, t] += (-1)**(dim+1) * grad_1[i] * self.impulse

                __pyx_t_22 = __pyx_v_b;
                __pyx_t_21 = __pyx_v_vtx_idx_1;
                __pyx_t_28 = __pyx_v_i;
                __pyx_t_29 = __pyx_v_t;
                *((float *) ( /* dim=3 */ (( /* dim=2 */ (( /* dim=1 */ (( /* dim=0 */ (__pyx_v_grad_local_view.data + __pyx_t_22 * __pyx_v_grad_local_view.strides[0]) ) + __pyx_t_21 * __pyx_v_grad_local_view.strides[1]) ) + __pyx_t_28 * __pyx_v_grad_local_view.strides[2]) ) + __pyx_t_29 * __pyx_v_grad_local_view.strides[3]) )) += ((pow(-1.0, ((double)(__pyx_v_dim + 1))) * (__pyx_v_grad_1[__pyx_v_i])) * __pyx_v_self->impulse);

    +088:                             grad_local_view[b, vtx_idx_2, i, t] += (-1)**(dim+1) * grad_2[i] * self.impulse

                __pyx_t_29 = __pyx_v_b;
                __pyx_t_28 = __pyx_v_vtx_idx_2;
                __pyx_t_21 = __pyx_v_i;
                __pyx_t_22 = __pyx_v_t;
                *((float *) ( /* dim=3 */ (( /* dim=2 */ (( /* dim=1 */ (( /* dim=0 */ (__pyx_v_grad_local_view.data + __pyx_t_29 * __pyx_v_grad_local_view.strides[0]) ) + __pyx_t_28 * __pyx_v_grad_local_view.strides[1]) ) + __pyx_t_21 * __pyx_v_grad_local_view.strides[2]) ) + __pyx_t_22 * __pyx_v_grad_local_view.strides[3]) )) += ((pow(-1.0, ((double)(__pyx_v_dim + 1))) * (__pyx_v_grad_2[__pyx_v_i])) * __pyx_v_self->impulse);
              }
              break;
            }

     089:             # free memory after each data

    +090:             free(grad_1)

        free(__pyx_v_grad_1);

    +091:             free(grad_2)

        free(__pyx_v_grad_2);

     092:             # cumsum

    +093:             for i in range(self.steps - 1):

        __pyx_t_14 = (__pyx_v_self->steps - 1);
        __pyx_t_20 = __pyx_t_14;
        for (__pyx_t_18 = 0; __pyx_t_18 < __pyx_t_20; __pyx_t_18+=1) {
          __pyx_v_i = __pyx_t_18;

    +094:                 ecc_view[b, i+1] += ecc_view[b, i]

          __pyx_t_22 = __pyx_v_b;
          __pyx_t_21 = __pyx_v_i;
          __pyx_t_28 = __pyx_v_b;
          __pyx_t_29 = (__pyx_v_i + 1);
          *((float *) ( /* dim=1 */ (( /* dim=0 */ (__pyx_v_ecc_view.data + __pyx_t_28 * __pyx_v_ecc_view.strides[0]) ) + __pyx_t_29 * __pyx_v_ecc_view.strides[1]) )) += (*((float *) ( /* dim=1 */ (( /* dim=0 */ (__pyx_v_ecc_view.data + __pyx_t_22 * __pyx_v_ecc_view.strides[0]) ) + __pyx_t_21 * __pyx_v_ecc_view.strides[1]) )));
        }
      }

    +095:         return ecc, grad_local

      __Pyx_XDECREF(__pyx_r);
      __pyx_t_1 = PyTuple_New(2); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 95, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_1);
      __Pyx_INCREF(__pyx_v_ecc);
      __Pyx_GIVEREF(__pyx_v_ecc);
      if (__Pyx_PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_v_ecc)) __PYX_ERR(0, 95, __pyx_L1_error);
      __Pyx_INCREF(__pyx_v_grad_local);
      __Pyx_GIVEREF(__pyx_v_grad_local);
      if (__Pyx_PyTuple_SET_ITEM(__pyx_t_1, 1, __pyx_v_grad_local)) __PYX_ERR(0, 95, __pyx_L1_error);
      __pyx_r = __pyx_t_1;
      __pyx_t_1 = 0;
      goto __pyx_L0;

     096:

     097:

     098:     @staticmethod

     099:     @cython.boundscheck(False)      # turn off bounds-checking for entire function

     100:     @cython.wraparound(False)       # turn off negative index wrapping for entire function

     101:     @cython.cdivision(True)         # turn off checking for division by zero

    +102:     cdef inline (float*, float*) _cal_edge_grad(float[:] vtx_1, float[:] vtx_2, float filt, int d):

    static CYTHON_INLINE __pyx_ctuple_float__ptr__and_float__ptr __pyx_f_3ecc_15RipsEccBackbone__cal_edge_grad(__Pyx_memviewslice __pyx_v_vtx_1, __Pyx_memviewslice __pyx_v_vtx_2, float __pyx_v_filt, int __pyx_v_d) {
      float *__pyx_v_grad_1;
      float *__pyx_v_grad_2;
      int __pyx_v_i;
      __pyx_ctuple_float__ptr__and_float__ptr __pyx_r;
    /* … */
      /* function exit code */
      __pyx_L0:;
      return __pyx_r;
    }
    /* … */
    struct __pyx_ctuple_float__ptr__and_float__ptr {
      float *f0;
      float *f1;
    };

    +103:         cdef float *grad_1 = <float *> malloc(d * sizeof(float))

      __pyx_v_grad_1 = ((float *)malloc((__pyx_v_d * (sizeof(float)))));

    +104:         cdef float *grad_2 = <float *> malloc(d * sizeof(float))

      __pyx_v_grad_2 = ((float *)malloc((__pyx_v_d * (sizeof(float)))));

     105:

    +106:         for i in range(d):

      __pyx_t_1 = __pyx_v_d;
      __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;

    +107:             grad_1[i] = (vtx_1[i] - vtx_2[i]) / filt

        __pyx_t_4 = __pyx_v_i;
        __pyx_t_5 = __pyx_v_i;
        (__pyx_v_grad_1[__pyx_v_i]) = (((*((float *) ( /* dim=0 */ (__pyx_v_vtx_1.data + __pyx_t_4 * __pyx_v_vtx_1.strides[0]) ))) - (*((float *) ( /* dim=0 */ (__pyx_v_vtx_2.data + __pyx_t_5 * __pyx_v_vtx_2.strides[0]) )))) / __pyx_v_filt);

    +108:             grad_2[i] = (vtx_2[i] - vtx_1[i]) / filt

        __pyx_t_5 = __pyx_v_i;
        __pyx_t_4 = __pyx_v_i;
        (__pyx_v_grad_2[__pyx_v_i]) = (((*((float *) ( /* dim=0 */ (__pyx_v_vtx_2.data + __pyx_t_5 * __pyx_v_vtx_2.strides[0]) ))) - (*((float *) ( /* dim=0 */ (__pyx_v_vtx_1.data + __pyx_t_4 * __pyx_v_vtx_1.strides[0]) )))) / __pyx_v_filt);
      }

     109:

    +110:         return grad_1, grad_2

      __pyx_t_6.f0 = __pyx_v_grad_1;
      __pyx_t_6.f1 = __pyx_v_grad_2;
      __pyx_r = __pyx_t_6;
      goto __pyx_L0;