scirs2-numpy
A SciRS2-maintained fork of rust-numpy providing Rust interfaces for the NumPy C API with native support for ndarray 0.17.
What Is This Crate?
scirs2-numpy is the bridge between Rust's ndarray crate and Python's NumPy library. It enables:
- Zero-copy conversion of NumPy arrays to Rust
ndarrayarrays (where memory layout permits) - Returning Rust arrays to Python as NumPy arrays without data copying
- Complex number support for scientific computing workloads
- Multi-dimensional array support up to dynamic rank (
PyArrayDyn)
The key motivation for maintaining this fork is ndarray 0.17 support. The upstream rust-numpy crate pins to ndarray 0.16, which creates a version conflict when used alongside the rest of the SciRS2 ecosystem (which uses ndarray 0.17 throughout). This fork eliminates that conflict, enabling direct zero-copy interop in scirs2-python.
Relationship to rust-numpy
| Feature | rust-numpy (upstream) |
scirs2-numpy (this crate) |
|---|---|---|
| ndarray version | 0.16 | 0.17 |
| Zero-copy interop | Yes | Yes |
| Complex arrays | Yes | Yes |
| nalgebra integration | Yes | Yes |
| PyO3 version | Latest | Latest |
| SciRS2 compatibility | Needs conversion | Native, no conversion |
If you do not use SciRS2 internals and only need NumPy interop in your own PyO3 extension, you can use the upstream rust-numpy. Use scirs2-numpy when you need compatibility with scirs2-* crates.
When to Use This Crate vs scirs2-python
| Scenario | Recommended |
|---|---|
| Writing a Python extension that calls SciRS2 internals | scirs2-numpy + PyO3 |
| Using SciRS2 from Python | scirs2-python (wraps this crate) |
| Pure Python user, no Rust code | pip install scirs2 |
| Standalone Rust project needing NumPy interop | rust-numpy (upstream) |
Features
- Zero-copy array sharing: Rust reads/writes NumPy array memory directly when alignment and contiguity permit
- Numeric type support:
f32,f64,i32,i64,u32,u64,c32(complex float),c64(complex double) - Multi-dimensional arrays:
PyArray0throughPyArray6andPyArrayDynfor dynamic rank - Read/write access control:
PyReadonlyArrayandPyReadwriteArrayfor safe borrow semantics - Memory layout handling: C-order (row-major) and Fortran-order (column-major) both supported
- Type coercion:
PyArrayLikefor accepting arrays with automatic type conversion - nalgebra integration: Optional
nalgebrafeature converts between NumPy arrays andnalgebra::Matrix AllowTypeChange/TypeMustMatch: Control strictness of type checking at array boundaries
Usage
Add to your Cargo.toml:
[]
= { = "../scirs2-numpy" }
# or from crates.io once published:
# scirs2-numpy = "0.3.1"
= { = "0.22", = ["extension-module"] }
Basic Example: Accepting a NumPy Array and Returning One
use *;
use ;
use Array1;
Matrix Operations (2D Arrays)
use *;
use ;
use Array2;
Dynamic Rank Arrays
use *;
use ;
Complex Number Support
use *;
use ;
use Complex64;
Read/Write Mutable Access
use *;
use ;
nalgebra Integration (Optional Feature)
// Cargo.toml: scirs2-numpy = { version = "0.3.1", features = ["nalgebra"] }
use *;
use ;
Type Aliases
use ;
Memory Layout
NumPy supports both C-order (row-major) and Fortran-order (column-major) arrays. scirs2-numpy handles both:
use ;
// Check if an array is C-contiguous (row-major)
let is_c_order = array.is_c_contiguous;
// Check if Fortran-contiguous (column-major)
let is_f_order = array.is_fortran_contiguous;
For non-contiguous arrays (strides that are not standard), the crate automatically copies into a contiguous buffer before providing a Rust view.
Type Coercion with PyArrayLike
PyArrayLike accepts Python lists, NumPy arrays, and other array-like objects, performing type coercion:
use *;
use ;
API Overview
| Type / Function | Description |
|---|---|
PyArray<T, D> |
Core type wrapping a NumPy array of element type T and ndim D |
PyArrayDyn<T> |
Dynamic-rank NumPy array |
PyArray0..6<T> |
Fixed-rank aliases (0D through 6D) |
PyReadonlyArray |
Shared read-only borrow of array memory |
PyReadwriteArray |
Exclusive read-write borrow of array memory |
ToPyArray |
Trait to convert ndarray::Array → PyArray |
PyArrayMethods |
Core method trait: shape(), strides(), as_array(), readonly(), readwrite() |
PyArrayLike<T> |
Accept array-like Python objects with type coercion |
AllowTypeChange |
Marker: allow implicit type conversion when receiving arrays |
TypeMustMatch |
Marker: require exact dtype match |
get_array_module |
Get the numpy Python module object |
Integration with SciRS2-Python
scirs2-python uses scirs2-numpy internally for all its Python binding modules. When you call scirs2.fft_py(data) from Python, the data flow is:
Python ndarray (NumPy)
|
v zero-copy (via scirs2-numpy, PyReadonlyArray)
Rust ndarray::ArrayView<f64> (ndarray 0.17)
|
v SciRS2 computation (scirs2-fft, etc.)
Rust ndarray::Array<f64>
|
v zero-copy (via ToPyArray)
Python ndarray (NumPy)
This eliminates the ndarray 0.16/0.17 conversion overhead that affected earlier versions.
Building
This crate is a standard Rust library. Build with:
To run the Python integration tests, a Python environment with NumPy installed is required:
License
Licensed under the Apache License 2.0. See LICENSE for details.
Authors
COOLJAPAN OU (Team KitaSan)
Acknowledgments
Based on the upstream rust-numpy project by the PyO3 contributors, modified for ndarray 0.17 compatibility and SciRS2 ecosystem integration.