#![allow(dead_code)]
const BASES: [u8; 4] = [b'A', b'C', b'G', b'T'];
pub struct Rng {
state: u64,
}
impl Rng {
pub fn new(seed: u64) -> Self {
Rng {
state: if seed == 0 {
0x9E37_79B9_7F4A_7C15
} else {
seed
},
}
}
fn next_u64(&mut self) -> u64 {
let mut x = self.state;
x ^= x << 13;
x ^= x >> 7;
x ^= x << 17;
self.state = x;
x
}
fn next_f64(&mut self) -> f64 {
(self.next_u64() >> 11) as f64 / (1u64 << 53) as f64
}
fn random_base(&mut self) -> u8 {
BASES[(self.next_u64() % 4) as usize]
}
}
pub fn random_molecule(len: usize, rng: &mut Rng) -> Vec<u8> {
(0..len).map(|_| rng.random_base()).collect()
}
pub fn mutant(truth: &[u8], sub_rate: f64, indel_rate: f64, rng: &mut Rng) -> Vec<u8> {
let ins = indel_rate / 2.0;
let del = indel_rate / 2.0;
let mut out = Vec::with_capacity(truth.len() + 8);
for &b in truth {
if rng.next_f64() < ins {
out.push(rng.random_base());
}
let roll = rng.next_f64();
if roll < del {
continue; } else if roll < del + sub_rate {
out.push(rng.random_base()); } else {
out.push(b);
}
}
out
}
pub fn family(truth_len: usize, n: usize, seed: u64) -> (Vec<u8>, Vec<Vec<u8>>) {
let mut rng = Rng::new(seed);
let truth = random_molecule(truth_len, &mut rng);
let reads = (0..n)
.map(|_| mutant(&truth, 0.01, 0.005, &mut rng))
.collect();
(truth, reads)
}
pub const REGIME: &[(usize, usize)] = &[
(3, 235),
(4, 235),
(6, 235),
(10, 235),
(50, 1000), ];