 #include <cuda_runtime.h>
 #include <cusparse_v2.h>
 
-typedef cusparseStatus_t (*crskernel_t) (cusparseHandle_t handle, cusparseOperation_t transA, 
+typedef cusparseStatus_t (*cusparse_crs_spmv_kernel_t) (cusparseHandle_t handle, cusparseOperation_t transA, 
         int m, int n, int nnz, const void           *alpha, 
         const cusparseMatDescr_t descrA, 
         const void           *csrValA, 

        zero<dt1>(beta);
    }
    
    ghost_densemat_t *lhscompact, *rhscompact;
    void *lhsval, *rhsval;
    
    if (lhs->traits.flags & GHOST_DENSEMAT_SCATTERED) {
        INFO_LOG("Cloning (and compressing) lhs before operation");
        GHOST_CALL_RETURN(lhs->clone(lhs,&lhscompact,lhs->traits.nrows,0,lhs->traits.ncols,0));
    } else {
        lhscompact = lhs;
    }
    if (rhs->traits.flags & GHOST_DENSEMAT_SCATTERED) {
        INFO_LOG("Cloning (and compressing) v2 before operation");
        GHOST_CALL_RETURN(rhs->clone(rhs,&rhscompact,rhs->traits.nrows,0,rhs->traits.ncols,0));
    } else {
        rhscompact = rhs;
    }
    GHOST_CALL_RETURN(ghost_densemat_cu_valptr(lhscompact,&lhsval));
    GHOST_CALL_RETURN(ghost_densemat_cu_valptr(rhscompact,&rhsval));


    if (localdot || shift) {
        WARNING_LOG("Localdot or shift are not NULL, something went wrong!");
    } 

    crskernel(cusparse_handle,CUSPARSE_OPERATION_NON_TRANSPOSE,mat->nrows,mat->ncols,mat->nnz,&scale,descr,(dt1 *)CR(mat)->cumat->val, CR(mat)->cumat->rpt, CR(mat)->cumat->col, (dt1 *)rhsval, &beta, (dt1 *)lhsval);

    if (lhscompact != lhs) {
        GHOST_CALL_RETURN(lhs->fromVec(lhs,lhscompact,0,0));
        lhscompact->destroy(lhscompact);

        rhscompact->destroy(rhscompact);
    }

    return ret;


    /*cusparseHandle_t cusparse_handle;
