Generated by Cython 0.22

Raw output: psparse.c

+001: # psparse.pyx
  __pyx_t_1 = PyDict_New(); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  __Pyx_GOTREF(__pyx_t_1);
  if (PyDict_SetItem(__pyx_d, __pyx_n_s_test, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 002: 
 003: #-----------------------------------------------------------------------------
 004: # Imports
 005: #-----------------------------------------------------------------------------
 006: cimport cython
 007: cimport numpy as np
+008: import numpy as np
  __pyx_t_1 = __Pyx_Import(__pyx_n_s_numpy, 0, -1); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 8; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  __Pyx_GOTREF(__pyx_t_1);
  if (PyDict_SetItem(__pyx_d, __pyx_n_s_np, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 8; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+009: import scipy.sparse
  __pyx_t_1 = __Pyx_Import(__pyx_n_s_scipy_sparse, 0, -1); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 9; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  __Pyx_GOTREF(__pyx_t_1);
  if (PyDict_SetItem(__pyx_d, __pyx_n_s_scipy, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 9; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 010: from libc.stddef cimport ptrdiff_t
 011: from cython.parallel import parallel, prange
 012: 
 013: #-----------------------------------------------------------------------------
 014: # Headers
 015: #-----------------------------------------------------------------------------
 016: 
 017: ctypedef int csi
 018: 
 019: ctypedef struct cs:
 020:     # matrix in compressed-column or triplet form
 021:     csi nzmax       # maximum number of entries
 022:     csi m           # number of rows
 023:     csi n           # number of columns
 024:     csi *p          # column pointers (size n+1) or col indices (size nzmax)
 025:     csi *i          # row indices, size nzmax
 026:     double *x       # numerical values, size nzmax
 027:     csi nz          # # of entries in triplet matrix, -1 for compressed-col
 028: 
 029: cdef extern csi cs_gaxpy (cs *A, double *x, double *y) nogil
 030: cdef extern csi cs_print (cs *A, csi brief) nogil
 031: 
 032: cdef extern csi cs_multiply (cs *A, cs *B) nogil
 033: 
+034: assert sizeof(csi) == 4
  #ifndef CYTHON_WITHOUT_ASSERTIONS
  if (unlikely(!Py_OptimizeFlag)) {
    if (unlikely(!(((sizeof(__pyx_t_7psparse_csi)) == 4) != 0))) {
      PyErr_SetNone(PyExc_AssertionError);
      {__pyx_filename = __pyx_f[0]; __pyx_lineno = 34; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
    }
  }
  #endif
 035: 
 036: #-----------------------------------------------------------------------------
 037: # Functions
 038: #-----------------------------------------------------------------------------
 039: 
+040: def csc_multiply(X not None, Y not None):
/* Python wrapper */
static PyObject *__pyx_pw_7psparse_1csc_multiply(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
static PyMethodDef __pyx_mdef_7psparse_1csc_multiply = {"csc_multiply", (PyCFunction)__pyx_pw_7psparse_1csc_multiply, METH_VARARGS|METH_KEYWORDS, 0};
static PyObject *__pyx_pw_7psparse_1csc_multiply(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
  PyObject *__pyx_v_X = 0;
  PyObject *__pyx_v_Y = 0;
  PyObject *__pyx_r = 0;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("csc_multiply (wrapper)", 0);
  {
    static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_X,&__pyx_n_s_Y,0};
    PyObject* values[2] = {0,0};
    if (unlikely(__pyx_kwds)) {
      Py_ssize_t kw_args;
      const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args);
      switch (pos_args) {
        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
        case  0: break;
        default: goto __pyx_L5_argtuple_error;
      }
      kw_args = PyDict_Size(__pyx_kwds);
      switch (pos_args) {
        case  0:
        if (likely((values[0] = PyDict_GetItem(__pyx_kwds, __pyx_n_s_X)) != 0)) kw_args--;
        else goto __pyx_L5_argtuple_error;
        case  1:
        if (likely((values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s_Y)) != 0)) kw_args--;
        else {
          __Pyx_RaiseArgtupleInvalid("csc_multiply", 1, 2, 2, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 40; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
        }
      }
      if (unlikely(kw_args > 0)) {
        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "csc_multiply") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 40; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
      }
    } else if (PyTuple_GET_SIZE(__pyx_args) != 2) {
      goto __pyx_L5_argtuple_error;
    } else {
      values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
      values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
    }
    __pyx_v_X = values[0];
    __pyx_v_Y = values[1];
  }
  goto __pyx_L4_argument_unpacking_done;
  __pyx_L5_argtuple_error:;
  __Pyx_RaiseArgtupleInvalid("csc_multiply", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 40; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
  __pyx_L3_error:;
  __Pyx_AddTraceback("psparse.csc_multiply", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __Pyx_RefNannyFinishContext();
  return NULL;
  __pyx_L4_argument_unpacking_done:;
  if (unlikely(((PyObject *)__pyx_v_X) == Py_None)) {
    PyErr_Format(PyExc_TypeError, "Argument '%.200s' must not be None", "X"); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 40; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  }
  if (unlikely(((PyObject *)__pyx_v_Y) == Py_None)) {
    PyErr_Format(PyExc_TypeError, "Argument '%.200s' must not be None", "Y"); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 40; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  }
  __pyx_r = __pyx_pf_7psparse_csc_multiply(__pyx_self, __pyx_v_X, __pyx_v_Y);
  int __pyx_lineno = 0;
  const char *__pyx_filename = NULL;
  int __pyx_clineno = 0;

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

static PyObject *__pyx_pf_7psparse_csc_multiply(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_X, PyObject *__pyx_v_Y) {
  __pyx_t_7psparse_cs __pyx_v_csX;
  PyArrayObject *__pyx_v_Xindptr = 0;
  PyArrayObject *__pyx_v_Xindices = 0;
  PyArrayObject *__pyx_v_Xdata = 0;
  __pyx_t_7psparse_cs __pyx_v_csY;
  PyArrayObject *__pyx_v_Yindptr = 0;
  PyArrayObject *__pyx_v_Yindices = 0;
  PyArrayObject *__pyx_v_Ydata = 0;
  __pyx_t_7psparse_csi __pyx_v_res;
  __Pyx_LocalBuf_ND __pyx_pybuffernd_Xdata;
  __Pyx_Buffer __pyx_pybuffer_Xdata;
  __Pyx_LocalBuf_ND __pyx_pybuffernd_Xindices;
  __Pyx_Buffer __pyx_pybuffer_Xindices;
  __Pyx_LocalBuf_ND __pyx_pybuffernd_Xindptr;
  __Pyx_Buffer __pyx_pybuffer_Xindptr;
  __Pyx_LocalBuf_ND __pyx_pybuffernd_Ydata;
  __Pyx_Buffer __pyx_pybuffer_Ydata;
  __Pyx_LocalBuf_ND __pyx_pybuffernd_Yindices;
  __Pyx_Buffer __pyx_pybuffer_Yindices;
  __Pyx_LocalBuf_ND __pyx_pybuffernd_Yindptr;
  __Pyx_Buffer __pyx_pybuffer_Yindptr;
  PyObject *__pyx_r = NULL;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("csc_multiply", 0);
  __pyx_pybuffer_Xindptr.pybuffer.buf = NULL;
  __pyx_pybuffer_Xindptr.refcount = 0;
  __pyx_pybuffernd_Xindptr.data = NULL;
  __pyx_pybuffernd_Xindptr.rcbuffer = &__pyx_pybuffer_Xindptr;
  __pyx_pybuffer_Xindices.pybuffer.buf = NULL;
  __pyx_pybuffer_Xindices.refcount = 0;
  __pyx_pybuffernd_Xindices.data = NULL;
  __pyx_pybuffernd_Xindices.rcbuffer = &__pyx_pybuffer_Xindices;
  __pyx_pybuffer_Xdata.pybuffer.buf = NULL;
  __pyx_pybuffer_Xdata.refcount = 0;
  __pyx_pybuffernd_Xdata.data = NULL;
  __pyx_pybuffernd_Xdata.rcbuffer = &__pyx_pybuffer_Xdata;
  __pyx_pybuffer_Yindptr.pybuffer.buf = NULL;
  __pyx_pybuffer_Yindptr.refcount = 0;
  __pyx_pybuffernd_Yindptr.data = NULL;
  __pyx_pybuffernd_Yindptr.rcbuffer = &__pyx_pybuffer_Yindptr;
  __pyx_pybuffer_Yindices.pybuffer.buf = NULL;
  __pyx_pybuffer_Yindices.refcount = 0;
  __pyx_pybuffernd_Yindices.data = NULL;
  __pyx_pybuffernd_Yindices.rcbuffer = &__pyx_pybuffer_Yindices;
  __pyx_pybuffer_Ydata.pybuffer.buf = NULL;
  __pyx_pybuffer_Ydata.refcount = 0;
  __pyx_pybuffernd_Ydata.data = NULL;
  __pyx_pybuffernd_Ydata.rcbuffer = &__pyx_pybuffer_Ydata;
/* … */
  /* function exit code */
  __pyx_L1_error:;
  __Pyx_XDECREF(__pyx_t_1);
  __Pyx_XDECREF(__pyx_t_2);
  __Pyx_XDECREF(__pyx_t_3);
  { PyObject *__pyx_type, *__pyx_value, *__pyx_tb;
    __Pyx_ErrFetch(&__pyx_type, &__pyx_value, &__pyx_tb);
    __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_Xdata.rcbuffer->pybuffer);
    __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_Xindices.rcbuffer->pybuffer);
    __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_Xindptr.rcbuffer->pybuffer);
    __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_Ydata.rcbuffer->pybuffer);
    __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_Yindices.rcbuffer->pybuffer);
    __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_Yindptr.rcbuffer->pybuffer);
  __Pyx_ErrRestore(__pyx_type, __pyx_value, __pyx_tb);}
  __Pyx_AddTraceback("psparse.csc_multiply", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __pyx_r = NULL;
  goto __pyx_L2;
  __pyx_L0:;
  __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_Xdata.rcbuffer->pybuffer);
  __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_Xindices.rcbuffer->pybuffer);
  __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_Xindptr.rcbuffer->pybuffer);
  __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_Ydata.rcbuffer->pybuffer);
  __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_Yindices.rcbuffer->pybuffer);
  __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_Yindptr.rcbuffer->pybuffer);
  __pyx_L2:;
  __Pyx_XDECREF((PyObject *)__pyx_v_Xindptr);
  __Pyx_XDECREF((PyObject *)__pyx_v_Xindices);
  __Pyx_XDECREF((PyObject *)__pyx_v_Xdata);
  __Pyx_XDECREF((PyObject *)__pyx_v_Yindptr);
  __Pyx_XDECREF((PyObject *)__pyx_v_Yindices);
  __Pyx_XDECREF((PyObject *)__pyx_v_Ydata);
  __Pyx_XGIVEREF(__pyx_r);
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}
/* … */
  __pyx_tuple__9 = PyTuple_Pack(11, __pyx_n_s_X, __pyx_n_s_Y, __pyx_n_s_csX, __pyx_n_s_Xindptr, __pyx_n_s_Xindices, __pyx_n_s_Xdata, __pyx_n_s_csY, __pyx_n_s_Yindptr, __pyx_n_s_Yindices, __pyx_n_s_Ydata, __pyx_n_s_res); if (unlikely(!__pyx_tuple__9)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 40; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  __Pyx_GOTREF(__pyx_tuple__9);
  __Pyx_GIVEREF(__pyx_tuple__9);
/* … */
  __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_7psparse_1csc_multiply, NULL, __pyx_n_s_psparse); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 40; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  __Pyx_GOTREF(__pyx_t_1);
  if (PyDict_SetItem(__pyx_d, __pyx_n_s_csc_multiply, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 40; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_codeobj__10 = (PyObject*)__Pyx_PyCode_New(2, 0, 11, 0, 0, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__9, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_users_nboley_src_boosting_peyto, __pyx_n_s_csc_multiply, 40, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__10)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 40; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+041:     if X.shape[1] != Y.shape[0]:
  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_X, __pyx_n_s_shape); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 41; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_2 = __Pyx_GetItemInt(__pyx_t_1, 1, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(__pyx_t_2 == NULL)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 41; __pyx_clineno = __LINE__; goto __pyx_L1_error;};
  __Pyx_GOTREF(__pyx_t_2);
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_Y, __pyx_n_s_shape); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 41; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_3 = __Pyx_GetItemInt(__pyx_t_1, 0, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(__pyx_t_3 == NULL)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 41; __pyx_clineno = __LINE__; goto __pyx_L1_error;};
  __Pyx_GOTREF(__pyx_t_3);
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_t_1 = PyObject_RichCompare(__pyx_t_2, __pyx_t_3, Py_NE); __Pyx_XGOTREF(__pyx_t_1); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 41; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  __pyx_t_4 = __Pyx_PyObject_IsTrue(__pyx_t_1); if (unlikely(__pyx_t_4 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 41; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  if (__pyx_t_4) {
+042:         raise ValueError('matrices are not aligned')
    __pyx_t_1 = __Pyx_PyObject_Call(__pyx_builtin_ValueError, __pyx_tuple_, NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 42; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
    __Pyx_GOTREF(__pyx_t_1);
    __Pyx_Raise(__pyx_t_1, 0, 0, 0);
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
    {__pyx_filename = __pyx_f[0]; __pyx_lineno = 42; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  }
/* … */
  __pyx_tuple_ = PyTuple_Pack(1, __pyx_kp_s_matrices_are_not_aligned); if (unlikely(!__pyx_tuple_)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 42; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  __Pyx_GOTREF(__pyx_tuple_);
  __Pyx_GIVEREF(__pyx_tuple_);
 043: 
 044:     cdef cs csX
+045:     cdef np.ndarray[csi, ndim=1, mode = 'c'] Xindptr  = X.indptr
  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_X, __pyx_n_s_indptr); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 45; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  __Pyx_GOTREF(__pyx_t_1);
  if (!(likely(((__pyx_t_1) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_1, __pyx_ptype_5numpy_ndarray))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 45; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  __pyx_t_5 = ((PyArrayObject *)__pyx_t_1);
  {
    __Pyx_BufFmt_StackElem __pyx_stack[1];
    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_Xindptr.rcbuffer->pybuffer, (PyObject*)__pyx_t_5, &__Pyx_TypeInfo_nn___pyx_t_7psparse_csi, PyBUF_FORMAT| PyBUF_C_CONTIGUOUS, 1, 0, __pyx_stack) == -1)) {
      __pyx_v_Xindptr = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_pybuffernd_Xindptr.rcbuffer->pybuffer.buf = NULL;
      {__pyx_filename = __pyx_f[0]; __pyx_lineno = 45; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
    } else {__pyx_pybuffernd_Xindptr.diminfo[0].strides = __pyx_pybuffernd_Xindptr.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_Xindptr.diminfo[0].shape = __pyx_pybuffernd_Xindptr.rcbuffer->pybuffer.shape[0];
    }
  }
  __pyx_t_5 = 0;
  __pyx_v_Xindptr = ((PyArrayObject *)__pyx_t_1);
  __pyx_t_1 = 0;
+046:     cdef np.ndarray[csi, ndim=1, mode = 'c'] Xindices = X.indices
  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_X, __pyx_n_s_indices); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 46; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  __Pyx_GOTREF(__pyx_t_1);
  if (!(likely(((__pyx_t_1) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_1, __pyx_ptype_5numpy_ndarray))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 46; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  __pyx_t_6 = ((PyArrayObject *)__pyx_t_1);
  {
    __Pyx_BufFmt_StackElem __pyx_stack[1];
    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_Xindices.rcbuffer->pybuffer, (PyObject*)__pyx_t_6, &__Pyx_TypeInfo_nn___pyx_t_7psparse_csi, PyBUF_FORMAT| PyBUF_C_CONTIGUOUS, 1, 0, __pyx_stack) == -1)) {
      __pyx_v_Xindices = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_pybuffernd_Xindices.rcbuffer->pybuffer.buf = NULL;
      {__pyx_filename = __pyx_f[0]; __pyx_lineno = 46; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
    } else {__pyx_pybuffernd_Xindices.diminfo[0].strides = __pyx_pybuffernd_Xindices.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_Xindices.diminfo[0].shape = __pyx_pybuffernd_Xindices.rcbuffer->pybuffer.shape[0];
    }
  }
  __pyx_t_6 = 0;
  __pyx_v_Xindices = ((PyArrayObject *)__pyx_t_1);
  __pyx_t_1 = 0;
+047:     cdef np.ndarray[double, ndim=1, mode = 'c'] Xdata = X.data
  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_X, __pyx_n_s_data); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 47; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  __Pyx_GOTREF(__pyx_t_1);
  if (!(likely(((__pyx_t_1) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_1, __pyx_ptype_5numpy_ndarray))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 47; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  __pyx_t_7 = ((PyArrayObject *)__pyx_t_1);
  {
    __Pyx_BufFmt_StackElem __pyx_stack[1];
    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_Xdata.rcbuffer->pybuffer, (PyObject*)__pyx_t_7, &__Pyx_TypeInfo_double, PyBUF_FORMAT| PyBUF_C_CONTIGUOUS, 1, 0, __pyx_stack) == -1)) {
      __pyx_v_Xdata = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_pybuffernd_Xdata.rcbuffer->pybuffer.buf = NULL;
      {__pyx_filename = __pyx_f[0]; __pyx_lineno = 47; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
    } else {__pyx_pybuffernd_Xdata.diminfo[0].strides = __pyx_pybuffernd_Xdata.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_Xdata.diminfo[0].shape = __pyx_pybuffernd_Xdata.rcbuffer->pybuffer.shape[0];
    }
  }
  __pyx_t_7 = 0;
  __pyx_v_Xdata = ((PyArrayObject *)__pyx_t_1);
  __pyx_t_1 = 0;
 048: 
 049:     # Pack the scipy data into the CSparse struct. This is just copying some
 050:     # pointers.
+051:     csX.nzmax = X.data.shape[0]
  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_X, __pyx_n_s_data); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 51; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_shape); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 51; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  __Pyx_GOTREF(__pyx_t_3);
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_t_1 = __Pyx_GetItemInt(__pyx_t_3, 0, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(__pyx_t_1 == NULL)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 51; __pyx_clineno = __LINE__; goto __pyx_L1_error;};
  __Pyx_GOTREF(__pyx_t_1);
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  __pyx_t_8 = __Pyx_PyInt_As_int(__pyx_t_1); if (unlikely((__pyx_t_8 == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 51; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_v_csX.nzmax = __pyx_t_8;
+052:     csX.m = X.shape[0]
  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_X, __pyx_n_s_shape); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 52; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_3 = __Pyx_GetItemInt(__pyx_t_1, 0, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(__pyx_t_3 == NULL)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 52; __pyx_clineno = __LINE__; goto __pyx_L1_error;};
  __Pyx_GOTREF(__pyx_t_3);
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_t_8 = __Pyx_PyInt_As_int(__pyx_t_3); if (unlikely((__pyx_t_8 == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 52; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  __pyx_v_csX.m = __pyx_t_8;
+053:     csX.n = X.shape[1]
  __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_v_X, __pyx_n_s_shape); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 53; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  __Pyx_GOTREF(__pyx_t_3);
  __pyx_t_1 = __Pyx_GetItemInt(__pyx_t_3, 1, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(__pyx_t_1 == NULL)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 53; __pyx_clineno = __LINE__; goto __pyx_L1_error;};
  __Pyx_GOTREF(__pyx_t_1);
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  __pyx_t_8 = __Pyx_PyInt_As_int(__pyx_t_1); if (unlikely((__pyx_t_8 == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 53; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_v_csX.n = __pyx_t_8;
+054:     csX.p = &Xindptr[0]
  __pyx_t_9 = 0;
  __pyx_t_10 = -1;
  if (__pyx_t_9 < 0) {
    __pyx_t_9 += __pyx_pybuffernd_Xindptr.diminfo[0].shape;
    if (unlikely(__pyx_t_9 < 0)) __pyx_t_10 = 0;
  } else if (unlikely(__pyx_t_9 >= __pyx_pybuffernd_Xindptr.diminfo[0].shape)) __pyx_t_10 = 0;
  if (unlikely(__pyx_t_10 != -1)) {
    __Pyx_RaiseBufferIndexError(__pyx_t_10);
    {__pyx_filename = __pyx_f[0]; __pyx_lineno = 54; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  }
  __pyx_v_csX.p = (&(*__Pyx_BufPtrCContig1d(__pyx_t_7psparse_csi *, __pyx_pybuffernd_Xindptr.rcbuffer->pybuffer.buf, __pyx_t_9, __pyx_pybuffernd_Xindptr.diminfo[0].strides)));
+055:     csX.i = &Xindices[0]
  __pyx_t_11 = 0;
  __pyx_t_10 = -1;
  if (__pyx_t_11 < 0) {
    __pyx_t_11 += __pyx_pybuffernd_Xindices.diminfo[0].shape;
    if (unlikely(__pyx_t_11 < 0)) __pyx_t_10 = 0;
  } else if (unlikely(__pyx_t_11 >= __pyx_pybuffernd_Xindices.diminfo[0].shape)) __pyx_t_10 = 0;
  if (unlikely(__pyx_t_10 != -1)) {
    __Pyx_RaiseBufferIndexError(__pyx_t_10);
    {__pyx_filename = __pyx_f[0]; __pyx_lineno = 55; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  }
  __pyx_v_csX.i = (&(*__Pyx_BufPtrCContig1d(__pyx_t_7psparse_csi *, __pyx_pybuffernd_Xindices.rcbuffer->pybuffer.buf, __pyx_t_11, __pyx_pybuffernd_Xindices.diminfo[0].strides)));
+056:     csX.x = &Xdata[0]
  __pyx_t_12 = 0;
  __pyx_t_10 = -1;
  if (__pyx_t_12 < 0) {
    __pyx_t_12 += __pyx_pybuffernd_Xdata.diminfo[0].shape;
    if (unlikely(__pyx_t_12 < 0)) __pyx_t_10 = 0;
  } else if (unlikely(__pyx_t_12 >= __pyx_pybuffernd_Xdata.diminfo[0].shape)) __pyx_t_10 = 0;
  if (unlikely(__pyx_t_10 != -1)) {
    __Pyx_RaiseBufferIndexError(__pyx_t_10);
    {__pyx_filename = __pyx_f[0]; __pyx_lineno = 56; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  }
  __pyx_v_csX.x = (&(*__Pyx_BufPtrCContig1d(double *, __pyx_pybuffernd_Xdata.rcbuffer->pybuffer.buf, __pyx_t_12, __pyx_pybuffernd_Xdata.diminfo[0].strides)));
+057:     csX.nz = -1  # to indicate CSC format
  __pyx_v_csX.nz = -1;
 058: 
 059:     cdef cs csY
+060:     cdef np.ndarray[csi, ndim=1, mode = 'c'] Yindptr  = Y.indptr
  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_Y, __pyx_n_s_indptr); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 60; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  __Pyx_GOTREF(__pyx_t_1);
  if (!(likely(((__pyx_t_1) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_1, __pyx_ptype_5numpy_ndarray))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 60; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  __pyx_t_13 = ((PyArrayObject *)__pyx_t_1);
  {
    __Pyx_BufFmt_StackElem __pyx_stack[1];
    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_Yindptr.rcbuffer->pybuffer, (PyObject*)__pyx_t_13, &__Pyx_TypeInfo_nn___pyx_t_7psparse_csi, PyBUF_FORMAT| PyBUF_C_CONTIGUOUS, 1, 0, __pyx_stack) == -1)) {
      __pyx_v_Yindptr = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_pybuffernd_Yindptr.rcbuffer->pybuffer.buf = NULL;
      {__pyx_filename = __pyx_f[0]; __pyx_lineno = 60; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
    } else {__pyx_pybuffernd_Yindptr.diminfo[0].strides = __pyx_pybuffernd_Yindptr.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_Yindptr.diminfo[0].shape = __pyx_pybuffernd_Yindptr.rcbuffer->pybuffer.shape[0];
    }
  }
  __pyx_t_13 = 0;
  __pyx_v_Yindptr = ((PyArrayObject *)__pyx_t_1);
  __pyx_t_1 = 0;
+061:     cdef np.ndarray[csi, ndim=1, mode = 'c'] Yindices = Y.indices
  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_Y, __pyx_n_s_indices); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 61; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  __Pyx_GOTREF(__pyx_t_1);
  if (!(likely(((__pyx_t_1) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_1, __pyx_ptype_5numpy_ndarray))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 61; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  __pyx_t_14 = ((PyArrayObject *)__pyx_t_1);
  {
    __Pyx_BufFmt_StackElem __pyx_stack[1];
    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_Yindices.rcbuffer->pybuffer, (PyObject*)__pyx_t_14, &__Pyx_TypeInfo_nn___pyx_t_7psparse_csi, PyBUF_FORMAT| PyBUF_C_CONTIGUOUS, 1, 0, __pyx_stack) == -1)) {
      __pyx_v_Yindices = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_pybuffernd_Yindices.rcbuffer->pybuffer.buf = NULL;
      {__pyx_filename = __pyx_f[0]; __pyx_lineno = 61; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
    } else {__pyx_pybuffernd_Yindices.diminfo[0].strides = __pyx_pybuffernd_Yindices.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_Yindices.diminfo[0].shape = __pyx_pybuffernd_Yindices.rcbuffer->pybuffer.shape[0];
    }
  }
  __pyx_t_14 = 0;
  __pyx_v_Yindices = ((PyArrayObject *)__pyx_t_1);
  __pyx_t_1 = 0;
+062:     cdef np.ndarray[double, ndim=1, mode = 'c'] Ydata = Y.data
  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_Y, __pyx_n_s_data); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 62; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  __Pyx_GOTREF(__pyx_t_1);
  if (!(likely(((__pyx_t_1) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_1, __pyx_ptype_5numpy_ndarray))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 62; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  __pyx_t_15 = ((PyArrayObject *)__pyx_t_1);
  {
    __Pyx_BufFmt_StackElem __pyx_stack[1];
    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_Ydata.rcbuffer->pybuffer, (PyObject*)__pyx_t_15, &__Pyx_TypeInfo_double, PyBUF_FORMAT| PyBUF_C_CONTIGUOUS, 1, 0, __pyx_stack) == -1)) {
      __pyx_v_Ydata = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_pybuffernd_Ydata.rcbuffer->pybuffer.buf = NULL;
      {__pyx_filename = __pyx_f[0]; __pyx_lineno = 62; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
    } else {__pyx_pybuffernd_Ydata.diminfo[0].strides = __pyx_pybuffernd_Ydata.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_Ydata.diminfo[0].shape = __pyx_pybuffernd_Ydata.rcbuffer->pybuffer.shape[0];
    }
  }
  __pyx_t_15 = 0;
  __pyx_v_Ydata = ((PyArrayObject *)__pyx_t_1);
  __pyx_t_1 = 0;
 063: 
+064:     csY.nzmax = Y.data.shape[0]
  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_Y, __pyx_n_s_data); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 64; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_shape); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 64; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  __Pyx_GOTREF(__pyx_t_3);
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_t_1 = __Pyx_GetItemInt(__pyx_t_3, 0, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(__pyx_t_1 == NULL)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 64; __pyx_clineno = __LINE__; goto __pyx_L1_error;};
  __Pyx_GOTREF(__pyx_t_1);
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  __pyx_t_8 = __Pyx_PyInt_As_int(__pyx_t_1); if (unlikely((__pyx_t_8 == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 64; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_v_csY.nzmax = __pyx_t_8;
+065:     csY.m = Y.shape[0]
  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_Y, __pyx_n_s_shape); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 65; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_3 = __Pyx_GetItemInt(__pyx_t_1, 0, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(__pyx_t_3 == NULL)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 65; __pyx_clineno = __LINE__; goto __pyx_L1_error;};
  __Pyx_GOTREF(__pyx_t_3);
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_t_8 = __Pyx_PyInt_As_int(__pyx_t_3); if (unlikely((__pyx_t_8 == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 65; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  __pyx_v_csY.m = __pyx_t_8;
+066:     csY.n = Y.shape[1]
  __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_v_Y, __pyx_n_s_shape); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 66; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  __Pyx_GOTREF(__pyx_t_3);
  __pyx_t_1 = __Pyx_GetItemInt(__pyx_t_3, 1, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(__pyx_t_1 == NULL)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 66; __pyx_clineno = __LINE__; goto __pyx_L1_error;};
  __Pyx_GOTREF(__pyx_t_1);
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  __pyx_t_8 = __Pyx_PyInt_As_int(__pyx_t_1); if (unlikely((__pyx_t_8 == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 66; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_v_csY.n = __pyx_t_8;
+067:     csY.p = &Yindptr[0]
  __pyx_t_16 = 0;
  __pyx_t_10 = -1;
  if (__pyx_t_16 < 0) {
    __pyx_t_16 += __pyx_pybuffernd_Yindptr.diminfo[0].shape;
    if (unlikely(__pyx_t_16 < 0)) __pyx_t_10 = 0;
  } else if (unlikely(__pyx_t_16 >= __pyx_pybuffernd_Yindptr.diminfo[0].shape)) __pyx_t_10 = 0;
  if (unlikely(__pyx_t_10 != -1)) {
    __Pyx_RaiseBufferIndexError(__pyx_t_10);
    {__pyx_filename = __pyx_f[0]; __pyx_lineno = 67; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  }
  __pyx_v_csY.p = (&(*__Pyx_BufPtrCContig1d(__pyx_t_7psparse_csi *, __pyx_pybuffernd_Yindptr.rcbuffer->pybuffer.buf, __pyx_t_16, __pyx_pybuffernd_Yindptr.diminfo[0].strides)));
+068:     csY.i = &Yindices[0]
  __pyx_t_17 = 0;
  __pyx_t_10 = -1;
  if (__pyx_t_17 < 0) {
    __pyx_t_17 += __pyx_pybuffernd_Yindices.diminfo[0].shape;
    if (unlikely(__pyx_t_17 < 0)) __pyx_t_10 = 0;
  } else if (unlikely(__pyx_t_17 >= __pyx_pybuffernd_Yindices.diminfo[0].shape)) __pyx_t_10 = 0;
  if (unlikely(__pyx_t_10 != -1)) {
    __Pyx_RaiseBufferIndexError(__pyx_t_10);
    {__pyx_filename = __pyx_f[0]; __pyx_lineno = 68; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  }
  __pyx_v_csY.i = (&(*__Pyx_BufPtrCContig1d(__pyx_t_7psparse_csi *, __pyx_pybuffernd_Yindices.rcbuffer->pybuffer.buf, __pyx_t_17, __pyx_pybuffernd_Yindices.diminfo[0].strides)));
+069:     csY.x = &Ydata[0]
  __pyx_t_18 = 0;
  __pyx_t_10 = -1;
  if (__pyx_t_18 < 0) {
    __pyx_t_18 += __pyx_pybuffernd_Ydata.diminfo[0].shape;
    if (unlikely(__pyx_t_18 < 0)) __pyx_t_10 = 0;
  } else if (unlikely(__pyx_t_18 >= __pyx_pybuffernd_Ydata.diminfo[0].shape)) __pyx_t_10 = 0;
  if (unlikely(__pyx_t_10 != -1)) {
    __Pyx_RaiseBufferIndexError(__pyx_t_10);
    {__pyx_filename = __pyx_f[0]; __pyx_lineno = 69; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  }
  __pyx_v_csY.x = (&(*__Pyx_BufPtrCContig1d(double *, __pyx_pybuffernd_Ydata.rcbuffer->pybuffer.buf, __pyx_t_18, __pyx_pybuffernd_Ydata.diminfo[0].strides)));
+070:     csY.nz = -1  # to indicate CSC format
  __pyx_v_csY.nz = -1;
 071: 
+072:     res = cs_multiply(&csX, &csY)
  __pyx_v_res = cs_multiply((&__pyx_v_csX), (&__pyx_v_csY));
+073:     return res
  __Pyx_XDECREF(__pyx_r);
  __pyx_t_1 = __Pyx_PyInt_From_int(__pyx_v_res); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 73; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_r = __pyx_t_1;
  __pyx_t_1 = 0;
  goto __pyx_L0;
 074: 
 075: @cython.boundscheck(False)
+076: def pmultiply(X not None, np.ndarray[ndim=2, mode='fortran', dtype=np.float64_t] W not None):
/* Python wrapper */
static PyObject *__pyx_pw_7psparse_3pmultiply(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
static char __pyx_doc_7psparse_2pmultiply[] = "Multiply a sparse CSC matrix by a dense matrix\n\n    Parameters\n    ----------\n    X : scipy.sparse.csc_matrix\n        A sparse matrix, of size N x M\n    W : np.ndarray[dtype=float564, ndim=2, mode='fortran']\n        A dense matrix, of size M x P. Note, W must be contiguous and in\n        fortran (column-major) order. You can ensure this using\n        numpy's `asfortranarray` function.\n\n    Returns\n    -------\n    A : np.ndarray[dtype=float64, ndim=2, mode='fortran']\n        A dense matrix, of size N x P, the result of multiplying X by W.\n\n    Notes\n    -----\n    This function is parallelized over the columns of W using OpenMP. You\n    can control the number of threads at runtime using the OMP_NUM_THREADS\n    environment variable. The internal sparse matrix code is from CSPARSE, \n    a Concise Sparse matrix package. Copyright (c) 2006, Timothy A. Davis.\n    http://www.cise.ufl.edu/research/sparse/CSparse, licensed under the\n    GNU LGPL v2.1+.\n\n    References\n    ----------\n    .. [1] Davis, Timothy A., \"Direct Methods for Sparse Linear Systems\n    (Fundamentals of Algorithms 2),\" SIAM Press, 2006. ISBN: 0898716136\n    ";
static PyMethodDef __pyx_mdef_7psparse_3pmultiply = {"pmultiply", (PyCFunction)__pyx_pw_7psparse_3pmultiply, METH_VARARGS|METH_KEYWORDS, __pyx_doc_7psparse_2pmultiply};
static PyObject *__pyx_pw_7psparse_3pmultiply(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
  PyObject *__pyx_v_X = 0;
  PyArrayObject *__pyx_v_W = 0;
  PyObject *__pyx_r = 0;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("pmultiply (wrapper)", 0);
  {
    static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_X,&__pyx_n_s_W,0};
    PyObject* values[2] = {0,0};
    if (unlikely(__pyx_kwds)) {
      Py_ssize_t kw_args;
      const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args);
      switch (pos_args) {
        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
        case  0: break;
        default: goto __pyx_L5_argtuple_error;
      }
      kw_args = PyDict_Size(__pyx_kwds);
      switch (pos_args) {
        case  0:
        if (likely((values[0] = PyDict_GetItem(__pyx_kwds, __pyx_n_s_X)) != 0)) kw_args--;
        else goto __pyx_L5_argtuple_error;
        case  1:
        if (likely((values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s_W)) != 0)) kw_args--;
        else {
          __Pyx_RaiseArgtupleInvalid("pmultiply", 1, 2, 2, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 76; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
        }
      }
      if (unlikely(kw_args > 0)) {
        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "pmultiply") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 76; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
      }
    } else if (PyTuple_GET_SIZE(__pyx_args) != 2) {
      goto __pyx_L5_argtuple_error;
    } else {
      values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
      values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
    }
    __pyx_v_X = values[0];
    __pyx_v_W = ((PyArrayObject *)values[1]);
  }
  goto __pyx_L4_argument_unpacking_done;
  __pyx_L5_argtuple_error:;
  __Pyx_RaiseArgtupleInvalid("pmultiply", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 76; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
  __pyx_L3_error:;
  __Pyx_AddTraceback("psparse.pmultiply", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __Pyx_RefNannyFinishContext();
  return NULL;
  __pyx_L4_argument_unpacking_done:;
  if (unlikely(((PyObject *)__pyx_v_X) == Py_None)) {
    PyErr_Format(PyExc_TypeError, "Argument '%.200s' must not be None", "X"); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 76; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  }
  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_W), __pyx_ptype_5numpy_ndarray, 0, "W", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 76; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  __pyx_r = __pyx_pf_7psparse_2pmultiply(__pyx_self, __pyx_v_X, __pyx_v_W);
  int __pyx_lineno = 0;
  const char *__pyx_filename = NULL;
  int __pyx_clineno = 0;

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

static PyObject *__pyx_pf_7psparse_2pmultiply(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_X, PyArrayObject *__pyx_v_W) {
  int __pyx_v_i;
  __pyx_t_7psparse_cs __pyx_v_csX;
  PyArrayObject *__pyx_v_result = 0;
  PyArrayObject *__pyx_v_indptr = 0;
  PyArrayObject *__pyx_v_indices = 0;
  PyArrayObject *__pyx_v_data = 0;
  __Pyx_LocalBuf_ND __pyx_pybuffernd_W;
  __Pyx_Buffer __pyx_pybuffer_W;
  __Pyx_LocalBuf_ND __pyx_pybuffernd_data;
  __Pyx_Buffer __pyx_pybuffer_data;
  __Pyx_LocalBuf_ND __pyx_pybuffernd_indices;
  __Pyx_Buffer __pyx_pybuffer_indices;
  __Pyx_LocalBuf_ND __pyx_pybuffernd_indptr;
  __Pyx_Buffer __pyx_pybuffer_indptr;
  __Pyx_LocalBuf_ND __pyx_pybuffernd_result;
  __Pyx_Buffer __pyx_pybuffer_result;
  PyObject *__pyx_r = NULL;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("pmultiply", 0);
  __pyx_pybuffer_result.pybuffer.buf = NULL;
  __pyx_pybuffer_result.refcount = 0;
  __pyx_pybuffernd_result.data = NULL;
  __pyx_pybuffernd_result.rcbuffer = &__pyx_pybuffer_result;
  __pyx_pybuffer_indptr.pybuffer.buf = NULL;
  __pyx_pybuffer_indptr.refcount = 0;
  __pyx_pybuffernd_indptr.data = NULL;
  __pyx_pybuffernd_indptr.rcbuffer = &__pyx_pybuffer_indptr;
  __pyx_pybuffer_indices.pybuffer.buf = NULL;
  __pyx_pybuffer_indices.refcount = 0;
  __pyx_pybuffernd_indices.data = NULL;
  __pyx_pybuffernd_indices.rcbuffer = &__pyx_pybuffer_indices;
  __pyx_pybuffer_data.pybuffer.buf = NULL;
  __pyx_pybuffer_data.refcount = 0;
  __pyx_pybuffernd_data.data = NULL;
  __pyx_pybuffernd_data.rcbuffer = &__pyx_pybuffer_data;
  __pyx_pybuffer_W.pybuffer.buf = NULL;
  __pyx_pybuffer_W.refcount = 0;
  __pyx_pybuffernd_W.data = NULL;
  __pyx_pybuffernd_W.rcbuffer = &__pyx_pybuffer_W;
  {
    __Pyx_BufFmt_StackElem __pyx_stack[1];
    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_W.rcbuffer->pybuffer, (PyObject*)__pyx_v_W, &__Pyx_TypeInfo_nn___pyx_t_5numpy_float64_t, PyBUF_FORMAT| PyBUF_F_CONTIGUOUS, 2, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 76; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  }
  __pyx_pybuffernd_W.diminfo[0].strides = __pyx_pybuffernd_W.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_W.diminfo[0].shape = __pyx_pybuffernd_W.rcbuffer->pybuffer.shape[0]; __pyx_pybuffernd_W.diminfo[1].strides = __pyx_pybuffernd_W.rcbuffer->pybuffer.strides[1]; __pyx_pybuffernd_W.diminfo[1].shape = __pyx_pybuffernd_W.rcbuffer->pybuffer.shape[1];
/* … */
  /* 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_12);
  __Pyx_XDECREF(__pyx_t_13);
  { PyObject *__pyx_type, *__pyx_value, *__pyx_tb;
    __Pyx_ErrFetch(&__pyx_type, &__pyx_value, &__pyx_tb);
    __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_W.rcbuffer->pybuffer);
    __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_data.rcbuffer->pybuffer);
    __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_indices.rcbuffer->pybuffer);
    __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_indptr.rcbuffer->pybuffer);
    __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_result.rcbuffer->pybuffer);
  __Pyx_ErrRestore(__pyx_type, __pyx_value, __pyx_tb);}
  __Pyx_AddTraceback("psparse.pmultiply", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __pyx_r = NULL;
  goto __pyx_L2;
  __pyx_L0:;
  __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_W.rcbuffer->pybuffer);
  __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_data.rcbuffer->pybuffer);
  __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_indices.rcbuffer->pybuffer);
  __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_indptr.rcbuffer->pybuffer);
  __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_result.rcbuffer->pybuffer);
  __pyx_L2:;
  __Pyx_XDECREF((PyObject *)__pyx_v_result);
  __Pyx_XDECREF((PyObject *)__pyx_v_indptr);
  __Pyx_XDECREF((PyObject *)__pyx_v_indices);
  __Pyx_XDECREF((PyObject *)__pyx_v_data);
  __Pyx_XGIVEREF(__pyx_r);
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}
/* … */
  __pyx_tuple__11 = PyTuple_Pack(8, __pyx_n_s_X, __pyx_n_s_W, __pyx_n_s_i, __pyx_n_s_csX, __pyx_n_s_result, __pyx_n_s_indptr, __pyx_n_s_indices, __pyx_n_s_data); if (unlikely(!__pyx_tuple__11)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 76; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  __Pyx_GOTREF(__pyx_tuple__11);
  __Pyx_GIVEREF(__pyx_tuple__11);
/* … */
  __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_7psparse_3pmultiply, NULL, __pyx_n_s_psparse); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 76; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  __Pyx_GOTREF(__pyx_t_1);
  if (PyDict_SetItem(__pyx_d, __pyx_n_s_pmultiply, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 76; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 077:     """Multiply a sparse CSC matrix by a dense matrix
 078: 
 079:     Parameters
 080:     ----------
 081:     X : scipy.sparse.csc_matrix
 082:         A sparse matrix, of size N x M
 083:     W : np.ndarray[dtype=float564, ndim=2, mode='fortran']
 084:         A dense matrix, of size M x P. Note, W must be contiguous and in
 085:         fortran (column-major) order. You can ensure this using
 086:         numpy's `asfortranarray` function.
 087: 
 088:     Returns
 089:     -------
 090:     A : np.ndarray[dtype=float64, ndim=2, mode='fortran']
 091:         A dense matrix, of size N x P, the result of multiplying X by W.
 092: 
 093:     Notes
 094:     -----
 095:     This function is parallelized over the columns of W using OpenMP. You
 096:     can control the number of threads at runtime using the OMP_NUM_THREADS
 097:     environment variable. The internal sparse matrix code is from CSPARSE, 
 098:     a Concise Sparse matrix package. Copyright (c) 2006, Timothy A. Davis.
 099:     http://www.cise.ufl.edu/research/sparse/CSparse, licensed under the
 100:     GNU LGPL v2.1+.
 101: 
 102:     References
 103:     ----------
 104:     .. [1] Davis, Timothy A., "Direct Methods for Sparse Linear Systems
 105:     (Fundamentals of Algorithms 2)," SIAM Press, 2006. ISBN: 0898716136
 106:     """
+107:     if X.shape[1] != W.shape[0]:
  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_X, __pyx_n_s_shape); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 107; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_2 = __Pyx_GetItemInt(__pyx_t_1, 1, long, 1, __Pyx_PyInt_From_long, 0, 0, 0); if (unlikely(__pyx_t_2 == NULL)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 107; __pyx_clineno = __LINE__; goto __pyx_L1_error;};
  __Pyx_GOTREF(__pyx_t_2);
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_t_1 = __Pyx_PyInt_From_Py_intptr_t((__pyx_v_W->dimensions[0])); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 107; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_3 = PyObject_RichCompare(__pyx_t_2, __pyx_t_1, Py_NE); __Pyx_XGOTREF(__pyx_t_3); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 107; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_t_4 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_4 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 107; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  if (__pyx_t_4) {
+108:         raise ValueError('matrices are not aligned')
    __pyx_t_3 = __Pyx_PyObject_Call(__pyx_builtin_ValueError, __pyx_tuple__2, NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 108; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
    __Pyx_GOTREF(__pyx_t_3);
    __Pyx_Raise(__pyx_t_3, 0, 0, 0);
    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
    {__pyx_filename = __pyx_f[0]; __pyx_lineno = 108; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  }
/* … */
  __pyx_tuple__2 = PyTuple_Pack(1, __pyx_kp_s_matrices_are_not_aligned); if (unlikely(!__pyx_tuple__2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 108; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  __Pyx_GOTREF(__pyx_tuple__2);
  __Pyx_GIVEREF(__pyx_tuple__2);
 109: 
 110:     cdef int i
 111:     cdef cs csX
 112:     cdef np.ndarray[double, ndim=2, mode='fortran'] result
+113:     cdef np.ndarray[csi, ndim=1, mode = 'c'] indptr  = X.indptr
  __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_v_X, __pyx_n_s_indptr); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 113; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  __Pyx_GOTREF(__pyx_t_3);
  if (!(likely(((__pyx_t_3) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_3, __pyx_ptype_5numpy_ndarray))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 113; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  __pyx_t_5 = ((PyArrayObject *)__pyx_t_3);
  {
    __Pyx_BufFmt_StackElem __pyx_stack[1];
    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_indptr.rcbuffer->pybuffer, (PyObject*)__pyx_t_5, &__Pyx_TypeInfo_nn___pyx_t_7psparse_csi, PyBUF_FORMAT| PyBUF_C_CONTIGUOUS, 1, 0, __pyx_stack) == -1)) {
      __pyx_v_indptr = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_pybuffernd_indptr.rcbuffer->pybuffer.buf = NULL;
      {__pyx_filename = __pyx_f[0]; __pyx_lineno = 113; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
    } else {__pyx_pybuffernd_indptr.diminfo[0].strides = __pyx_pybuffernd_indptr.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_indptr.diminfo[0].shape = __pyx_pybuffernd_indptr.rcbuffer->pybuffer.shape[0];
    }
  }
  __pyx_t_5 = 0;
  __pyx_v_indptr = ((PyArrayObject *)__pyx_t_3);
  __pyx_t_3 = 0;
+114:     cdef np.ndarray[csi, ndim=1, mode = 'c'] indices = X.indices
  __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_v_X, __pyx_n_s_indices); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 114; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  __Pyx_GOTREF(__pyx_t_3);
  if (!(likely(((__pyx_t_3) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_3, __pyx_ptype_5numpy_ndarray))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 114; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  __pyx_t_6 = ((PyArrayObject *)__pyx_t_3);
  {
    __Pyx_BufFmt_StackElem __pyx_stack[1];
    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_indices.rcbuffer->pybuffer, (PyObject*)__pyx_t_6, &__Pyx_TypeInfo_nn___pyx_t_7psparse_csi, PyBUF_FORMAT| PyBUF_C_CONTIGUOUS, 1, 0, __pyx_stack) == -1)) {
      __pyx_v_indices = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_pybuffernd_indices.rcbuffer->pybuffer.buf = NULL;
      {__pyx_filename = __pyx_f[0]; __pyx_lineno = 114; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
    } else {__pyx_pybuffernd_indices.diminfo[0].strides = __pyx_pybuffernd_indices.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_indices.diminfo[0].shape = __pyx_pybuffernd_indices.rcbuffer->pybuffer.shape[0];
    }
  }
  __pyx_t_6 = 0;
  __pyx_v_indices = ((PyArrayObject *)__pyx_t_3);
  __pyx_t_3 = 0;
+115:     cdef np.ndarray[double, ndim=1, mode = 'c']    data = X.data
  __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_v_X, __pyx_n_s_data); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 115; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  __Pyx_GOTREF(__pyx_t_3);
  if (!(likely(((__pyx_t_3) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_3, __pyx_ptype_5numpy_ndarray))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 115; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  __pyx_t_7 = ((PyArrayObject *)__pyx_t_3);
  {
    __Pyx_BufFmt_StackElem __pyx_stack[1];
    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_data.rcbuffer->pybuffer, (PyObject*)__pyx_t_7, &__Pyx_TypeInfo_double, PyBUF_FORMAT| PyBUF_C_CONTIGUOUS, 1, 0, __pyx_stack) == -1)) {
      __pyx_v_data = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_pybuffernd_data.rcbuffer->pybuffer.buf = NULL;
      {__pyx_filename = __pyx_f[0]; __pyx_lineno = 115; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
    } else {__pyx_pybuffernd_data.diminfo[0].strides = __pyx_pybuffernd_data.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_data.diminfo[0].shape = __pyx_pybuffernd_data.rcbuffer->pybuffer.shape[0];
    }
  }
  __pyx_t_7 = 0;
  __pyx_v_data = ((PyArrayObject *)__pyx_t_3);
  __pyx_t_3 = 0;
 116: 
 117:     # Pack the scipy data into the CSparse struct. This is just copying some
 118:     # pointers.
+119:     csX.nzmax = X.data.shape[0]
  __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_v_X, __pyx_n_s_data); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 119; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  __Pyx_GOTREF(__pyx_t_3);
  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_n_s_shape); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 119; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  __Pyx_GOTREF(__pyx_t_1);
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  __pyx_t_3 = __Pyx_GetItemInt(__pyx_t_1, 0, long, 1, __Pyx_PyInt_From_long, 0, 0, 0); if (unlikely(__pyx_t_3 == NULL)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 119; __pyx_clineno = __LINE__; goto __pyx_L1_error;};
  __Pyx_GOTREF(__pyx_t_3);
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_t_8 = __Pyx_PyInt_As_int(__pyx_t_3); if (unlikely((__pyx_t_8 == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 119; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  __pyx_v_csX.nzmax = __pyx_t_8;
+120:     csX.m = X.shape[0]
  __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_v_X, __pyx_n_s_shape); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 120; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  __Pyx_GOTREF(__pyx_t_3);
  __pyx_t_1 = __Pyx_GetItemInt(__pyx_t_3, 0, long, 1, __Pyx_PyInt_From_long, 0, 0, 0); if (unlikely(__pyx_t_1 == NULL)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 120; __pyx_clineno = __LINE__; goto __pyx_L1_error;};
  __Pyx_GOTREF(__pyx_t_1);
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  __pyx_t_8 = __Pyx_PyInt_As_int(__pyx_t_1); if (unlikely((__pyx_t_8 == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 120; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_v_csX.m = __pyx_t_8;
+121:     csX.n = X.shape[1]
  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_X, __pyx_n_s_shape); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 121; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_3 = __Pyx_GetItemInt(__pyx_t_1, 1, long, 1, __Pyx_PyInt_From_long, 0, 0, 0); if (unlikely(__pyx_t_3 == NULL)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 121; __pyx_clineno = __LINE__; goto __pyx_L1_error;};
  __Pyx_GOTREF(__pyx_t_3);
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_t_8 = __Pyx_PyInt_As_int(__pyx_t_3); if (unlikely((__pyx_t_8 == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 121; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  __pyx_v_csX.n = __pyx_t_8;
+122:     csX.p = &indptr[0]
  __pyx_t_9 = 0;
  if (__pyx_t_9 < 0) __pyx_t_9 += __pyx_pybuffernd_indptr.diminfo[0].shape;
  __pyx_v_csX.p = (&(*__Pyx_BufPtrCContig1d(__pyx_t_7psparse_csi *, __pyx_pybuffernd_indptr.rcbuffer->pybuffer.buf, __pyx_t_9, __pyx_pybuffernd_indptr.diminfo[0].strides)));
+123:     csX.i = &indices[0]
  __pyx_t_10 = 0;
  if (__pyx_t_10 < 0) __pyx_t_10 += __pyx_pybuffernd_indices.diminfo[0].shape;
  __pyx_v_csX.i = (&(*__Pyx_BufPtrCContig1d(__pyx_t_7psparse_csi *, __pyx_pybuffernd_indices.rcbuffer->pybuffer.buf, __pyx_t_10, __pyx_pybuffernd_indices.diminfo[0].strides)));
+124:     csX.x = &data[0]
  __pyx_t_11 = 0;
  if (__pyx_t_11 < 0) __pyx_t_11 += __pyx_pybuffernd_data.diminfo[0].shape;
  __pyx_v_csX.x = (&(*__Pyx_BufPtrCContig1d(double *, __pyx_pybuffernd_data.rcbuffer->pybuffer.buf, __pyx_t_11, __pyx_pybuffernd_data.diminfo[0].strides)));
+125:     csX.nz = -1  # to indicate CSC format
  __pyx_v_csX.nz = -1;
 126: 
+127:     result = np.zeros((X.shape[0], W.shape[1]), order='F', dtype=np.double)
  __pyx_t_3 = __Pyx_GetModuleGlobalName(__pyx_n_s_np); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 127; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  __Pyx_GOTREF(__pyx_t_3);
  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_n_s_zeros); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 127; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  __Pyx_GOTREF(__pyx_t_1);
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_v_X, __pyx_n_s_shape); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 127; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  __Pyx_GOTREF(__pyx_t_3);
  __pyx_t_2 = __Pyx_GetItemInt(__pyx_t_3, 0, long, 1, __Pyx_PyInt_From_long, 0, 0, 0); if (unlikely(__pyx_t_2 == NULL)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 127; __pyx_clineno = __LINE__; goto __pyx_L1_error;};
  __Pyx_GOTREF(__pyx_t_2);
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  __pyx_t_3 = __Pyx_PyInt_From_Py_intptr_t((__pyx_v_W->dimensions[1])); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 127; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  __Pyx_GOTREF(__pyx_t_3);
  __pyx_t_12 = PyTuple_New(2); if (unlikely(!__pyx_t_12)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 127; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  __Pyx_GOTREF(__pyx_t_12);
  PyTuple_SET_ITEM(__pyx_t_12, 0, __pyx_t_2);
  __Pyx_GIVEREF(__pyx_t_2);
  PyTuple_SET_ITEM(__pyx_t_12, 1, __pyx_t_3);
  __Pyx_GIVEREF(__pyx_t_3);
  __pyx_t_2 = 0;
  __pyx_t_3 = 0;
  __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 127; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  __Pyx_GOTREF(__pyx_t_3);
  PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_12);
  __Pyx_GIVEREF(__pyx_t_12);
  __pyx_t_12 = 0;
  __pyx_t_12 = PyDict_New(); if (unlikely(!__pyx_t_12)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 127; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  __Pyx_GOTREF(__pyx_t_12);
  if (PyDict_SetItem(__pyx_t_12, __pyx_n_s_order, __pyx_n_s_F) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 127; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  __pyx_t_2 = __Pyx_GetModuleGlobalName(__pyx_n_s_np); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 127; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  __Pyx_GOTREF(__pyx_t_2);
  __pyx_t_13 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_double); if (unlikely(!__pyx_t_13)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 127; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  __Pyx_GOTREF(__pyx_t_13);
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  if (PyDict_SetItem(__pyx_t_12, __pyx_n_s_dtype, __pyx_t_13) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 127; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  __Pyx_DECREF(__pyx_t_13); __pyx_t_13 = 0;
  __pyx_t_13 = __Pyx_PyObject_Call(__pyx_t_1, __pyx_t_3, __pyx_t_12); if (unlikely(!__pyx_t_13)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 127; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  __Pyx_GOTREF(__pyx_t_13);
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  __Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;
  if (!(likely(((__pyx_t_13) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_13, __pyx_ptype_5numpy_ndarray))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 127; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  __pyx_t_14 = ((PyArrayObject *)__pyx_t_13);
  {
    __Pyx_BufFmt_StackElem __pyx_stack[1];
    __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_result.rcbuffer->pybuffer);
    __pyx_t_15 = __Pyx_GetBufferAndValidate(&__pyx_pybuffernd_result.rcbuffer->pybuffer, (PyObject*)__pyx_t_14, &__Pyx_TypeInfo_double, PyBUF_FORMAT| PyBUF_F_CONTIGUOUS, 2, 0, __pyx_stack);
    if (unlikely(__pyx_t_15 < 0)) {
      PyErr_Fetch(&__pyx_t_16, &__pyx_t_17, &__pyx_t_18);
      if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_result.rcbuffer->pybuffer, (PyObject*)__pyx_v_result, &__Pyx_TypeInfo_double, PyBUF_FORMAT| PyBUF_F_CONTIGUOUS, 2, 0, __pyx_stack) == -1)) {
        Py_XDECREF(__pyx_t_16); Py_XDECREF(__pyx_t_17); Py_XDECREF(__pyx_t_18);
        __Pyx_RaiseBufferFallbackError();
      } else {
        PyErr_Restore(__pyx_t_16, __pyx_t_17, __pyx_t_18);
      }
    }
    __pyx_pybuffernd_result.diminfo[0].strides = __pyx_pybuffernd_result.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_result.diminfo[0].shape = __pyx_pybuffernd_result.rcbuffer->pybuffer.shape[0]; __pyx_pybuffernd_result.diminfo[1].strides = __pyx_pybuffernd_result.rcbuffer->pybuffer.strides[1]; __pyx_pybuffernd_result.diminfo[1].shape = __pyx_pybuffernd_result.rcbuffer->pybuffer.shape[1];
    if (unlikely(__pyx_t_15 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 127; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  }
  __pyx_t_14 = 0;
  __pyx_v_result = ((PyArrayObject *)__pyx_t_13);
  __pyx_t_13 = 0;
+128:     for i in prange(W.shape[1], nogil=True):
  {
      #ifdef WITH_THREAD
      PyThreadState *_save;
      Py_UNBLOCK_THREADS
      #endif
      /*try:*/ {
        __pyx_t_19 = (__pyx_v_W->dimensions[1]);
        if (1 == 0) abort();
        {
            #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_21 = (__pyx_t_19 - 0) / 1;
            if (__pyx_t_21 > 0)
            {
                #ifdef _OPENMP
                #pragma omp parallel
                #endif /* _OPENMP */
                {
                    #ifdef _OPENMP
                    #pragma omp for firstprivate(__pyx_v_i) lastprivate(__pyx_v_i)
                    #endif /* _OPENMP */
                    for (__pyx_t_20 = 0; __pyx_t_20 < __pyx_t_21; __pyx_t_20++){
                        {
                            __pyx_v_i = 0 + 1 * __pyx_t_20;
/* … */
      /*finally:*/ {
        /*normal exit:*/{
          #ifdef WITH_THREAD
          Py_BLOCK_THREADS
          #endif
          goto __pyx_L6;
        }
        __pyx_L6:;
      }
  }
 129:         # X is in fortran format, so we can get quick access to each of its
 130:         # columns
+131:         cs_gaxpy(&csX, &W[0, i], &result[0, i])
                            __pyx_t_22 = 0;
                            __pyx_t_15 = __pyx_v_i;
                            if (__pyx_t_22 < 0) __pyx_t_22 += __pyx_pybuffernd_W.diminfo[0].shape;
                            if (__pyx_t_15 < 0) __pyx_t_15 += __pyx_pybuffernd_W.diminfo[1].shape;
                            __pyx_t_23 = 0;
                            __pyx_t_24 = __pyx_v_i;
                            if (__pyx_t_23 < 0) __pyx_t_23 += __pyx_pybuffernd_result.diminfo[0].shape;
                            if (__pyx_t_24 < 0) __pyx_t_24 += __pyx_pybuffernd_result.diminfo[1].shape;
                            cs_gaxpy((&__pyx_v_csX), (&(*__Pyx_BufPtrFortranContig2d(__pyx_t_5numpy_float64_t *, __pyx_pybuffernd_W.rcbuffer->pybuffer.buf, __pyx_t_22, __pyx_pybuffernd_W.diminfo[0].strides, __pyx_t_15, __pyx_pybuffernd_W.diminfo[1].strides))), (&(*__Pyx_BufPtrFortranContig2d(double *, __pyx_pybuffernd_result.rcbuffer->pybuffer.buf, __pyx_t_23, __pyx_pybuffernd_result.diminfo[0].strides, __pyx_t_24, __pyx_pybuffernd_result.diminfo[1].strides))));
                        }
                    }
                }
            }
        }
        #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
      }
 132: 
+133:     return result
  __Pyx_XDECREF(__pyx_r);
  __Pyx_INCREF(((PyObject *)__pyx_v_result));
  __pyx_r = ((PyObject *)__pyx_v_result);
  goto __pyx_L0;