COOLJAPAN
← All posts

SciRS2 0.6.1 Released — Real Codegen, DLPack Safety, and GPU-Dispatch Honesty

SciRS2 0.6.1 replaces placeholder and silently-wrong code paths with real implementations: genuine model-serving codegen, a critical DLPack SIGBUS fix, honest GPU-dispatch and hardware-detection reporting, and a symbolic-engine soundness fix — plus F-distribution ppf, spatial hamming distance, and new finance facades. Pure Rust, Apache-2.0.

release scirs2 rust scientific-computing pure-rust gpu correctness dlpack

Every scientific library accumulates a quiet kind of debt: a stub that returns a plausible number instead of a real one, a GPU probe that lies instead of erroring, an FFI boundary one missing attribute away from a crash. SciRS2 0.6.1 spent this release paying that debt down.

Today we released SciRS2 0.6.1 — a hardening release that replaces five separate placeholder, simulated, or silently-wrong code paths with real implementations, fixes a process-crashing DLPack bug, and closes a symbolic-engine soundness bug that could swap operands roughly one time in ten. Nothing about the public API expanded for its own sake this cycle; almost everything here exists because something that looked like it worked actually didn’t.

No C. No Fortran. No CUDA Toolkit, no system BLAS, nothing to apt install before cargo build succeeds. SciRS2 0.6.1 compiles to a single static binary (or WASM) and runs everywhere, exactly like every release before it — this cycle just makes sure what runs is telling you the truth.

Why SciRS2 0.6.1 is a game changer

Libraries that fake it are common, and the failure mode is always the same shape:

SciRS2 0.6.1 ends all five of those, concretely:

Technical Deep Dive: honesty at every boundary

The DLPack capsule, precisely. DLPack is a C ABI — the struct layout crossing the Rust/Python boundary has to match byte-for-byte what the consuming framework expects. BackingStore held the tensor’s backing allocation alive for the lifetime of the capsule, but without #[repr(C)], Rust was free to reorder or pad its fields however the compiler preferred. The moment Python’s garbage collector called the capsule’s destructor, that layout mismatch turned into a SIGBUS. The fix is one attribute, but finding it required treating “it works in testing” as insufficient evidence — the bug only manifests once garbage collection actually reclaims the capsule, which a short-lived test process may never trigger.

ModelPackager, for real this time. The new serving module — split into mod.rs/types.rs/packager.rs/codegen.rs/tests.rs — generates an actual temp-directory Cargo project around the model being packaged and invokes cargo build --release against it, producing a genuine native binary or C-shared-library artifact. The previous implementation wrote bytes that looked like output without ever compiling anything.

Why Backends::PRIMARY, not Backends::all(). Seven crates’ wgpu adapter/device enumeration now restricts discovery to Backends::PRIMARY (Vulkan/Metal/DX12/BrowserWebGPU). The secondary GL/GLES backend can look compatible on a host with a broken or missing Vulkan loader — enumeration succeeds, a device comes back — but GL is too limited for wgpu’s mandatory indirect-dispatch validation pipeline, so that device dies on its first real dispatch. Restricting discovery up front means adapter selection fails cleanly at startup instead of handing back a device that fails later, somewhere less convenient to debug.

The e-graph pop-order bug. cas/e_graph/extract.rs’s reconstruct() walks an e-graph iteratively (no recursion on LoweredOp, per SciRS2’s usual discipline) using an explicit work stack. Binary e-node children were pushed in reversed order but popped assuming forward order — a classic stack-vs-queue mismatch. For commutative operators the swap is invisible (a+b and b+a are equal), which is exactly why it survived undetected: it only produces a wrong answer for Pow/Sub/Div, and even then only non-deterministically, since the trigger depended on HashMap iteration order. sin²(x)+cos²(x) could intermittently — roughly one run in ten — extract as 2^sin(x)+2^cos(x) instead of simplifying to 1. The fix aligns the pop order with the already-correct pattern used by the sibling pattern::instantiate.

Getting Started

