numeris
Pure-Rust numerical algorithms library, no-std compatible. Similar in scope to SciPy, suitable for embedded targets (no heap allocation, no FPU assumptions).
Features
- Fixed-size matrices — stack-allocated, const-generic
Matrix<T, M, N> - Dynamic matrices — heap-allocated
DynMatrix<T>with runtime dimensions (optionalallocfeature) - Linear algebra — LU, Cholesky, and QR decompositions with solve, inverse, and determinant
- ODE integration — fixed-step RK4, 7 adaptive Runge-Kutta solvers with dense output, RODAS4 stiff solver
- Optimization — root finding (Brent, Newton), BFGS minimization, Gauss-Newton and Levenberg-Marquardt least squares
- Complex number support — all decompositions work with
Complex<f32>/Complex<f64>(optional feature) - Quaternions — unit quaternion rotations, SLERP, Euler angles, rotation matrices
- Norms — L1, L2, Frobenius, infinity, one norms
- No-std / embedded — runs without
stdor heap; float math falls back to softwarelibm
Quick start
[]
= "0.1"
use ;
// Solve a linear system Ax = b
let a = new;
let b = from_array;
let x = a.solve.unwrap; // x = [2, 3, -1]
// Cholesky decomposition of a symmetric positive-definite matrix
let spd = new;
let chol = spd.cholesky.unwrap;
let inv = chol.inverse;
// QR decomposition and least-squares
let a = new;
let b = from_array;
let x = a.qr.unwrap.solve; // least-squares fit
// Quaternion rotation
use Quaternion;
let q = from_axis_angle;
let v = from_array;
let rotated = q * v; // [0, 1, 0]
Dynamic matrices
When dimensions aren't known at compile time, use DynMatrix (requires alloc, included with default std feature):
use ;
// Runtime-sized matrix
let a = from_slice;
let b = from_slice;
let x = a.solve.unwrap;
// Convert between fixed and dynamic
use Matrix;
let fixed = new;
let dynamic: = fixed.into;
let back: = .try_into.unwrap;
// Mixed arithmetic
let result = fixed * &dynamic; // Matrix * DynMatrix → DynMatrix
Type aliases: DynMatrixf64, DynMatrixf32, DynVectorf64, DynVectorf32, DynMatrixz64 (complex, requires complex feature), etc.
ODE integration
Fixed-step RK4 and 7 adaptive Runge-Kutta solvers with embedded error estimation and dense output:
use ;
use Vector;
// Harmonic oscillator: y'' = -y
let y0 = from_array;
let tau = 2.0 * PI;
let sol = RKTS54integrate.unwrap;
assert!; // cos(2π) ≈ 1
Explicit solvers
| Solver | Stages | Order | FSAL | Interpolant |
|---|---|---|---|---|
RKF45 |
6 | 5(4) | no | — |
RKTS54 |
7 | 5(4) | yes | 4th degree |
RKV65 |
10 | 6(5) | no | 6th degree |
RKV87 |
17 | 8(7) | no | 7th degree |
RKV98 |
21 | 9(8) | no | 8th degree |
RKV98NoInterp |
16 | 9(8) | no | — |
RKV98Efficient |
26 | 9(8) | no | 9th degree |
Stiff solvers (Rosenbrock)
For stiff ODEs (chemical kinetics, circuit simulation, orbital mechanics with drag), use RODAS4 — a linearly-implicit Rosenbrock method that solves linear systems involving the Jacobian instead of nonlinear Newton iterations:
use ;
use ;
// Stiff decay: y' = -1000*y, y(0) = 1
let y0 = from_array;
let sol = RODAS4integrate.unwrap;
// Or use integrate_auto for automatic finite-difference Jacobian
| Solver | Stages | Order | L-stable |
|---|---|---|---|
RODAS4 |
6 | 4(3) | yes |
Optimization
Root finding, unconstrained minimization, and nonlinear least squares (requires optim feature):
[]
= { = "0.1", = ["optim"] }
use ;
use ;
// Root finding: solve x² - 2 = 0
let root = brent.unwrap;
assert!;
// BFGS minimization: minimize (x-1)² + (y-2)²
let min = minimize_bfgs.unwrap;
assert!;
// Levenberg-Marquardt: fit y = a * exp(b * x)
let t = ;
let y = ;
let fit = least_squares_lm.unwrap;
assert!;
| Algorithm | Function | Use case |
|---|---|---|
| Brent's method | brent |
Bracketed scalar root finding |
| Newton's method | newton_1d |
Scalar root finding with derivative |
| BFGS | minimize_bfgs |
Unconstrained minimization |
| Gauss-Newton | least_squares_gn |
Nonlinear least squares (QR-based) |
| Levenberg-Marquardt | least_squares_lm |
Nonlinear least squares (damped) |
Finite-difference utilities: finite_difference_gradient and finite_difference_jacobian for when analytical derivatives aren't available.
Complex matrices
Enable the complex feature to use decompositions with complex elements:
[]
= { = "0.1", = ["complex"] }
use ;
type C = ;
let a = new;
let b = from_array;
let x = a.solve.unwrap;
// Hermitian positive-definite Cholesky (A = L * L^H)
let hpd = new;
let chol = hpd.cholesky.unwrap;
Complex support adds zero overhead to real-valued code paths. The LinalgScalar trait methods (modulus, conj, etc.) are #[inline] identity functions for f32/f64, fully erased by the compiler.
Cargo features
| Feature | Default | Description |
|---|---|---|
std |
yes | Implies alloc. Uses hardware FPU via system libm. |
alloc |
via std |
Enables DynMatrix / DynVector (heap-allocated, runtime-sized). |
ode |
yes | ODE integration (RK4, adaptive solvers). |
optim |
no | Optimization (root finding, BFGS, Gauss-Newton, LM). |
libm |
baseline | Pure-Rust software float math. Always available as fallback. |
complex |
no | Adds Complex<f32> / Complex<f64> support via num-complex. |
all |
no | All features: std + ode + optim + complex. |
# Default (std + ode)
# All features
# No-std for embedded
# No-std with dynamic matrices
# With optimization and complex support
Module overview
matrix — Fixed-size matrix
Matrix<T, M, N> with [[T; N]; M] row-major storage.
- Arithmetic:
+,-,*(matrix and scalar), negation, element-wise multiply/divide - Indexing:
m[(i, j)], row/column access, block extraction and insertion - Square:
trace,det,diag,from_diag,pow,is_symmetric,eye - Norms:
frobenius_norm,norm_inf,norm_one - Utilities:
transpose,from_fn,map,swap_rows,swap_cols,sum,abs - Iteration:
iter(),iter_mut(),as_slice(),IntoIterator
Vectors are type aliases: Vector<T, N> = Matrix<T, 1, N> (row vector), ColumnVector<T, N> = Matrix<T, N, 1>.
Vector-specific: dot, cross, outer, norm, norm_l1, normalize.
Size aliases
Convenience aliases are provided for common sizes (all re-exported from the crate root):
| Square | Rectangular (examples) | Vectors |
|---|---|---|
Matrix1 .. Matrix6 |
Matrix2x3, Matrix3x4, Matrix4x6, ... |
Vector1 .. Vector6 |
| All M×N combinations for M,N ∈ 1..6, M≠N | ColumnVector1 .. ColumnVector6 |
use ;
let rotation: = eye;
let points: = zeros; // 4 rows, 3 cols
let v: = from_array;
dynmatrix — Dynamic matrix (requires alloc)
DynMatrix<T> with Vec<T> row-major storage and runtime dimensions.
- Same arithmetic, norms, block ops, and utilities as fixed
Matrix - Mixed ops:
Matrix * DynMatrix,DynMatrix + Matrix, etc. →DynMatrix DynVector<T>newtype with single-index access anddot- Conversions:
From<Matrix>→DynMatrix,TryFrom<&DynMatrix>→Matrix - Full linalg:
DynLu,DynCholesky,DynQrwrappers + convenience methods
Type aliases: DynMatrixf64, DynMatrixf32, DynVectorf64, DynVectorf32, DynMatrixi32, DynMatrixi64, DynMatrixu32, DynMatrixu64, DynMatrixz64, DynMatrixz32 (complex).
linalg — Decompositions
All decompositions provide both free functions (operating on &mut impl MatrixMut<T>) and wrapper structs with solve(), inverse(), det().
| Decomposition | Free function | Fixed struct | Dynamic struct | Notes |
|---|---|---|---|---|
| LU | lu_in_place |
LuDecomposition |
DynLu |
Partial pivoting |
| Cholesky | cholesky_in_place |
CholeskyDecomposition |
DynCholesky |
A = LL^H (Hermitian) |
| QR | qr_in_place |
QrDecomposition |
DynQr |
Householder reflections, least-squares |
Convenience methods on Matrix: a.lu(), a.cholesky(), a.qr(), a.solve(&b), a.inverse(), a.det().
Same convenience methods on DynMatrix: a.lu(), a.cholesky(), a.qr(), a.solve(&b), a.inverse(), a.det().
ode — ODE integration
Fixed-step rk4 / rk4_step and 7 adaptive Runge-Kutta solvers via the RKAdaptive trait. PI step-size controller (Söderlind & Wang 2006). Dense output / interpolation available for most solvers (gated behind std). For stiff systems, RODAS4 provides an L-stable Rosenbrock method via the Rosenbrock trait — accepts user-supplied or automatic finite-difference Jacobians.
optim — Optimization (requires optim feature)
- Root finding:
brent(bracketed, superlinear convergence),newton_1d(with derivative) - Minimization:
minimize_bfgs(BFGS quasi-Newton with Armijo line search) - Least squares:
least_squares_gn(Gauss-Newton via QR),least_squares_lm(Levenberg-Marquardt via damped normal equations) - Finite differences:
finite_difference_gradient,finite_difference_jacobianfor numerical derivatives - All algorithms use
FloatScalarbound (real-valued), configurable via settings structs withDefaultimpls forf32andf64
quaternion — Unit quaternion rotations
Quaternion<T> with scalar-first convention [w, x, y, z].
- Construction:
new,identity,from_axis_angle,from_euler,from_rotation_matrix,rotx,roty,rotz - Operations:
*(Hamilton product),* Vector3(rotation),conjugate,inverse,normalize,slerp - Conversion:
to_rotation_matrix,to_axis_angle,to_euler
traits — Element traits
| Trait | Bounds | Used by |
|---|---|---|
Scalar |
Copy + PartialEq + Debug + Zero + One + Num |
All matrix ops |
FloatScalar |
Scalar + Float + LinalgScalar<Real=Self> |
Quaternions, ordered comparisons |
LinalgScalar |
Scalar + modulus, conj, re, lsqrt, lln, from_real |
Decompositions, norms |
MatrixRef<T> |
Read-only get(row, col) |
Generic algorithms |
MatrixMut<T> |
Adds get_mut(row, col) |
In-place decompositions |
Module plan
Checked items are implemented; unchecked are potential future work.
- matrix — Fixed-size matrix (stack-allocated, const-generic dimensions), size aliases up to 6×6
- linalg — LU, Cholesky, QR decompositions; solvers, inverse, determinant; complex support
- quaternion — Unit quaternion for rotations (SLERP, Euler, axis-angle, rotation matrices)
- ode — ODE integration (RK4, 7 adaptive solvers, dense output, RODAS4 stiff solver)
- dynmatrix — Heap-allocated runtime-sized matrix/vector (
allocfeature) - interp — Interpolation (linear, cubic spline, Hermite)
- optim — Optimization (Brent, Newton, BFGS, Gauss-Newton, Levenberg-Marquardt)
- quad — Numerical quadrature / integration
- fft — Fast Fourier Transform
- special — Special functions (Bessel, gamma, erf, etc.)
- stats — Statistics and distributions
- poly — Polynomial operations and root-finding
Design decisions
- Stack-allocated:
[[T; N]; M]storage, no heap. Dimensions are const generics. - Heap-allocated:
DynMatrixusesVec<T>for runtime dimensions, behindallocfeature. num-traits: Generic numeric bounds withdefault-features = false.- In-place algorithms: Decompositions operate on
&mut impl MatrixMut<T>, avoiding allocator/storage trait complexity. BothMatrixandDynMatriximplementMatrixMut, so the same free functions work for both. - Integer matrices: Work with
Scalar(all basic ops). Float-only operations (det, norms, decompositions) requireLinalgScalarorFloatScalar. - Complex support: Additive, behind a feature flag. Zero cost for real-only usage.
License
MIT