NumRS2 Python Guide
February 16, 2026 · View on GitHub
Complete guide to using NumRS2 from Python via PyO3 bindings.
Table of Contents
- Installation
- Quick Start
- API Reference
- NumPy Compatibility
- Performance
- Advanced Usage
- Troubleshooting
Installation
Prerequisites
- Python 3.8 or higher
- Rust toolchain (for building from source)
- maturin (Python package builder)
Installing from Source
# Install maturin
pip install maturin
# Clone the repository
git clone https://github.com/cool-japan/numrs
cd numrs
# Build and install in development mode
maturin develop --release --features python
# Or build a wheel
maturin build --release --features python
pip install target/wheels/numrs2-*.whl
Verify Installation
import numrs2 as nr
print(nr.__version__)
Quick Start
Basic Array Operations
import numrs2 as nr
import numpy as np
# Create arrays
a = nr.array([1.0, 2.0, 3.0, 4.0, 5.0])
b = nr.zeros([3, 4])
c = nr.ones([2, 3])
d = nr.eye(3)
# Array properties
print(a.shape) # [5]
print(a.ndim) # 1
print(a.size) # 5
print(a.dtype) # 'float64'
# Operations
a_sum = a.sum()
a_mean = a.mean()
a_min = a.min()
a_max = a.max()
# Reshape and transpose
matrix = a.reshape([5, 1])
transposed = matrix.transpose()
# Convert to NumPy
numpy_array = a.to_numpy(None)
Element-wise Operations
x = nr.array([1.0, 2.0, 3.0])
y = nr.array([4.0, 5.0, 6.0])
# Arithmetic
z = x + y # [5.0, 7.0, 9.0]
z = x - y # [-3.0, -3.0, -3.0]
z = x * y # [4.0, 10.0, 18.0]
z = x / y # [0.25, 0.4, 0.5]
# Negation
neg_x = -x # [-1.0, -2.0, -3.0]
API Reference
Array Creation
array(data)
Create an array from Python list, tuple, or NumPy array.
a = nr.array([1.0, 2.0, 3.0])
b = nr.array(np.array([4.0, 5.0, 6.0]))
zeros(shape)
Create an array filled with zeros.
z = nr.zeros([2, 3]) # 2x3 array of zeros
ones(shape)
Create an array filled with ones.
o = nr.ones([3, 2]) # 3x2 array of ones
eye(n, m=None, k=None)
Create a 2D array with ones on the diagonal.
I = nr.eye(3) # 3x3 identity matrix
identity(n)
Create an n×n identity matrix.
I = nr.identity(4) # 4x4 identity matrix
linspace(start, stop, num, endpoint=True)
Create an array with evenly spaced values.
x = nr.linspace(0.0, 1.0, 11) # [0.0, 0.1, ..., 1.0]
arange(start, stop, step=None)
Create an array with values in a range.
r = nr.arange(0.0, 10.0, 2.0) # [0.0, 2.0, 4.0, 6.0, 8.0]
full(shape, fill_value)
Create an array filled with a constant value.
f = nr.full([2, 3], 7.0) # 2x3 array filled with 7.0
zeros_like(a), ones_like(a)
Create arrays with the same shape as another array.
a = nr.array([1.0, 2.0, 3.0])
z = nr.zeros_like(a) # Same shape as a, filled with zeros
Array Methods
reshape(shape)
Reshape array to new dimensions.
a = nr.array([1.0, 2.0, 3.0, 4.0, 5.0, 6.0])
b = a.reshape([2, 3]) # 2x3 matrix
transpose()
Transpose array (swap dimensions).
a = nr.zeros([2, 3])
b = a.transpose() # Shape: [3, 2]
flatten()
Flatten array to 1D.
a = nr.array([1.0, 2.0, 3.0, 4.0]).reshape([2, 2])
b = a.flatten() # Shape: [4]
squeeze()
Remove dimensions of size 1.
a = nr.zeros([3, 1, 4, 1])
b = a.squeeze() # Shape: [3, 4]
tolist()
Convert to Python list.
a = nr.array([1.0, 2.0, 3.0])
lst = a.tolist() # [1.0, 2.0, 3.0]
to_numpy(py)
Convert to NumPy array.
a = nr.array([1.0, 2.0, 3.0])
np_array = a.to_numpy(None)
Linear Algebra (nr.linalg)
matmul(a, b)
Matrix multiplication.
A = nr.array([1.0, 2.0, 3.0, 4.0]).reshape([2, 2])
B = nr.array([5.0, 6.0, 7.0, 8.0]).reshape([2, 2])
C = nr.linalg.matmul(A, B)
# Or: C = nr.matmul(A, B)
dot(a, b)
Dot product.
u = nr.array([1.0, 2.0, 3.0])
v = nr.array([4.0, 5.0, 6.0])
result = nr.linalg.dot(u, v) # 32.0
# Or: result = nr.dot(u, v)
det(a)
Matrix determinant.
M = nr.array([4.0, 7.0, 2.0, 6.0]).reshape([2, 2])
d = nr.linalg.det(M)
trace(a)
Matrix trace (sum of diagonal elements).
M = nr.eye(3)
t = nr.linalg.trace(M) # 3.0
inv(a)
Matrix inverse.
M = nr.array([4.0, 7.0, 2.0, 6.0]).reshape([2, 2])
M_inv = nr.linalg.inv(M)
solve(a, b)
Solve linear system Ax = b.
A = nr.array([3.0, 1.0, 1.0, 2.0]).reshape([2, 2])
b = nr.array([9.0, 8.0])
x = nr.linalg.solve(A, b)
eigvals(a)
Compute eigenvalues.
M = nr.array([4.0, -2.0, 1.0, 1.0]).reshape([2, 2])
vals = nr.linalg.eigvals(M)
eig(a)
Eigendecomposition (eigenvalues and eigenvectors).
M = nr.array([4.0, -2.0, 1.0, 1.0]).reshape([2, 2])
vals, vecs = nr.linalg.eig(M)
svd(a, full_matrices=True)
Singular Value Decomposition.
A = nr.array([1.0, 2.0, 3.0, 4.0, 5.0, 6.0]).reshape([2, 3])
U, S, Vt = nr.linalg.svd(A)
qr(a)
QR decomposition.
A = nr.array([1.0, 2.0, 3.0, 4.0, 5.0, 6.0]).reshape([2, 3])
Q, R = nr.linalg.qr(A)
cholesky(a)
Cholesky decomposition (for positive definite matrices).
# A must be positive definite
L = nr.linalg.cholesky(A)
lu(a)
LU decomposition.
A = nr.array([1.0, 2.0, 3.0, 4.0]).reshape([2, 2])
P, L, U = nr.linalg.lu(A)
norm(a, ord=None)
Matrix or vector norm.
v = nr.array([3.0, 4.0])
n = nr.linalg.norm(v) # 5.0 (L2 norm)
cond(a)
Condition number.
M = nr.array([1.0, 2.0, 3.0, 4.0]).reshape([2, 2])
c = nr.linalg.cond(M)
matrix_rank(a, tol=None)
Matrix rank.
M = nr.array([1.0, 2.0, 2.0, 4.0]).reshape([2, 2])
r = nr.linalg.matrix_rank(M) # 1 (rank-deficient)
Statistics (nr.stats)
mean(a, axis=None)
Arithmetic mean.
a = nr.array([1.0, 2.0, 3.0, 4.0, 5.0])
m = nr.stats.mean(a) # 3.0
median(a, axis=None)
Median value.
a = nr.array([1.0, 2.0, 3.0, 4.0, 5.0])
med = nr.stats.median(a) # 3.0
std(a, axis=None, ddof=0)
Standard deviation.
a = nr.array([1.0, 2.0, 3.0, 4.0, 5.0])
s = nr.stats.std(a)
var(a, axis=None, ddof=0)
Variance.
a = nr.array([1.0, 2.0, 3.0, 4.0, 5.0])
v = nr.stats.var(a)
corrcoef(x, y=None)
Correlation coefficient.
x = nr.array([1.0, 2.0, 3.0, 4.0, 5.0])
y = nr.array([2.0, 4.0, 6.0, 8.0, 10.0])
corr_matrix = nr.stats.corrcoef(x, y)
histogram(a, bins=None, range=None)
Compute histogram.
a = nr.array([1.0, 2.0, 2.0, 3.0, 3.0, 3.0])
counts, edges = nr.stats.histogram(a, bins=3)
percentile(a, q)
Compute percentile.
a = nr.array([1.0, 2.0, 3.0, 4.0, 5.0])
p50 = nr.stats.percentile(a, 50.0) # Median
Random Numbers (nr.random)
randn(size)
Random samples from standard normal distribution.
samples = nr.random.randn([100]) # 100 samples from N(0, 1)
rand(size)
Random samples from uniform [0, 1) distribution.
samples = nr.random.rand([10, 10]) # 10x10 uniform random
Neural Networks (nr.nn)
Activation Functions
x = nr.array([-2.0, -1.0, 0.0, 1.0, 2.0])
# ReLU: max(0, x)
y = nr.nn.relu(x)
# Sigmoid: 1 / (1 + exp(-x))
y = nr.nn.sigmoid(x)
# Tanh: tanh(x)
y = nr.nn.tanh(x)
# Softmax (outputs sum to 1)
logits = nr.array([1.0, 2.0, 3.0])
probs = nr.nn.softmax(logits)
Loss Functions
predictions = nr.array([1.5, 2.3, 3.1])
targets = nr.array([1.0, 2.0, 3.0])
# Mean squared error
mse = nr.nn.mse_loss(predictions, targets)
# Cross-entropy
ce = nr.nn.cross_entropy_loss(predictions, targets)
Normalization
x = nr.array([1.0, 2.0, 3.0, 4.0, 5.0])
# Dropout (probability p)
dropped = nr.nn.dropout(x, p=0.5)
# Batch normalization
normalized = nr.nn.batch_norm(x, eps=1e-5)
I/O (nr.io)
NPY Format (NumPy Binary)
# Save
a = nr.array([1.0, 2.0, 3.0])
nr.io.save_npy("array.npy", a)
# Load
b = nr.io.load_npy("array.npy")
CSV Format
# Save
a = nr.array([1.0, 2.0, 3.0])
nr.io.save_csv("array.csv", a)
# Load
b = nr.io.load_csv("array.csv")
JSON Format
# Save
a = nr.array([1.0, 2.0, 3.0])
nr.io.save_json("array.json", a)
# Load
b = nr.io.load_json("array.json")
NumPy Compatibility
API Mapping
| NumPy | NumRS2 | Notes |
|---|---|---|
np.array() | nr.array() | Fully compatible |
np.zeros() | nr.zeros() | Fully compatible |
np.ones() | nr.ones() | Fully compatible |
np.eye() | nr.eye() | Fully compatible |
np.linspace() | nr.linspace() | Fully compatible |
np.arange() | nr.arange() | Fully compatible |
arr.reshape() | arr.reshape() | Fully compatible |
arr.T | arr.transpose() | Use method instead of property |
np.matmul() | nr.matmul() | Fully compatible |
np.linalg.det() | nr.linalg.det() | Fully compatible |
np.linalg.inv() | nr.linalg.inv() | Fully compatible |
np.mean() | nr.stats.mean() | In stats submodule |
np.std() | nr.stats.std() | In stats submodule |
Zero-Copy Conversion
NumRS2 supports efficient conversion to/from NumPy:
import numpy as np
import numrs2 as nr
# NumPy -> NumRS2
np_array = np.array([1.0, 2.0, 3.0])
nr_array = nr.array(np_array)
# NumRS2 -> NumPy
back_to_numpy = nr_array.to_numpy(None)
Performance
Benchmarks
NumRS2 leverages Rust's performance and SIMD optimizations:
- Array operations: Comparable to NumPy for large arrays
- Linear algebra: Uses OxiBLAS (pure Rust BLAS implementation)
- Memory safety: No segfaults or buffer overflows
Performance Tips
- Use vectorized operations instead of Python loops
- Minimize conversions between NumPy and NumRS2
- Preallocate arrays when possible
# Good: Vectorized
result = nr.array([1.0, 2.0, 3.0]) * 2.0
# Avoid: Python loops
result = nr.array([x * 2.0 for x in [1.0, 2.0, 3.0]])
Advanced Usage
Type Hints
NumRS2 provides type stubs for IDE support:
from numrs2 import Array
import numrs2 as nr
def process_data(arr: Array) -> Array:
return arr * 2.0
result: Array = nr.zeros([10])
Error Handling
NumRS2 converts Rust errors to Python exceptions:
try:
M = nr.array([1.0, 0.0, 0.0, 0.0]).reshape([2, 2])
inv = nr.linalg.inv(M) # Singular matrix
except ValueError as e:
print(f"Error: {e}")
Troubleshooting
Installation Issues
Problem: maturin: command not found
pip install maturin
Problem: Build fails with "Rust compiler not found"
# Install Rust
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
Runtime Issues
Problem: ImportError: cannot import name '_numrs2'
Solution: Rebuild the package:
maturin develop --release --features python
Problem: Dimension mismatch errors
Solution: Check array shapes before operations:
print(f"Shape: {arr.shape}")
Performance Issues
Problem: Operations slower than NumPy
Solution:
- Ensure you're using release build (
--releaseflag) - Check if SIMD optimizations are enabled
- Profile your code to identify bottlenecks
Examples
See the examples/python/ directory for complete examples:
basic_usage.py- Array creation and manipulationlinear_algebra.py- Matrix operations and decompositionsneural_networks.py- Neural network primitivesdata_io.py- Saving and loading arraysnumpy_migration.py- NumPy to NumRS2 migration guide
Further Reading
Contributing
We welcome contributions! Please see our contributing guidelines in the main repository.
License
NumRS2 is licensed under Apache-2.0.
Version: 0.2.0 Last Updated: 2026-02-09