const WINDOW_SIZE: u32 = 64;
const CHAR_OFFSET: u32 = 31;
pub struct Rollsum {
s1: u32,
s2: u32,
window: [u8; WINDOW_SIZE as usize],
wofs: usize,
}
impl Rollsum {
pub fn new() -> Self {
Self {
s1: WINDOW_SIZE * CHAR_OFFSET,
s2: WINDOW_SIZE * (WINDOW_SIZE - 1) * CHAR_OFFSET,
window: [0; WINDOW_SIZE as usize],
wofs: 0,
}
}
pub fn update(&mut self, byte: u8) {
self.rollsum_add(self.window[self.wofs], byte);
self.window[self.wofs] = byte;
self.wofs = (self.wofs + 1) % (WINDOW_SIZE as usize);
}
fn rollsum_add(&mut self, drop: u8, add: u8) {
let add = add as u32;
let drop = drop as u32;
self.s1 = self.s1.wrapping_add(add.wrapping_sub(drop));
self.s2 = self
.s2
.wrapping_add(self.s1.wrapping_sub(WINDOW_SIZE * (drop + CHAR_OFFSET)));
}
pub fn split(&self, mask: u32) -> bool {
self.s2 & mask == mask
}
}