Periodic cubic splines just went from O(n²) to O(n) — and your .npz files now write compressed, in pure Rust.
Today we released NumRS2 0.3.0 — a release that pairs a genuine algorithmic speedup with compressed pure-Rust storage and a full lift onto the SciRS2 0.3.0 stack.
This one earns its minor-version bump. The headline is a real interpolation win: periodic cubic-spline solves are now linear-time. Around it, .npz archives finally write DEFLATE-compressed — through the COOLJAPAN pure-Rust archive layer, with no zlib and no C — and every SciRS2 dependency moves up to v0.3.0, pulling in faster spatial structures, sharper SIMD, and updated special functions.
No C. No Fortran. No system BLAS/LAPACK. No zlib for compression. No Python interpreter overhead. No FFI. Just clean, blazing-fast N-dimensional arrays — broadcasting, fancy indexing, SVD, FFT, autodiff and all — that compile to a single static binary (or WASM) and run everywhere: from laptops to browsers to edge devices to cloud clusters.
Why NumRS2 0.3.0 matters
NumPy is the bedrock of scientific Python, but its foundation shows its age — built on C and Fortran, dependent on a system BLAS/LAPACK you have to link at install time, throttled by the GIL, and stuck reaching for native zlib the moment you want compressed .npz on disk. Periodic interpolation, in particular, is the kind of thing that quietly costs you: a naive cyclic spline solve scales quadratically, and on long periodic signals that is real wall-clock time.
NumRS2 0.3.0 answers with concrete wins:
- Periodic cubic-spline interpolation is now O(n). The old O(n²) Gaussian-elimination cyclic solve is replaced by a Sherman-Morrison cyclic Thomas algorithm — linear-time. On long periodic series the difference is not a micro-optimization; it changes the complexity class.
.npzfiles now write DEFLATE-compressed, in pure Rust. Compression is enabled through OxiARC, COOLJAPAN’s pure-Rust archive/compression crate — no zlib, no C, no native dependency. Your arrays land smaller on disk and stay sovereign.- The whole SciRS2 stack moves to 0.3.0. Core, linalg, stats, FFT, ndimage, spatial, special, and the numpy bridge all step up together — so improvements arrive as a coherent set, not a patchwork.
- Faster KD-trees.
scirs2-spatial 0.3.0brings improved KD-tree construction and queries — spatial workloads that lean on nearest-neighbor search get faster for free. - Sharper SIMD and updated special functions.
scirs2-core 0.3.0enhances SIMD, parallel, and random ops, whilescirs2-special 0.3.0refreshes the special-function set NumRS2 exposes.
Technical Deep Dive: The O(n) Cyclic Thomas Solver, Compressed .npz, and the 0.3.0 Stack
Layer 1 — From O(n²) to O(n) periodic splines. A natural cubic spline reduces to a tridiagonal system, which the Thomas algorithm solves in linear time. A periodic (cyclic) cubic spline breaks that nice structure: the periodicity constraint adds corner entries to the matrix, turning it from tridiagonal into “tridiagonal plus a rank-one perturbation.” The old solver fell back to general Gaussian elimination on that system — O(n²). NumRS2 0.3.0 instead applies the Sherman-Morrison identity to handle the rank-one corner correction, then runs the standard tridiagonal Thomas solve twice. The result is mathematically exact and runs in O(n). For periodic data — closed curves, cyclic time series, anything that wraps around — this is the difference between a quadratic blowup and a flat, linear cost.
Layer 2 — DEFLATE .npz through OxiARC. A .npz is, structurally, a multi-file archive of .npy members. Writing it compressed means running each member through DEFLATE inside an archive container. This had been waiting on OxiARC to fix a multi-file bug in its v0.3.0+ line; with that resolved, NumRS2 enables DEFLATE compression for .npz writes. The payoff is twofold: smaller files, and a storage path that is pure Rust top to bottom — no zlib, no native codec linked into your binary. Compressed array I/O is now as sovereign as the math that produced the arrays.
Layer 3 — The SciRS2 0.3.0 lift, across the whole stack. Every scirs2-* dependency moves to v0.3.0 in one coordinated step: scirs2-core 0.3.0 (enhanced SIMD, parallel, and random ops), scirs2-linalg 0.3.0 (linear-algebra improvements on OxiBLAS), scirs2-stats 0.3.0 (statistical-function enhancements), scirs2-fft 0.3.0 (FFT improvements), scirs2-ndimage 0.3.0 (N-dimensional image processing), scirs2-spatial 0.3.0 (spatial algorithms with improved KD-trees), scirs2-special 0.3.0 (special-function updates), and scirs2-numpy 0.3.0 (Python-bindings compatibility). Because the stack moves together, NumRS2 inherits the gains without version-skew between the layers it sits on.
Layer 4 — WASM stays honest. The WebAssembly build is held to the same standard as everything else: the version-assertion tests were updated to expect “0.3”, so the same numerical code that runs on a laptop or a cluster keeps running bit-for-bit in the browser, now on the 0.3.0 stack.
Getting Started
cargo add numrs2
use numrs2::prelude::*;
fn main() -> Result<()> {
// N-dimensional arrays with NumPy-style broadcasting
let a = Array::from_vec(vec![1.0, 2.0, 3.0, 4.0]).reshape(&[2, 2]);
let b = Array::from_vec(vec![5.0, 6.0, 7.0, 8.0]).reshape(&[2, 2]);
let e = a.matmul(&b)?; // matrix multiply on OxiBLAS
println!("a @ b = {}", e);
// Descriptive statistics
let data = Array::from_vec(vec![1.0, 2.0, 3.0, 4.0, 5.0]);
println!("mean = {}, std = {}", data.mean()?, data.std()?);
// FFT on a real signal
let signal = Array::from_vec(vec![1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]);
let spectrum = signal.fft()?;
println!("spectrum = {}", spectrum);
Ok(())
}
For periodic data, reach for cubic-spline interpolation: as of 0.3.0 the periodic (cyclic) solve runs in O(n), so fitting a closed curve or a wrap-around time series is linear-time. And when you persist the result, saving to .npz now writes a DEFLATE-compressed, pure-Rust archive — smaller on disk, with no zlib in your binary.
What’s New in 0.3.0
- Cyclic spline solver rewritten — the O(n²) Gaussian-elimination cyclic spline solve is replaced by a Sherman-Morrison O(n) cyclic Thomas algorithm; periodic cubic-spline interpolation is now linear-time.
- NPZ compression enabled —
.npzfiles now write DEFLATE-compressed via OxiARC (pure Rust, no zlib/C), after the OxiARC v0.3.0+ multi-file bug was fixed. - SciRS2 ecosystem update — all
scirs2-*dependencies updated to v0.3.0: core, linalg, stats, fft, ndimage, spatial (improved KD-trees), special, and numpy. - Fixed: WASM version-assertion tests updated to expect “0.3”.
Tips
- Periodic interpolation is now O(n) — use it for anything that wraps. Closed curves, cyclic schedules, looping signals: the periodic cubic-spline solve is linear-time as of 0.3.0, so you no longer pay a quadratic penalty as the series gets long.
- Your
.npzfiles just got smaller, for free..npzwrites now apply DEFLATE compression through OxiARC. It is pure Rust — no zlib to link — so compressed array storage costs you nothing in dependencies and saves you disk. - You inherit SciRS2 0.3.0’s improvements automatically. Faster KD-trees (
scirs2-spatial), enhanced SIMD and parallel ops (scirs2-core), and updated special functions (scirs2-special) come along with the lift — spatial and vectorized workloads speed up without any code change on your side. - Keep the SciRS2 stack aligned at 0.3.0. NumRS2 0.3.0 expects the full
scirs2-*family at v0.3.0; pin them together so core, linalg, stats, fft, ndimage, spatial, special, and numpy all match. - Re-run your WASM assertions. If you assert on the library version in a wasm32 build, expect “0.3” now — the version-assertion tests were updated for this release.
This is the foundation
NumRS2 is the NumPy-class N-dimensional array core of the COOLJAPAN scientific stack, and 0.3.0 lifts it onto the SciRS2 0.3.0 generation. It sits directly beneath SciRS2, depending on the full scirs2-* family at v0.3.0 — core, linalg, stats, fft, ndimage, spatial, and special — for unified SIMD, statistics, transforms, spatial structures, and special functions. Linear algebra rides on OxiBLAS, serialization on OxiCode, and compressed .npz now on OxiARC — all pure-Rust COOLJAPAN crates.
By March 2026 the ecosystem around it is broad and deepening: OptiRS and PandRS alongside NumRS2; the OxiFFT, OxiARC, OxiZ, OxiGDAL, and OxiLean infrastructure crates; ML and application work spanning ToRSh, VoiRS, TenRSo, TensorLogic, legalis, mecrab, chie, mielin, and oxirag. NumRS2 is the array layer all of them can build on — now faster on periodic data, smaller on disk, and aligned to the 0.3.0 stack.
Repository: https://github.com/cool-japan/numrs
Star the repo if you want a NumPy-class numerical foundation with linear-time periodic splines and compressed pure-Rust storage — and not a line of C or Fortran in the build.
Pure Rust numerical computing is here — fast, safe, and sovereign.
— KitaSan at COOLJAPAN OÜ March 6, 2026