If you had CSR rather than CSC input, you could avoid random access in `R`, but you'd get random access over `w`. Do you know that this is a bottleneck in the function?

You might get a very small win (although the compiler may already do this) by pulling `w[ii]` out. Otherwise, you could try use typed memoryviews (and you can require the data to be contiguous rather than strided; `scipy.sparse` already requires contiguous arrays for many of its internal operations) instead of the Cython numpy interface, and from this could even just treat the underlying data as C arrays, cutting a little more overhead.