COOLJAPAN
← All posts

SciRS2 0.5.1 Released — Correctness, API Stability, and Deeper Pure-Rust Sovereignty

SciRS2 0.5.1 is a correctness and Pure-Rust hardening release: exact autograd gradients for matrix functions (Sylvester / Daleckii–Krein / reduced-SVD VJP), a restored CoreError #[non_exhaustive] contract, honest GPU/CUDA reporting, public Zarr v2/v3, and the removal of the C/MPFR rug, C rusqlite, and tokenizers dependencies. 36,606 tests, zero warnings — the sovereign scientific-computing layer of the COOLJAPAN ecosystem.

release scirs2 rust scientific-computing pure-rust autograd linear-algebra correctness

A scientific-computing stack whose gradients are now provably correct, whose error types are stable by contract, and which just deleted its last C and MPFR dependencies — all in pure Rust.

Today we released SciRS2 0.5.1 — a correctness, API-stability, and Pure-Rust hardening release. Where 0.4.4 built a computer algebra system and 0.5.0 made the GPU story real, 0.5.1 is the release that goes back through the stack and makes the hard parts right: exact spectral gradients, honest device reporting, a stable error contract, and a cleaner pure-Rust dependency tree.

No C. No Fortran. No OpenBLAS. No NumPy/SciPy system dependencies — and now, no MPFR either. 0.5.1 removes the C/MPFR-backed rug, the C-backed rusqlite, and the tokenizers dependency, along with the external either, hex, urlencoding, and data-encoding crates. Arbitrary precision now runs on oxinum-* (scirs2-special’s arbitrary_precision migrated rugoxinum-float), SQLite runs on oxisql-sqlite-compat, blake3 builds with its no-ASM pure feature, and scirs2-io vendors its own encoding_utils (hex / percent-encode / base64). The default build is, once again, 100% pure Rust — only now there is even less C lurking behind the feature flags.

This is a patch release by number, but a meaningful one: 36,606 tests passing plus 4,999 doc-tests across 29 workspace crates, roughly 3.9 million lines of Rust, 80,800+ public API items, zero warnings (clippy + rustdoc + fmt clean), Apache-2.0.

Why SciRS2 0.5.1 is a game changer

Feature counts are easy. Correctness is hard — and it is exactly where most scientific libraries quietly cut corners. A gradient that silently returns all-zeros, a “GPU context” that fabricates throughput numbers it never measured, an error enum that breaks downstream code the moment you add a variant: these are the bugs that don’t show up in a feature matrix but cost you a week when they bite. 0.5.1 hunts them down.

Concrete 0.5.1 wins:

Technical Deep Dive: getting the gradients right

Spectral gradients done properly. Differentiating a matrix function is not the same as differentiating it elementwise. The derivative of A^{1/2}, log(A), or A^p couples every eigen-pair of A, and the textbook-correct formulas are nontrivial. 0.5.1 implements them as written: the matrix-square-root backward solves a Sylvester equation relating the output gradient to the input; the matrix-log and matrix-power backwards use Daleckii–Krein divided differences over the spectrum; and the SVD backward is the Townsend / Wan–Zhang reduced-SVD VJP, complete with detection of degenerate (repeated) singular values — the case where the naive formula blows up. These live in scirs2-autograd’s new decomposition_backward.rs alongside the existing cholesky_backward, lu_backward, qr_backward, and svd_backward primitives, so the whole matrix-factorization family now backpropagates correctly.

Honesty over optimism. The GPU/CUDA cleanup is a philosophy as much as a patch. The old code, when a real device or measurement was missing, would rather return something — a default context, an identity result, a plausible-looking throughput number. That is the worst possible failure mode: it produces wrong answers silently. 0.5.1 changes the contract across scirs2-core, scirs2-linalg, and scirs2-fft so those paths return BackendNotAvailable / NotImplemented or an honest Option<f64> instead. If SciRS2 didn’t measure it, it won’t claim it.

Stability as a feature. The restored CoreError #[non_exhaustive] is small in diff and large in consequence. With it, adding a new error variant in a future release is a non-breaking change — downstream match expressions are required to carry a wildcard _ arm, so they keep compiling. The new core_error_non_exhaustive compile-fail test in scirs2-stability-tests makes that guarantee executable: the contract can no longer be lost by accident.

