# Buggy code
def kron(A, B, format=None):
    """kronecker product of sparse matrices A and B

    Parameters
    ----------
    A : sparse or dense matrix
        first matrix of the product
    B : sparse or dense matrix
        second matrix of the product
    format : str, optional
        format of the result (e.g. "csr")

    Returns
    -------
    kronecker product in a sparse matrix format


    Examples
    --------
    >>> from scipy import sparse
    >>> A = sparse.csr_matrix(np.array([[0, 2], [5, 0]]))
    >>> B = sparse.csr_matrix(np.array([[1, 2], [3, 4]]))
    >>> sparse.kron(A, B).toarray()
    array([[ 0,  0,  2,  4],
           [ 0,  0,  6,  8],
           [ 5, 10,  0,  0],
           [15, 20,  0,  0]])

    >>> sparse.kron(A, [[1, 2], [3, 4]]).toarray()
    array([[ 0,  0,  2,  4],
           [ 0,  0,  6,  8],
           [ 5, 10,  0,  0],
           [15, 20,  0,  0]])

    """
    B = coo_matrix(B)

    if (format is None or format == "bsr") and 2 * B.nnz >= B.shape[0] * B.shape[1]:
        # B is fairly dense, use BSR
        A = csr_matrix(A, copy=True)

        output_shape = (A.shape[0] * B.shape[0], A.shape[1] * B.shape[1])

        if A.nnz == 0 or B.nnz == 0:
            # kronecker product is the zero matrix
            return coo_matrix(output_shape)

        B = B.toarray()
        data = A.data.repeat(B.size).reshape(-1, B.shape[0], B.shape[1])
        data = data * B

        return bsr_matrix((data, A.indices, A.indptr), shape=output_shape)
    else:
        # use COO
        A = coo_matrix(A)
        output_shape = (A.shape[0] * B.shape[0], A.shape[1] * B.shape[1])

        if A.nnz == 0 or B.nnz == 0:
            # kronecker product is the zero matrix
            return coo_matrix(output_shape)

        # expand entries of a into blocks
        row = A.row.repeat(B.nnz)
        col = A.col.repeat(B.nnz)
        data = A.data.repeat(B.nnz)

        row *= B.shape[0]
        col *= B.shape[1]

        # increment block indices
        row, col = row.reshape(-1, B.nnz), col.reshape(-1, B.nnz)
        row += B.row
        col += B.col
        row, col = row.reshape(-1), col.reshape(-1)

        # compute block entries
        data = data.reshape(-1, B.nnz) * B.data
        data = data.reshape(-1)

        return coo_matrix((data, (row, col)), shape=output_shape).asformat(format)


# Traceback (ValueError)
Traceback (most recent call last):
File "sparse_test.py", line 12, in <module>
scipy_kron = kron(sparse_A,sparse_B)
File "/Users/weitang/opt/anaconda3/envs/cc-env/lib/python3.7/site-packages/scipy/sparse/construct.py", line 355, in kron
return coo_matrix((data,(row,col)), shape=output_shape).asformat(format)
File "/Users/weitang/opt/anaconda3/envs/cc-env/lib/python3.7/site-packages/scipy/sparse/coo.py", line 198, in __init__
self._check()
File "/Users/weitang/opt/anaconda3/envs/cc-env/lib/python3.7/site-packages/scipy/sparse/coo.py", line 291, in _check
raise ValueError('negative column index found')
ValueError: negative column index found

# Fixed code
def kron(A, B, format=None):
    """kronecker product of sparse matrices A and B

    Parameters
    ----------
    A : sparse or dense matrix
        first matrix of the product
    B : sparse or dense matrix
        second matrix of the product
    format : str, optional
        format of the result (e.g. "csr")

    Returns
    -------
    kronecker product in a sparse matrix format


    Examples
    --------
    >>> from scipy import sparse
    >>> A = sparse.csr_matrix(np.array([[0, 2], [5, 0]]))
    >>> B = sparse.csr_matrix(np.array([[1, 2], [3, 4]]))
    >>> sparse.kron(A, B).toarray()
    array([[ 0,  0,  2,  4],
           [ 0,  0,  6,  8],
           [ 5, 10,  0,  0],
           [15, 20,  0,  0]])

    >>> sparse.kron(A, [[1, 2], [3, 4]]).toarray()
    array([[ 0,  0,  2,  4],
           [ 0,  0,  6,  8],
           [ 5, 10,  0,  0],
           [15, 20,  0,  0]])

    """
    B = coo_matrix(B)

    if (format is None or format == "bsr") and 2 * B.nnz >= B.shape[0] * B.shape[1]:
        # B is fairly dense, use BSR
        A = csr_matrix(A, copy=True)

        output_shape = (A.shape[0] * B.shape[0], A.shape[1] * B.shape[1])

        if A.nnz == 0 or B.nnz == 0:
            # kronecker product is the zero matrix
            return coo_matrix(output_shape)

        B = B.toarray()
        data = A.data.repeat(B.size).reshape(-1, B.shape[0], B.shape[1])
        data = data * B

        return bsr_matrix((data, A.indices, A.indptr), shape=output_shape)
    else:
        # use COO
        A = coo_matrix(A)
        output_shape = (A.shape[0] * B.shape[0], A.shape[1] * B.shape[1])

        if A.nnz == 0 or B.nnz == 0:
            # kronecker product is the zero matrix
            return coo_matrix(output_shape)

        # expand entries of a into blocks
        row = A.row.repeat(B.nnz)
        col = A.col.repeat(B.nnz)
        data = A.data.repeat(B.nnz)

        if (
            max(A.shape[0] * B.shape[0], A.shape[1] * B.shape[1])
            > np.iinfo("int32").max
        ):
            row = row.astype(np.int64)
            col = col.astype(np.int64)

        row *= B.shape[0]
        col *= B.shape[1]

        # increment block indices
        row, col = row.reshape(-1, B.nnz), col.reshape(-1, B.nnz)
        row += B.row
        col += B.col
        row, col = row.reshape(-1), col.reshape(-1)

        # compute block entries
        data = data.reshape(-1, B.nnz) * B.data
        data = data.reshape(-1)

        return coo_matrix((data, (row, col)), shape=output_shape).asformat(format)