ferray
A tiny NumPy-like library for Python, written in Rust. Built to learn the inner workings of NumPy and explore Rust-Python interoperability with PyO3 and maturin.
Overview
ferray is an educational project that implements a NumPy-like multidimensional array library in Rust with Python bindings. It demonstrates how to build high-performance numerical computing libraries using Rust's safety and speed while maintaining Python's ease of use.
The project uses OpenBLAS for optimized linear algebra operations and PyO3 for seamless Python-Rust interoperability.
Key Features
- NumPy-like API: Familiar interface for Python developers with array operations
- Rust Performance: Fast operations with zero-cost abstractions and memory safety
- OpenBLAS Integration: Leverages optimized BLAS routines for linear algebra
- Python Bindings: Seamless integration via PyO3 and maturin
- Broadcasting Support: NumPy-style broadcasting for element-wise operations
- NumPy Interoperability: Convert between NumPy arrays and ferray
Supported Operations
Array Creation
NdArray([2, 3])— Create uninitialized arrayzeros([3, 4])— Create array filled with zerosones([2, 3])— Create array filled with onesfrom_list([[1, 2], [3, 4]])— From Python listfrom_numpy(arr)— From NumPy array
Indexing & Reshaping
a[0, 2]— Element access via indexinga.get([0, 1])— Get element at positiona.set([0, 1], 42.0)— Set element valuea.reshape([3, 2])— Change shapea.transpose()— Matrix transpose
Element-wise Operations
a + b— Addition with broadcastinga - b— Subtractiona * b— Multiplicationa / b— Divisiona + 2.0— Scalar operations
Properties & Conversion
a.ndim()— Number of dimensionsa.shape()— Shape tuplea.to_list()— Convert to Python lista.to_numpy()— Convert to NumPy array
Installation
Prerequisites
OpenBLAS
# Ubuntu/Debian
sudo apt install libopenblas-dev
# macOS (Homebrew)
brew install openblas
# Arch Linux
sudo pacman -S openblasRust Toolchain
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | shMaturin
# Using uv (recommended)
uv tool install maturin
# Or using pip
pip install maturinBuilding the Package
# Clone the repository
git clone https://github.com/kashifulhaque/ferray.git
cd ferray
# Build and install in development mode
maturin develop --release
# Or using uv
uv run maturin develop --releaseUsage Examples
Basic Array Creation
import ferray as tnp
# Create arrays
a = tnp.NdArray.zeros([3, 4])
b = tnp.NdArray.ones([2, 3])
c = tnp.NdArray.from_list([[1.0, 2.0], [3.0, 4.0]])
# Check properties
print(a.shape()) # [3, 4]
print(a.ndim()) # 2Indexing and Assignment
a = tnp.NdArray.zeros([3, 4])
# Get and set values
print(a[0, 2]) # 0.0
a[0, 2] = 99.0
print(a[0, 2]) # 99.0
# Using methods
a.set([1, 3], 42.0)
print(a.get([1, 3])) # 42.0Element-wise Operations
a = tnp.NdArray.ones([2, 3])
b = tnp.NdArray.ones([1, 3]) * 2.0
print(a + b) # Broadcasting addition
print(a - b) # Subtraction
print(a * b) # Multiplication
print(a / b) # Division
# Scalar operations
print(a + 2.0)
print(a * 5.0)Transpose and Reshape
a = tnp.NdArray.from_list([
[1.0, 2.0, 3.0],
[4.0, 5.0, 6.0]
])
print(a.shape()) # [2, 3]
print(a.transpose()) # Transposed array
a.reshape([3, 2])
print(a.shape()) # [3, 2]NumPy Interoperability
import numpy as np
import ferray as tnp
# From NumPy to ferray
a_np = np.ones((2, 3), dtype=np.float32)
a_rust = tnp.NdArray.from_numpy(a_np)
# Back to NumPy
a_back = a_rust.to_numpy()
print(np.allclose(a_np, a_back)) # TrueUsing mise (Optional)
If you have mise installed, you can use the provided task commands:
mise run develop
Build and install in development mode
mise run test
Run test suite
mise run bench
Run performance benchmarks
mise run check
Check code quality
Project Structure
src/lib.rs: PyO3 module definition and exportssrc/array.rs: Core NdArray implementationsrc/operations.rs: Element-wise operations and broadcastingsrc/conversions.rs: NumPy interoperabilitysrc/utils.rs: Helper functions and utilitiesbuild.rs: Build script for linking OpenBLAStest.py: Basic functionality testsbench_matmul.py: Matrix multiplication benchmarks
Tech Stack
Language Rust
Python Bindings PyO3
Build Tool maturin
Linear Algebra OpenBLAS
Target Python 3.11+
Learning Goals
- Understanding NumPy's internal architecture and memory layout
- Exploring Rust-Python interoperability with PyO3
- Implementing broadcasting semantics for array operations
- Integrating native BLAS libraries for performance
- Building Python extensions with maturin
- Managing memory safety across language boundaries