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
27 changes: 15 additions & 12 deletions src/fenwicktree.rs
Original file line number Diff line number Diff line change
@@ -1,37 +1,40 @@
use std::ops::{Bound, RangeBounds};
use std::{
iter::repeat_with,
ops::{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 Author

Choose a reason for hiding this comment

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

I don't think requiring using Default is not always a good idea because the semantics are different. Zero traits is clearly for the "additive identity", while Default trait is for a general "default" instance. The latter is not guaranteed to be an additive identity, and that restriction shall be stated in the doc instead of as a type restriction. I prefer type restrictions to other document constraints, and thus thought introducing Zero trait would be reasonable.


// 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: for<'a> std::ops::AddAssign<&'a T> + Zero> FenwickTree<T> {
pub fn new(n: usize) -> Self {
FenwickTree {
n,
ary: vec![e.clone(); n],
e,
ary: repeat_with(T::zero).take(n).collect(),
}
}
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();
sum += &self.ary[idx - 1];
idx &= idx - 1;
}
sum
}
/// performs data[idx] += val;
pub fn add<U: Clone>(&mut self, mut idx: usize, val: U)
pub fn add<U>(&mut self, mut idx: usize, val: U)
where
T: std::ops::AddAssign<U>,
T: for<'a> std::ops::AddAssign<&'a U>,
{
let n = self.n;
idx += 1;
while idx <= n {
self.ary[idx - 1] += val.clone();
self.ary[idx - 1] += &val;
idx += idx & idx.wrapping_neg();
}
}
Expand Down Expand Up @@ -62,7 +65,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 Down
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