Skip to content
Open
2 changes: 1 addition & 1 deletion examples/library-checker-static-range-sum.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ fn main() {
lrs: [(usize, usize); q],
}

let mut fenwick = FenwickTree::new(n, 0);
let mut fenwick = FenwickTree::<u64>::new(n);
for (i, a) in r#as.into_iter().enumerate() {
fenwick.add(i, a);
}
Expand Down
8 changes: 5 additions & 3 deletions expand.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,19 +32,21 @@
output_header = '//https://github.com/rust-lang-ja/ac-library-rs\n'
opt_list = ['help', 'all', 'output=']
output_list_all = ('convolution', 'dsu', 'fenwicktree', 'lazysegtree', 'math',
'maxflow', 'mincostflow', 'modint', 'scc', 'segtree',
'string', 'twosat',
'maxflow', 'mincostflow', 'modint', 'num_traits', 'scc',
'segtree', 'string', 'twosat',
'internal_bit', 'internal_math', 'internal_queue',
'internal_scc', 'internal_type_traits',)
dependency_list = {'convolution': ('internal_bit', 'modint',),
'fenwicktree': ('num_traits',),
'lazysegtree': ('internal_bit', 'segtree'),
'math': ('internal_math',),
'maxflow': ('internal_type_traits', 'internal_queue',),
'mincostflow': ('internal_type_traits',),
'modint': ('internal_math',),
'scc': ('internal_scc',),
'segtree': ('internal_bit', 'internal_type_traits',),
'twosat': ('internal_scc',), }
'twosat': ('internal_scc',),
'internal_type_traits': ('num_traits',), }
src_path = 'src/'
output_path = None

Expand Down
49 changes: 40 additions & 9 deletions src/fenwicktree.rs
Original file line number Diff line number Diff line change
@@ -1,22 +1,25 @@
use std::ops::{Bound, RangeBounds};
use std::{
iter::FromIterator,
ops::{AddAssign, Bound, RangeBounds},
};

use crate::num_traits::Zero;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These appear to be changes that need not specifically rely on #102. Check out the application examples below.

https://github.com/rust-lang-ja/ac-library-rs/compare/7e99fd2941976764b4e7925898fae7cc77890885...mizar:ac-library-rs:4be604494341a86242b77120e5685740dc41791f?expand=1

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the previous example, we used the Default trait, but now #55 makes it easier to use the Zero trait in user-defined structures as well, the need for the num crate may be lessened.

https://github.com/rust-lang-ja/ac-library-rs/compare/7e99fd2941976764b4e7925898fae7cc77890885...mizar:ac-library-rs:58bcfa92df9a75803b454771f8cb447a580a9cba?expand=1

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you rely on internal_type_traits::Zero traits, you will likely need to make this change to check for expand, FYI.
https://github.com/rust-lang-ja/ac-library-rs/compare/7e99fd2941976764b4e7925898fae7cc77890885...mizar:ac-library-rs:fd6bf7f453113c2b1ef5c7dd81c0955de2836cbd?expand=1


// Reference: https://en.wikipedia.org/wiki/Fenwick_tree
pub struct FenwickTree<T> {
n: usize,
ary: Vec<T>,
e: T,
}

