PyO3 / rust-numpy

PyO3-based Rust bindings of the NumPy C-API
BSD 2-Clause "Simplified" License
1.07k stars 98 forks source link

Support nalgebra transposed conversion #424

Closed akern40 closed 3 months ago

akern40 commented 3 months ago

Hi! Love working with this library and its integration with nalgebra. However, I was wondering whether it would be possible to support an additional set of conversions to/from nalgebra which essentially act as "transpose" conversions. The current .as_matrix works great if you want to keep thinking of the array in Python and Rust as the same shape and convention; however, I would really like to write a library that expects the matrix convention to be different between the Python and the Rust code.

As a concrete example, the following 2x3 matrix in Python/NumPy with C-style ordering

[[0, 1, 2],
 [3, 4, 5]]

is the exact same memory layout as the following 3x2 matrix in nalgebra with F-style ordering

[[0, 3],
 [1, 4],
 [2, 5]]

however, the current code cannot produce this conversion without an additional nalgebra transpose and data copy, as far as I can tell. I'd be happy to put in a PR for adding this behavior! Would like to hear peoples' thoughts, thanks.

adamreichold commented 3 months ago

Can't you apply as_matrix with C-style ordering by explicitly requesting the corresponding strides and then transpose that via nalgebra's routine?

adamreichold commented 3 months ago

Alternatively, if nalgebra cannot transpose without copying, you want to use reshape_with_order to do that on the NumPy representation and only then apply as_matrix.

akern40 commented 3 months ago

Thanks for the quick reply - I've been playing around with some options, but I can't figure out how to get either of these to work. The function is written to take in a PyArrayLike2, meaning we don't know the shape or strides when receiving it. I've attempted a reshape_with_order, but I don't think that this can accomplish a no-copy transpose: Numpy performs both the indexing and placing of the array elements using the given order. What we want is more like indexing in C-order but placing in F-order (or vice-versa).

adamreichold commented 3 months ago

Do you think exposing a safe interface to NumPy's Transpose help with this?

akern40 commented 3 months ago

Yes, I think that would work! Either that or SwapAxes.

adamreichold commented 3 months ago

I went for permute/transpose as the more general transformation. Could you give the code in #428 a try to see whether it resolves your issue?