use rand::Rng;
use rand_chacha::ChaCha20Rng;
use rand::SeedableRng;
pub fn generate_hhat(h: usize, w: usize, seed: &[u8; 32]) -> Vec<Vec<u32>> {
let mut rng = ChaCha20Rng::from_seed(*seed);
let mask = (1u32 << h) - 1;
let mut cols: Vec<u32> = Vec::with_capacity(w);
for _ in 0..w {
let mut val = rng.r#gen::<u32>() & mask;
if val.count_ones().is_multiple_of(2) {
val ^= 1; }
cols.push(val);
}
let mut rows = vec![vec![0u32; w]; h];
for (c, &col_val) in cols.iter().enumerate() {
for r in 0..h {
if col_val & (1 << r) != 0 {
rows[r][c] = 1;
}
}
}
rows
}
pub fn column_packed(hhat: &[Vec<u32>], col: usize) -> u32 {
let h = hhat.len();
let mut val = 0u32;
for r in 0..h {
if hhat[r][col] != 0 {
val |= 1 << r;
}
}
val
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn deterministic() {
let seed = [42u8; 32];
let a = generate_hhat(7, 100, &seed);
let b = generate_hhat(7, 100, &seed);
assert_eq!(a, b);
}
#[test]
fn odd_weight_columns() {
let seed = [7u8; 32];
let hhat = generate_hhat(7, 200, &seed);
for c in 0..200 {
let col = column_packed(&hhat, c);
assert!(
col.count_ones() % 2 == 1,
"column {c} has even weight: {col:#b}"
);
}
}
#[test]
fn different_seeds_differ() {
let a = generate_hhat(7, 50, &[1u8; 32]);
let b = generate_hhat(7, 50, &[2u8; 32]);
assert_ne!(a, b);
}
}