gen_queue: add in_flight_count tracking for all work item types (not just AnalyzeBody). Rewrite saturation test with AnalyzeBody items. Fix priority_ordering test thread count to match new gate. rng: collapse to single AtlasRng::new(seed) constructor — callers own their seed transform. import_province_boundaries: fix "savepoint" comment to "transaction". Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
58 lines
1.6 KiB
Rust
58 lines
1.6 KiB
Rust
//! Seeded LCG for deterministic generation (D-010).
|
|
//!
|
|
//! Shared by all atlas generation modules that need seeded randomness.
|
|
//! Uses Knuth's LCG parameters — integer-only arithmetic, no f32, D-010 compliant.
|
|
//!
|
|
//! Callers are responsible for any seed pre-mixing before calling `AtlasRng::new`.
|
|
|
|
/// Seeded linear congruential generator (D-010).
|
|
pub struct AtlasRng {
|
|
state: u64,
|
|
}
|
|
|
|
impl AtlasRng {
|
|
/// Create a new RNG from a pre-mixed seed.
|
|
///
|
|
/// Callers must ensure the seed is non-degenerate (avoid passing 0 directly
|
|
/// if the seed could realistically be 0 — add a constant before calling).
|
|
pub fn new(seed: u64) -> Self {
|
|
Self { state: seed }
|
|
}
|
|
|
|
fn next_u64(&mut self) -> u64 {
|
|
self.state = self
|
|
.state
|
|
.wrapping_mul(6364136223846793005)
|
|
.wrapping_add(1442695040888963407);
|
|
self.state
|
|
}
|
|
|
|
/// Next pseudorandom `u32` (top 31 bits of the LCG state).
|
|
pub fn next_u32(&mut self) -> u32 {
|
|
(self.next_u64() >> 33) as u32
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn deterministic_sequence() {
|
|
let mut a = AtlasRng::new(42);
|
|
let mut b = AtlasRng::new(42);
|
|
for _ in 0..100 {
|
|
assert_eq!(a.next_u32(), b.next_u32());
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn different_seeds_differ() {
|
|
let mut a = AtlasRng::new(1);
|
|
let mut b = AtlasRng::new(2);
|
|
let vals_a: Vec<u32> = (0..10).map(|_| a.next_u32()).collect();
|
|
let vals_b: Vec<u32> = (0..10).map(|_| b.next_u32()).collect();
|
|
assert_ne!(vals_a, vals_b);
|
|
}
|
|
}
|