| Crates.io | aporia |
| lib.rs | aporia |
| version | 0.2.0 |
| created_at | 2024-11-11 16:26:21.653342+00 |
| updated_at | 2025-08-10 03:52:03.550663+00 |
| description | A flexible random number generation library |
| homepage | |
| repository | https://github.com/SkuldNorniern/aporia |
| max_upload_size | |
| id | 1443903 |
| size | 51,912 |
Aporia is a small, dependency-free Rust RNG library with multiple backends and a consistent, ergonomic API. It favors clarity, correctness, and reproducibility. Not intended for cryptography.
Aporia (ἀπορία): Greek for “difficulty,” “perplexity,” or “impasse.”
Rng wrapper API across backendsu64/f64 and a fill_bytes helperno_std support (with optional std feature)Default (with std feature enabled):
[dependencies]
aporia = "0.1.2"
no_std (disable default std feature):
[dependencies]
aporia = { version = "0.1.2", default-features = false }
use aporia::{Rng, backend::XorShift};
fn main() {
let mut rng = Rng::new(XorShift::new(12345));
let n = rng.next_u64();
let x = rng.next_f64(); // in [0, 1)
println!("n = {n}, x = {x}");
}
The Rng::gen_range(min, max) method returns Result<u64, AporiaError>. It uses the unbiased “zone” rejection method to avoid modulo bias.
use aporia::{Rng, backend::XorShift};
fn sample_10_to_20() -> Result<u64, aporia::AporiaError> {
let mut rng = Rng::new(XorShift::new(1));
let v = rng.gen_range(10, 20)?; // returns Ok(10..20)
Ok(v)
}
fn sample_floats() -> Result<f64, aporia::AporiaError> {
let mut rng = Rng::new(XorShift::new(2));
let v = rng.gen_range_f64(0.0, 1.0)?; // Ok([0.0, 1.0))
Ok(v)
}
If bounds are guaranteed valid at the call site, using expect is acceptable:
use aporia::{Rng, backend::XorShift};
let mut rng = Rng::new(XorShift::new(7));
// Bounds are known-valid here; expecting success is safe.
let v = rng.gen_range(100, 200).expect("min < max holds by construction");
use aporia::{Rng, backend::SplitMix64};
let mut rng = Rng::new(SplitMix64::new(123));
// Take some u64s
let sum: u64 = rng.iter_u64().take(5).sum();
// Iterate f64s in [0,1)
let mut avg = 0.0;
for (i, x) in rng.iter_f64().take(10).enumerate() {
avg = (avg * i as f64 + x) / (i as f64 + 1.0);
}
// Fill a byte buffer
let mut buf = [0u8; 32];
rng.fill_bytes(&mut buf);
The crate uses a small custom error enum:
#[derive(Debug, Clone, PartialEq)]
pub enum AporiaError {
InvalidRangeU64 { min: u64, max: u64 },
InvalidRangeF64 { min: f64, max: f64 },
InvalidSeed(&'static str),
}
Examples of Result-based APIs:
Rng::gen_range(min, max) -> Result<u64, AporiaError>Rng::gen_range_f64(min, max) -> Result<f64, AporiaError>XorShift::try_new(seed) -> Result<XorShift, AporiaError>When std feature is enabled (default), AporiaError implements std::error::Error.
#![no_std] when built with default-features = false.For a given backend and seed, sequences are intended to remain stable across patch/minor versions.
Contributions are welcome. Please open an issue or PR for bugs or enhancements.