pub fn cordiv(numerator: &[u8], denominator: &[u8]) -> Vec<u8> {
let len = numerator.len().min(denominator.len());
let mut out = vec![0u8; len];
let mut prev = 0u8;
for t in 0..len {
if numerator[t] == 1 {
out[t] = 1;
} else if denominator[t] == 1 {
out[t] = 0;
} else {
out[t] = prev;
}
prev = out[t];
}
out
}
pub fn cordiv_packed(num_packed: &[u64], den_packed: &[u64], length: usize) -> Vec<u64> {
let n_words = num_packed.len().min(den_packed.len());
let mut out = vec![0u64; n_words];
let mut prev_bit = 0u8;
let total_bits = length.min(n_words * 64);
for bit_idx in 0..total_bits {
let word = bit_idx / 64;
let bit = bit_idx % 64;
let x = ((num_packed[word] >> bit) & 1) as u8;
let y = ((den_packed[word] >> bit) & 1) as u8;
let z = if x == 1 {
1u8
} else if y == 1 {
0u8
} else {
prev_bit
};
if z == 1 {
out[word] |= 1u64 << bit;
}
prev_bit = z;
}
out
}
pub fn adaptive_length_hoeffding(epsilon: f64, confidence: f64) -> usize {
let delta = 1.0 - confidence;
if delta <= 0.0 || epsilon <= 0.0 {
return 65536;
}
let l = -(delta / 2.0).ln() / (2.0 * epsilon * epsilon);
let l_int = l.ceil() as usize;
let l_int = l_int.max(64);
let mut p = 1usize;
while p < l_int {
p *= 2;
}
p.min(65536)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_cordiv_half_div_one() {
let x: Vec<u8> = (0..1000).map(|i| if i % 2 == 0 { 1 } else { 0 }).collect();
let y = vec![1u8; 1000];
let z = cordiv(&x, &y);
let p: f64 = z.iter().map(|&b| b as f64).sum::<f64>() / z.len() as f64;
assert!((p - 0.5).abs() < 0.05, "Expected ~0.5, got {p}");
}
#[test]
fn test_cordiv_zero_numerator() {
let x = vec![0u8; 100];
let y = vec![1u8; 100];
let z = cordiv(&x, &y);
assert!(z.iter().all(|&b| b == 0));
}
#[test]
fn test_cordiv_identity() {
let x: Vec<u8> = (0..1000).map(|i| if i % 3 != 0 { 1 } else { 0 }).collect();
let z = cordiv(&x, &x);
let p: f64 = z.iter().map(|&b| b as f64).sum::<f64>() / z.len() as f64;
assert!(p > 0.9, "Expected ~1.0, got {p}");
}
#[test]
fn test_adaptive_length_hoeffding() {
let l = adaptive_length_hoeffding(0.01, 0.95);
assert!(l >= 64);
assert!(l <= 65536);
assert!(l & (l - 1) == 0); }
#[test]
fn test_adaptive_tighter_needs_more() {
let l_coarse = adaptive_length_hoeffding(0.1, 0.95);
let l_fine = adaptive_length_hoeffding(0.01, 0.95);
assert!(l_fine > l_coarse);
}
}