impl<T: Clone + std::ops::AddAssign<T>> FenwickTree<T> {
pub fn new(n: usize, e: T) -> Self {
impl<T: Clone + AddAssign<T> + Zero> FenwickTree<T> {
pub fn new(n: usize) -> Self {
FenwickTree {
n,
ary: vec![e.clone(); n],
e,
ary: vec![T::zero(); n],
}
}
pub fn accum(&self, mut idx: usize) -> T {
let mut sum = self.e.clone();
let mut sum = T::zero();
while idx > 0 {
sum += self.ary[idx - 1].clone();
idx &= idx - 1;
Expand All @@ -26,7 +29,7 @@ impl<T: Clone + std::ops::AddAssign<T>> FenwickTree<T> {
/// performs data[idx] += val;
pub fn add<U: Clone>(&mut self, mut idx: usize, val: U)
where
T: std::ops::AddAssign<U>,
T: AddAssign<U>,
{
let n = self.n;
idx += 1;
Expand Down Expand Up @@ -54,6 +57,23 @@ impl<T: Clone + std::ops::AddAssign<T>> FenwickTree<T> {
self.accum(r) - self.accum(l)
}
}
impl<T: Clone + AddAssign<T>> From<Vec<T>> for FenwickTree<T> {
fn from(mut ary: Vec<T>) -> Self {
for i in 1..=ary.len() {
let j = i + (i & i.wrapping_neg());
if j <= ary.len() {
let add = ary[i - 1].clone();
ary[j - 1] += add;
}
}
Self { n: ary.len(), ary }
}
}
impl<T: Clone + AddAssign<T>> FromIterator<T> for FenwickTree<T> {
fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
iter.into_iter().collect::<Vec<_>>().into()
}
}

#[cfg(test)]
mod tests {
Expand All @@ -62,7 +82,7 @@ mod tests {

#[test]
fn fenwick_tree_works() {
let mut bit = FenwickTree::new(5, 0i64);
let mut bit = FenwickTree::<i64>::new(5);
// [1, 2, 3, 4, 5]
for i in 0..5 {
bit.add(i, i as i64 + 1);
Expand All @@ -78,4 +98,15 @@ mod tests {
assert_eq!(bit.sum(1..=3), 9);
assert_eq!(bit.sum((Excluded(0), Included(2))), 5);
}

#[test]
fn from_iter_works() {
let tree = FenwickTree::from_iter(vec![1, 2, 3, 4, 5].iter().map(|x| x * 2));
let internal = vec![2, 4, 6, 8, 10];
for j in 0..=internal.len() {
for i in 0..=j {
assert_eq!(tree.sum(i..j), internal[i..j].iter().sum::<i32>());
}
}
}
}
30 changes: 2 additions & 28 deletions src/internal_type_traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,25 +52,13 @@ pub trait Integral:
+ fmt::Debug
+ fmt::Binary
+ fmt::Octal
+ Zero
+ One
+ crate::num_traits::Zero
+ crate::num_traits::One
+ BoundedBelow
+ BoundedAbove
{
}

/// Class that has additive identity element
pub trait Zero {
/// The additive identity element
fn zero() -> Self;
}

/// Class that has multiplicative identity element
pub trait One {
/// The multiplicative identity element
fn one() -> Self;
}

pub trait BoundedBelow {
fn min_value() -> Self;
}
Expand All @@ -82,20 +70,6 @@ pub trait BoundedAbove {
macro_rules! impl_integral {
($($ty:ty),*) => {
$(
impl Zero for $ty {
#[inline]
fn zero() -> Self {
0
}
}

impl One for $ty {
#[inline]
fn one() -> Self {
1
}
}

impl BoundedBelow for $ty {
#[inline]
fn min_value() -> Self {
Expand Down
2 changes: 2 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ pub mod segtree;
pub mod string;
pub mod twosat;

pub mod num_traits;

mod internal_bit;
mod internal_math;
mod internal_queue;
Expand Down
43 changes: 43 additions & 0 deletions src/num_traits.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/// A type that has an additive identity element.
pub trait Zero {
/// The additive identity element.
fn zero() -> Self;
}

/// A type that has a multiplicative identity element.
pub trait One {
/// The multiplicative identity element.
fn one() -> Self;
}

macro_rules! impl_zero {
($zero: literal, $one: literal: $($t: ty),*) => {
$(
impl Zero for $t {
fn zero() -> Self {
$zero
}
}

impl One for $t {
fn one() -> Self {
$one
}
}
)*
};
}
impl_zero!(0, 1: usize, u8, u16, u32, u64, u128);
impl_zero!(0, 1: isize, i8, i16, i32, i64, i128);
impl_zero!(0.0, 1.0: f32, f64);

impl<T: Zero> Zero for core::num::Wrapping<T> {
fn zero() -> Self {
Self(T::zero())
}
}
impl<T: One> One for core::num::Wrapping<T> {
fn one() -> Self {
Self(T::one())
}
}
3 changes: 2 additions & 1 deletion src/segtree.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use crate::internal_bit::ceil_pow2;
use crate::internal_type_traits::{BoundedAbove, BoundedBelow, One, Zero};
use crate::internal_type_traits::{BoundedAbove, BoundedBelow};
use crate::num_traits::{One, Zero};
use std::cmp::{max, min};
use std::convert::Infallible;
use std::marker::PhantomData;
Expand Down