Skip to content

no_std Usage

Numra’s core crate supports no_std environments, making it usable on embedded systems, WASM targets, and other constrained platforms.

Rust’s standard library (std) depends on an operating system for features like heap allocation, file I/O, and threading. The no_std attribute removes this dependency, enabling bare-metal usage.

Numra uses a layered approach:

  • numra-core: Fully no_std compatible (with alloc)
  • Higher crates (numra-ode, numra-linalg, etc.): Require std

numra-core uses a Cargo feature flag:

[dependencies]
numra-core = { version = "0.1", default-features = false }

With default-features = false, the crate compiles without std. It still requires the alloc crate for Vec and String.

#![no_std]
extern crate alloc;
use numra_core::{Scalar, Uncertain, Interval};
use alloc::vec;
use alloc::vec::Vec;

The Scalar trait uses libm for math functions when std is unavailable. All transcendental functions (sin, cos, exp, ln, sqrt, etc.) work identically in both modes:

use numra_core::Scalar;
fn compute_decay<S: Scalar>(k: S, t: S) -> S {
(-k * t).exp() // Uses libm::exp in no_std, std::f64::exp in std
}

All Scalar methods work in no_std:

CategoryFunctions
Basicabs, sqrt, cbrt, powi, powf
Trigsin, cos, tan, asin, acos, atan, atan2
Hyperbolicsinh, cosh, tanh
Exponentialexp, ln, log2, log10
Roundingfloor, ceil, round
Comparisonmin_val, max_val, clamp
Classificationis_finite, is_nan, is_infinite

All Numra algorithms are generic over S: Scalar, meaning they work with both f32 and f64. Use f32 to halve memory usage on memory-constrained targets:

use numra_core::Uncertain;
// f32 uncertainty propagation
let x = Uncertain::<f32>::from_std(10.0, 0.5);
let y = Uncertain::<f32>::from_std(5.0, 0.3);
let result = x.mul(&y);
println!("f32: {} +/- {}", result.mean, result.std());
// f64 for full precision
let x = Uncertain::<f64>::from_std(10.0, 0.5);
let y = Uncertain::<f64>::from_std(5.0, 0.3);
let result = x.mul(&y);
println!("f64: {} +/- {}", result.mean, result.std());
Aspectf32f64
Digits~7 decimal~15 decimal
Epsilon1.19e-72.22e-16
Range1.18e-38 to 3.4e+382.23e-308 to 1.8e+308
Memory4 bytes8 bytes
Best forEmbedded, GPU, bulk dataScientific computing

Caution: For ODE solving, f32 limits achievable accuracy. Tolerances below rtol ~ 1e-5 may not be meaningful with f32.

Crateno_stdNotes
numra-coreYes (with alloc)Scalar, Vector, Signal, Uncertain, Interval
numra-odeNoRequires std for complex solvers
numra-linalgNoUses faer (requires std)
numra-nonlinearNoDepends on numra-linalg
numra-integrateNoRequires std
numra-interpNoRequires std
numra-autodiffNoRequires std
numra-specialNoRequires std
numra-fftNoUses rustfft (requires std)
numra-signalNoDepends on numra-fft
numra-statsNoRequires std
numra-fitNoDepends on numra-linalg
numra-optimizeNoDepends on numra-linalg
numra-ocpNoDepends on numra-ode

The Signal trait and most signal types work in no_std. The exception is FromFile, which requires filesystem access:

use numra_core::signal::{Harmonic, Step, Ramp, Pulse};
// These all work in no_std
let sine = Harmonic::new(1.0, 10.0, 0.0);
let step = Step::new(1.0, 0.5); // amplitude=1, at t=0.5
let ramp = Ramp::new(0.0, 1.0); // from t=0 to t=1

numra-core compiles to WebAssembly without modification:

.cargo/config.toml
[build]
target = "wasm32-unknown-unknown"

For WASM with a JavaScript host, you can use wasm-bindgen to expose Numra functions:

use wasm_bindgen::prelude::*;
use numra_core::{Uncertain, Scalar};
#[wasm_bindgen]
pub fn propagate_uncertainty(mean: f64, std: f64, scale: f64) -> Vec<f64> {
let x = Uncertain::<f64>::from_std(mean, std);
let result = x.scale(scale);
vec![result.mean, result.std()]
}
  1. Use numra-core directly for embedded projects; don’t pull in the full numra facade crate
  2. Prefer f64 unless memory is truly constrained — the precision difference matters for numerical methods
  3. Test with both features — run cargo test with and without the std feature to catch accidental std dependencies
  4. Pre-allocate vectors where possible to reduce allocator pressure on constrained targets