Two of 0.6.1’s new APIs, both genuinely new surface rather than internal hardening:

cargo add scirs2-stats scirs2-spatial
use scirs2_spatial::distance::hamming;
use scirs2_stats::distributions::f::F;

fn main() {
    // F::ppf is new in 0.6.1 — the inverse CDF, inverting the
    // regularized-incomplete-beta relation via bisection (same pattern
    // already used by Beta::ppf). Previously missing at both the Rust
    // and Python (PyF.ppf) layers.
    let f_dist = F::new(2.0f64, 10.0, 0.0, 1.0).expect("valid F distribution");
    let x = f_dist.ppf(0.5).expect("ppf(0.5) succeeds");
    let p_roundtrip = f_dist.cdf(x);
    println!("F(2,10).ppf(0.5) = {x:.6}  (roundtrip cdf = {p_roundtrip:.6})");
    assert!((p_roundtrip - 0.5).abs() < 1e-6);

    // hamming() is also new — proportion of differing coordinates,
    // matching scipy.spatial.distance.hamming semantics exactly.
    let point1 = &[1.0, 0.0, 1.0, 1.0, 0.0];
    let point2 = &[1.0, 1.0, 0.0, 1.0, 0.0];
    let dist = hamming(point1, point2);
    println!("hamming distance = {dist}"); // 2 of 5 coordinates differ -> 0.4
    assert!((dist - 0.4f64).abs() < 1e-6);
}

What’s New in 0.6.1

Added

Changed

Fixed

Removed

See CHANGELOG.md [0.6.1] for the complete list.

Tips

  1. Match on the new Option<f64>, don’t unwrap it. If you read BenchmarkResult.gpu_time_ms/.speedup from scirs2-datasets, None now means “no real GPU dispatch ran” — treat it as a real signal, not a null you paper over with unwrap_or(0.0), or you’ll silently reintroduce the fabricated-zero problem this release just removed.
  2. cuda_available() needs no crate feature to tell the truth now. PlatformCapabilities::detect() runtime-probes the NVIDIA driver unconditionally, so downstream Device::cuda_if_available()-style code (as in trustformers) sees accurate hardware state without an extra feature flag — if you had a workaround for the old hardcoded false, it’s safe to remove.
  3. Upgrade immediately if you touch DLPack. The #[repr(C)] fix addresses a real crash risk in any long-running process that creates and garbage-collects DLPack capsules — this isn’t a cosmetic fix, it’s a production stability one.
  4. F::ppf closes a real gap if you were computing F-distribution critical values or confidence intervals by hand — it mirrors Beta::ppf’s bisection approach and is available identically from Python via PyF.ppf.
  5. A custom wgpu adapter-selection path? Check it against the new Backends::PRIMARY restriction — if you were relying on the GL/GLES fallback on a host with a broken Vulkan loader, adapter discovery now fails at startup instead of handing you a device that dies on first dispatch.
  6. Turn on memory_tracking in scirs2-stats if you need real peak/average RSS numbers from the SciPy benchmark framework — without the feature, it reports honest zeros rather than a fabricated figure, which is correct but not useful if you actually need the numbers.

This is the foundation

SciRS2 0.6.1 is the sovereign scientific-computing layer of the COOLJAPAN ecosystem, and a correctness release matters precisely because so much depends on that foundation telling the truth:

Every one of these inherits SciRS2’s DLPack boundary, its GPU-dispatch reporting, and its symbolic engine along with everything else — so a SIGBUS fixed here is a SIGBUS that never reaches a downstream model-serving pipeline, and a soundness fix in the e-graph is one less place a ToRSh or TrustformeRS computation could silently get the wrong answer. The numeric core still rests on OxiBLAS and OxiFFT; verification on OxiZ; the new NVIDIA performance path on OxiCUDA; 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 library that would rather return an honest error than a fabricated number is what you’ve been waiting for.

The era of “it probably works” is over. Pure Rust scientific computing is here — fast, safe, and honest about what it actually did.

KitaSan at COOLJAPAN OÜ July 15, 2026

↑ Back to all posts