Pure Rust, deeper. The dependency purge is the quiet headline. rug pulled in GMP/MPFR — C and assembly — for arbitrary precision; scirs2-special’s arbitrary_precision now runs on oxinum-float instead. rusqlite linked libsqlite3; it is replaced by oxisql-sqlite-compat. tokenizers is gone. blake3 now builds with its pure (no-ASM) feature to respect the no-assembly default. And four small encoding crates (either, hex, urlencoding, data-encoding) were replaced by a crate-local Either<L, R> sum type in scirs2-stats and a vendored encoding_utils in scirs2-io. The ecosystem deps moved forward in lockstep: OxiArc 0.3.3, OxiSQL 0.3.1, OxiNum 0.1.2 (plus a new oxinum-complex), OxiH5 0.1.3, OxiZ 0.2.3, OxiCode 0.2.4, and OxiEML 0.1.2.

Getting Started

Add the crate:

cargo add scirs2

A minimal autograd example exercising the corrected matrix-function gradients — build a symmetric positive-definite matrix, take its matrix square root inside the tape, and get an exact gradient back:

use scirs2_autograd as ag;
use ag::tensor_ops as T;

fn main() {
    ag::run(|ctx| {
        // A small symmetric positive-definite matrix.
        let a = T::convert_to_tensor(
            ndarray::array![[4.0_f64, 1.0], [1.0, 3.0]].into_dyn(),
            ctx,
        );

        // Matrix square root, differentiated correctly via the
        // Sylvester-equation backward (MatrixSqrtBackwardOp).
        let s = T::matrix_sqrt(a);

        // A scalar objective: the trace of sqrt(A).
        // trace now has an exact reverse-mode gradient (gy * I_n).
        let loss = T::trace(&s);

        // Exact gradient dloss/dA — no all-zeros, no wrong shapes.
        let grad = &T::grad(&[loss], &[a])[0];

        println!("loss = {:?}", loss.eval(ctx));
        println!("dloss/dA =\n{:?}", grad.eval(ctx));
    });
}

Every gradient above is exact in 0.5.1 — the same code in an earlier release would have silently returned zeros.

What’s New in 0.5.1

Added

Changed

Fixed

Tips

  1. Add a wildcard arm to CoreError matches. With #[non_exhaustive] restored, any exhaustive match over CoreError must include a _ => { ... } arm — that is the whole point, and it keeps your code compiling when new variants land. The core_error_non_exhaustive compile-fail test enforces the contract upstream.
  2. Query the device before you dispatch. Call GpuDevice::get_info() and check the returned GpuDeviceInfo for fp64 support and work-group limits before sending an f64 GPU workload — it is the cheapest way to avoid a silent precision downgrade or an over-sized dispatch.
  3. Trust the matrix-function gradients now. matrix_sqrt, matrix_log, matrix_power, trace, and the SVD extractors backpropagate exactly in 0.5.1. If you pinned an earlier version specifically because these gradients were wrong, upgrade and delete your workaround.
  4. Reach for scirs2_io::zarr for chunked arrays. The Zarr v2/v3 module is now public — use it for directory-backed, codec-compressed, chunk-sliceable array storage that interoperates with the wider Zarr ecosystem.
  5. The Python import path is unchanged. The internal Rust crate is now scirs2_python, but Python users keep writing import scirs2. Nothing changes for downstream Python code.
  6. If you depended on either transitively through scirs2-stats, switch to scirs2_stats::Either — the external crate is gone, replaced by an allocation-free crate-local sum type.

This is the foundation

SciRS2 0.5.1 is the sovereign scientific-computing layer of the COOLJAPAN ecosystem — and a correctness release matters most precisely because so much is built on top of it:

Every one of these inherits SciRS2’s gradients, its error types, and its dependency tree — so when 0.5.1 makes a matrix-function gradient exact, restores an error contract, or deletes a C dependency, the entire stack above it gets more correct and more sovereign at once. The numeric core still rests on OxiBLAS and OxiFFT; verification on OxiZ; arbitrary precision now on OxiNum; compression on OxiARC; storage on OxiSQL and OxiH5. No C. No Fortran. No exceptions in the default build.

Repository: https://github.com/cool-japan/scirs

Star the repo if a scientific-computing foundation whose correctness you can actually trust — pure Rust, no C, no Fortran, no MPFR — is what you’ve been waiting for.

Pure Rust scientific computing — now correct, stable, and sovereign to the core.

KitaSan at COOLJAPAN OÜ June 25, 2026

↑ Back to all posts