Merge commit 'd803bfe2b1fe7f5e219e50ac20d6801a0a58ac75' as 'vendor/ruvector'
This commit is contained in:
177
vendor/ruvector/examples/ultra-low-latency-sim/src/bit_parallel.rs
vendored
Normal file
177
vendor/ruvector/examples/ultra-low-latency-sim/src/bit_parallel.rs
vendored
Normal file
@@ -0,0 +1,177 @@
|
||||
//! Bit-Parallel Simulation Primitives
|
||||
//!
|
||||
//! Each u64 word simulates 64 binary states simultaneously,
|
||||
//! providing a 64x multiplier over scalar simulation.
|
||||
|
||||
/// Generic bit-parallel automaton trait
|
||||
pub trait BitParallelAutomaton {
|
||||
/// Evolve all cells for one generation
|
||||
fn step(&mut self);
|
||||
|
||||
/// Number of cells (bits) being simulated
|
||||
fn num_cells(&self) -> usize;
|
||||
|
||||
/// Simulations per step (= num_cells)
|
||||
fn simulations_per_step(&self) -> u64 {
|
||||
self.num_cells() as u64
|
||||
}
|
||||
}
|
||||
|
||||
/// Rule-based 1D cellular automaton (Wolfram-style)
|
||||
/// Each u64 contains 64 cells, evolved using a lookup table
|
||||
#[repr(align(64))]
|
||||
pub struct CellularAutomaton1D {
|
||||
/// State: each bit is one cell
|
||||
state: Vec<u64>,
|
||||
/// Lookup table for 3-cell neighborhood → next cell
|
||||
rule_lut: [u8; 256],
|
||||
}
|
||||
|
||||
impl CellularAutomaton1D {
|
||||
/// Create CA with given number of u64 words and rule number
|
||||
pub fn new(num_words: usize, rule: u8) -> Self {
|
||||
// Build LUT: for each 8-bit pattern, compute result
|
||||
let mut rule_lut = [0u8; 256];
|
||||
for pattern in 0..=255u8 {
|
||||
let mut result = 0u8;
|
||||
for bit in 0..8 {
|
||||
let neighborhood = (pattern >> bit) & 0b111;
|
||||
let next = (rule >> neighborhood) & 1;
|
||||
result |= next << bit;
|
||||
}
|
||||
rule_lut[pattern as usize] = result;
|
||||
}
|
||||
|
||||
Self {
|
||||
state: vec![0xAAAA_AAAA_AAAA_AAAAu64; num_words],
|
||||
rule_lut,
|
||||
}
|
||||
}
|
||||
|
||||
/// Set initial state
|
||||
pub fn set_state(&mut self, initial: &[u64]) {
|
||||
self.state.copy_from_slice(initial);
|
||||
}
|
||||
|
||||
/// Get current state
|
||||
pub fn state(&self) -> &[u64] {
|
||||
&self.state
|
||||
}
|
||||
}
|
||||
|
||||
impl BitParallelAutomaton for CellularAutomaton1D {
|
||||
fn step(&mut self) {
|
||||
let len = self.state.len();
|
||||
if len == 0 { return; }
|
||||
|
||||
// We need to update in-place, so use temp for boundary handling
|
||||
let first = self.state[0];
|
||||
let last = self.state[len - 1];
|
||||
|
||||
for i in 0..len {
|
||||
let left = if i == 0 { last } else { self.state[i - 1] };
|
||||
let center = self.state[i];
|
||||
let right = if i == len - 1 { first } else { self.state[i + 1] };
|
||||
|
||||
let mut next = 0u64;
|
||||
for byte_idx in 0..8 {
|
||||
let shift = byte_idx * 8;
|
||||
// Extract 8-bit windows
|
||||
let l = ((left >> shift) & 0xFF) as u8;
|
||||
let c = ((center >> shift) & 0xFF) as u8;
|
||||
let r = ((right >> shift) & 0xFF) as u8;
|
||||
|
||||
// Combine into neighborhood pattern and lookup
|
||||
let pattern = l.rotate_right(1) ^ c ^ r.rotate_left(1);
|
||||
let result = self.rule_lut[pattern as usize];
|
||||
next |= (result as u64) << shift;
|
||||
}
|
||||
self.state[i] = next;
|
||||
}
|
||||
}
|
||||
|
||||
fn num_cells(&self) -> usize {
|
||||
self.state.len() * 64
|
||||
}
|
||||
}
|
||||
|
||||
/// Binary Markov chain with bit-parallel transitions
|
||||
/// Each bit represents one independent chain
|
||||
#[repr(align(64))]
|
||||
pub struct BinaryMarkovChain {
|
||||
/// Current states: 64 chains per u64
|
||||
states: Vec<u64>,
|
||||
/// Transition probability (0-65535 = 0.0-1.0)
|
||||
transition_threshold: u16,
|
||||
/// PRNG state
|
||||
rng_state: u64,
|
||||
}
|
||||
|
||||
impl BinaryMarkovChain {
|
||||
/// Create n×64 independent binary chains
|
||||
pub fn new(num_words: usize, transition_prob: f64) -> Self {
|
||||
let threshold = (transition_prob * 65535.0) as u16;
|
||||
Self {
|
||||
states: vec![0; num_words],
|
||||
transition_threshold: threshold,
|
||||
rng_state: 0x12345678_9ABCDEF0,
|
||||
}
|
||||
}
|
||||
|
||||
/// Fast xorshift64 PRNG
|
||||
#[inline(always)]
|
||||
fn next_random(&mut self) -> u64 {
|
||||
let mut x = self.rng_state;
|
||||
x ^= x << 13;
|
||||
x ^= x >> 7;
|
||||
x ^= x << 17;
|
||||
self.rng_state = x;
|
||||
x
|
||||
}
|
||||
}
|
||||
|
||||
impl BitParallelAutomaton for BinaryMarkovChain {
|
||||
fn step(&mut self) {
|
||||
let threshold = self.transition_threshold;
|
||||
let len = self.states.len();
|
||||
|
||||
for i in 0..len {
|
||||
let random = self.next_random();
|
||||
// Flip bit where random < threshold (probabilistic)
|
||||
// Using bit manipulation for parallel evaluation
|
||||
let flip_mask = random.wrapping_mul(threshold as u64);
|
||||
self.states[i] ^= flip_mask;
|
||||
}
|
||||
}
|
||||
|
||||
fn num_cells(&self) -> usize {
|
||||
self.states.len() * 64
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_ca_creation() {
|
||||
let ca = CellularAutomaton1D::new(16, 110);
|
||||
assert_eq!(ca.num_cells(), 16 * 64);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_ca_step() {
|
||||
let mut ca = CellularAutomaton1D::new(4, 110);
|
||||
let initial = ca.state().to_vec();
|
||||
ca.step();
|
||||
// State should change
|
||||
assert_ne!(ca.state(), &initial[..]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_markov_chain() {
|
||||
let mut mc = BinaryMarkovChain::new(8, 0.1);
|
||||
mc.step();
|
||||
assert_eq!(mc.num_cells(), 8 * 64);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user