use num::Integer;
#[derive(Clone, Debug)]
pub struct IndexOutOfRangeError;
#[derive(Clone, Debug)]
pub struct Fenwick<
T: Integer + std::clone::Clone + Copy + std::ops::AddAssign + std::ops::SubAssign,
> {
tree: Vec<T>,
}
impl<T: Integer + std::clone::Clone + Copy + std::ops::AddAssign + std::ops::SubAssign> Fenwick<T> {
pub fn with_size(n: usize) -> Self {
Self {
tree: vec![T::zero(); n + 1],
}
}
pub fn from_values(values: &[T]) -> Self {
let mut tree = vec![T::zero()];
tree.extend_from_slice(values);
for index in 1..tree.len() {
let parent_index = index + Self::largest_power_of_two_divisor(index);
if parent_index < tree.len() {
let parent_value = tree[index];
tree[parent_index] += parent_value;
}
}
Self { tree }
}
pub fn len(&self) -> usize {
self.tree.len() - 1
}
pub fn is_empty(&self) -> bool {
self.len() == 0
}
pub fn rank(&self, index: usize) -> Option<T> {
if index >= self.len() {
return None;
}
let mut index = index + 1;
let mut sum = T::zero();
while index > 0 {
sum += self.tree[index];
index -= Self::largest_power_of_two_divisor(index);
}
Some(sum)
}
pub fn update(&mut self, index: usize, value: T) -> Result<(), IndexOutOfRangeError> {
if index >= self.len() {
return Err(IndexOutOfRangeError);
}
let mut index = index + 1;
while index < self.tree.len() {
self.tree[index] += value;
index += Self::largest_power_of_two_divisor(index);
}
Ok(())
}
fn largest_power_of_two_divisor(n: usize) -> usize {
n & n.wrapping_neg()
}
pub fn range(&self, i: usize, j: usize) -> T {
if i >= j {
return T::zero();
}
let mut sum = T::zero();
let mut j = j + 1;
while j > i {
sum += self.tree[j];
j -= Self::largest_power_of_two_divisor(j);
}
let mut i = i + 1;
while i > j {
sum -= self.tree[i];
i -= Self::largest_power_of_two_divisor(i);
}
sum
}
pub fn slow_range(&self, i: usize, j: usize) -> T {
if i > j {
return T::zero();
}
self.rank(j).unwrap() - self.rank(i).unwrap()
}
pub fn select(&self, mut value: T) -> Option<usize> {
let mut index = 0;
let mut step = crate::math::prev_power_of_two(self.len());
while step > 0 {
if index + step < self.tree.len() && self.tree[index + step] <= value {
value -= self.tree[index + step];
index += step;
}
step >>= 1;
}
if index == 0 {
return None;
}
Some(index - 1)
}
}
#[cfg(test)]
mod tests {
use super::Fenwick;
#[test]
fn empty_tree() {
let fenwick = Fenwick::with_size(0);
assert_eq!(fenwick.rank(0), None);
assert_eq!(fenwick.select(0), None);
assert_eq!(fenwick.range(0, 0), 0);
}
#[test]
fn piecemeal_construction1() {
let mut fenwick = Fenwick::with_size(30);
fenwick.update(0, 10).unwrap();
assert_eq!(fenwick.rank(0).unwrap(), 10);
assert_eq!(fenwick.rank(1).unwrap(), 10);
}
#[test]
fn piecemeal_construction2() {
let input = [1, 2, 3, 4];
let result = [1, 3, 6, 10];
let mut fenwick = Fenwick::with_size(4);
for (index, value) in input.into_iter().enumerate() {
assert!(fenwick.update(index, value).is_ok());
}
assert_eq!(fenwick.len(), 4);
(0..input.len()).for_each(|i| {
assert_eq!(result[i], fenwick.rank(i).unwrap());
});
}
#[test]
fn bulk_construction1() {
let input = [1, 2, 3, 4];
let result = [1, 3, 6, 10];
let fenwick = Fenwick::from_values(&input);
assert_eq!(fenwick.len(), 4);
(0..input.len()).for_each(|i| {
assert_eq!(result[i], fenwick.rank(i).unwrap());
});
}
#[test]
fn bulk_piecemeal_same() {
let input = [19, 3, 27, 28, 263, 3897, -4, 27];
let mut fenwick1 = Fenwick::with_size(input.len());
(0..input.len()).for_each(|i| {
assert!(fenwick1.update(i, input[i]).is_ok());
});
let fenwick1 = fenwick1;
let fenwick2 = Fenwick::from_values(&input);
assert_eq!(fenwick1.len(), fenwick2.len());
(0..input.len()).for_each(|i| {
assert_eq!(fenwick1.rank(i), fenwick2.rank(i));
});
}
#[test]
fn is_empty() {
let fenwick = Fenwick::<u8>::with_size(0);
assert!(fenwick.is_empty());
let fenwick = Fenwick::from_values(&[0, 1, 4]);
assert!(!fenwick.is_empty());
}
#[test]
fn update_out_of_bounds() {
let mut fenwick = Fenwick::from_values(&[0, 1, 4]);
assert!(fenwick.update(0, 100).is_ok());
assert!(fenwick.update(3, 100).is_err());
}
#[test]
fn range_test() {
let input = [19, 3, 27, 28, 263, 3897, -4, 27];
let fenwick = Fenwick::from_values(&input);
for i in 0..input.len() {
for j in i..input.len() {
assert_eq!(fenwick.slow_range(i, j), fenwick.range(i, j));
}
}
}
#[test]
fn range_i_larger_than_j() {
let input = [19, 3, 27, 28, 263, 3897, -4, 27];
let fenwick = Fenwick::from_values(&input);
for i in 0..input.len() {
for j in 0..i {
assert_eq!(fenwick.slow_range(i, j), fenwick.range(i, j));
}
}
}
#[test]
fn rank() {
struct TestCase {
value: i32,
expected_index: Option<usize>,
expected_value: Option<i32>,
}
let input = [19, 3, 27, 28, 263, 3897, 4, 27];
let fenwick = Fenwick::from_values(&input);
let test_cases = [
TestCase {
value: 19,
expected_index: Some(0),
expected_value: Some(19),
},
TestCase {
value: 18,
expected_index: None,
expected_value: None,
},
TestCase {
value: 4233,
expected_index: Some(4),
expected_value: Some(340),
},
TestCase {
value: 4237,
expected_index: Some(5),
expected_value: Some(4237),
},
TestCase {
value: 4268,
expected_index: Some(7),
expected_value: Some(4268),
},
TestCase {
value: 5000,
expected_index: Some(7),
expected_value: Some(4268),
},
];
for test_case in test_cases {
let index = fenwick.select(test_case.value);
assert_eq!(test_case.expected_index, index);
if let Some(index) = index {
let value = fenwick.rank(index);
assert_eq!(value, test_case.expected_value);
} else {
assert!(test_case.expected_value.is_none());
}
}
}
}