#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct Scrambler {
pub c_init: u32,
}
impl Scrambler {
pub fn sequence(&self, n: usize) -> Vec<u8> {
comnum_math::sequences::gold_3gpp(self.c_init, n)
}
pub fn scramble(&self, bits: &[u8]) -> Vec<u8> {
bits.iter().zip(self.sequence(bits.len())).map(|(b, c)| b ^ c).collect()
}
pub fn descramble_llr(&self, llr: &[f64]) -> Vec<f64> {
llr.iter().zip(self.sequence(llr.len())).map(|(l, c)| if c == 1 { -l } else { *l }).collect()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn the_sequence_is_balanced_and_depends_on_its_seed() {
let a = Scrambler { c_init: 1 }.sequence(10_000);
let b = Scrambler { c_init: 2 }.sequence(10_000);
let ones = a.iter().filter(|v| **v == 1).count();
assert!((ones as f64 / 1e4 - 0.5).abs() < 0.02);
assert_ne!(a, b);
let llr = [1.0, -2.0, 3.0];
let s = Scrambler { c_init: 7 };
assert_eq!(s.descramble_llr(&s.descramble_llr(&llr)), llr);
}
}