#[inline]
pub fn fast_inc(val: &mut [u8], start: &mut usize, end: usize, inc: &[u8]) {
let mut pos = end;
let mut carry = 0u8;
for inc_pos in (0..inc.len()).rev() {
debug_assert!(
pos > 0,
"Buffer overflowed, make sure you allocate val with enough headroom."
);
pos -= 1;
let mut new_val = inc[inc_pos] + carry;
if pos >= *start {
new_val += val[pos] - b'0';
}
if new_val > b'9' {
carry = 1;
new_val -= 10;
} else {
carry = 0;
}
val[pos] = new_val;
}
if carry == 0 {
*start = (*start).min(pos);
return;
}
fast_inc_one(val, start, pos);
}
#[inline]
pub fn fast_inc_one(val: &mut [u8], start: &mut usize, end: usize) {
let mut pos = end;
while pos > *start {
pos -= 1;
if val[pos] == b'9' {
val[pos] = b'0';
} else {
val[pos] += 1;
return;
}
}
debug_assert!(
*start > 0,
"Buffer overflowed, make sure you allocate val with enough headroom."
);
val[*start - 1] = b'1';
*start -= 1;
}
#[cfg(test)]
mod tests {
use crate::fast_inc::fast_inc;
use crate::fast_inc::fast_inc_one;
#[test]
fn test_fast_inc_simple() {
let mut val = Vec::from("...0_".as_bytes());
let mut start: usize = 3;
let inc = "4".as_bytes();
fast_inc(val.as_mut(), &mut start, 4, inc);
assert_eq!(start, 3);
assert_eq!(val, "...4_".as_bytes());
fast_inc(val.as_mut(), &mut start, 4, inc);
assert_eq!(start, 3);
assert_eq!(val, "...8_".as_bytes());
fast_inc(val.as_mut(), &mut start, 4, inc);
assert_eq!(start, 2); assert_eq!(val, "..12_".as_bytes());
let mut val = Vec::from("0_".as_bytes());
let mut start: usize = 0;
let inc = "2".as_bytes();
fast_inc(val.as_mut(), &mut start, 1, inc);
assert_eq!(start, 0);
assert_eq!(val, "2_".as_bytes());
fast_inc(val.as_mut(), &mut start, 1, inc);
assert_eq!(start, 0);
assert_eq!(val, "4_".as_bytes());
fast_inc(val.as_mut(), &mut start, 1, inc);
assert_eq!(start, 0);
assert_eq!(val, "6_".as_bytes());
}
#[test]
fn test_fast_inc_large_inc() {
let mut val = Vec::from("...7_".as_bytes());
let mut start: usize = 3;
let inc = "543".as_bytes();
fast_inc(val.as_mut(), &mut start, 4, inc);
assert_eq!(start, 1); assert_eq!(val, ".550_".as_bytes());
fast_inc(val.as_mut(), &mut start, 4, inc);
assert_eq!(start, 0); assert_eq!(val, "1093_".as_bytes());
}
#[test]
fn test_fast_inc_carry() {
let mut val = Vec::from(".999_".as_bytes());
let mut start: usize = 1;
let inc = "1".as_bytes();
fast_inc(val.as_mut(), &mut start, 4, inc);
assert_eq!(start, 0);
assert_eq!(val, "1000_".as_bytes());
let mut val = Vec::from(".999_".as_bytes());
let mut start: usize = 1;
let inc = "11".as_bytes();
fast_inc(val.as_mut(), &mut start, 4, inc);
assert_eq!(start, 0);
assert_eq!(val, "1010_".as_bytes());
}
#[test]
fn test_fast_inc_one_simple() {
let mut val = Vec::from("...8_".as_bytes());
let mut start: usize = 3;
fast_inc_one(val.as_mut(), &mut start, 4);
assert_eq!(start, 3);
assert_eq!(val, "...9_".as_bytes());
fast_inc_one(val.as_mut(), &mut start, 4);
assert_eq!(start, 2); assert_eq!(val, "..10_".as_bytes());
fast_inc_one(val.as_mut(), &mut start, 4);
assert_eq!(start, 2);
assert_eq!(val, "..11_".as_bytes());
let mut val = Vec::from("0_".as_bytes());
let mut start: usize = 0;
fast_inc_one(val.as_mut(), &mut start, 1);
assert_eq!(start, 0);
assert_eq!(val, "1_".as_bytes());
fast_inc_one(val.as_mut(), &mut start, 1);
assert_eq!(start, 0);
assert_eq!(val, "2_".as_bytes());
fast_inc_one(val.as_mut(), &mut start, 1);
assert_eq!(start, 0);
assert_eq!(val, "3_".as_bytes());
}
}