diff --git a/.cargo/config.toml b/.cargo/config.toml deleted file mode 100644 index 3d99f63..0000000 --- a/.cargo/config.toml +++ /dev/null @@ -1,8 +0,0 @@ -[build] -# This works both on local `cargo doc` and on docs.rs because we don't have any `normal` dependency. -# In most cases, `package.metadata.docs.rs` is recommended. -# -# See also: -# - https://docs.rs/rustdoc-katex-demo -# - https://docs.rs/rust-latex-doc-minimal-example -rustdocflags = ["--html-in-header", "./doc/katex-header.html"] diff --git a/Cargo.toml b/Cargo.toml index c630983..70ff13a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,6 +10,7 @@ keywords = ["competitive"] categories = ["algorithms", "data-structures"] [package.metadata.docs.rs] +all-features = true rustdoc-args = ["--html-in-header", "./doc/katex-header.html"] [lib] @@ -18,6 +19,7 @@ name = "ac_library" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +num-traits = { version = "0.2.15", optional = true } [dev-dependencies] proconio = "=0.3.6" diff --git a/examples/library-checker-static-range-sum.rs b/examples/library-checker-static-range-sum.rs index 4c5cc03..54ee5bc 100644 --- a/examples/library-checker-static-range-sum.rs +++ b/examples/library-checker-static-range-sum.rs @@ -15,7 +15,7 @@ fn main() { lrs: [(usize, usize); q], } - let mut fenwick = FenwickTree::new(n, 0); + let mut fenwick = FenwickTree::::new(n); for (i, a) in r#as.into_iter().enumerate() { fenwick.add(i, a); } diff --git a/expand.py b/expand.py index 283d6fb..57c6789 100755 --- a/expand.py +++ b/expand.py @@ -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',), + 'modint': ('internal_math', 'num_traits',), '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 diff --git a/src/fenwicktree.rs b/src/fenwicktree.rs index cfcf32a..87b1850 100644 --- a/src/fenwicktree.rs +++ b/src/fenwicktree.rs @@ -1,22 +1,22 @@ use std::ops::{Bound, RangeBounds}; +use crate::num_traits::Zero; + // Reference: https://en.wikipedia.org/wiki/Fenwick_tree pub struct FenwickTree { n: usize, ary: Vec, - e: T, } -impl> FenwickTree { - pub fn new(n: usize, e: T) -> Self { +impl + Zero> FenwickTree { + 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; @@ -62,7 +62,7 @@ mod tests { #[test] fn fenwick_tree_works() { - let mut bit = FenwickTree::new(5, 0i64); + let mut bit = FenwickTree::::new(5); // [1, 2, 3, 4, 5] for i in 0..5 { bit.add(i, i as i64 + 1); diff --git a/src/internal_type_traits.rs b/src/internal_type_traits.rs index 88a52a9..9b00aec 100644 --- a/src/internal_type_traits.rs +++ b/src/internal_type_traits.rs @@ -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; } @@ -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 { diff --git a/src/lib.rs b/src/lib.rs index 09cc26f..1a8deb4 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -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; diff --git a/src/modint.rs b/src/modint.rs index 022263c..288021a 100644 --- a/src/modint.rs +++ b/src/modint.rs @@ -898,6 +898,55 @@ macro_rules! impl_basic_traits { } } + #[cfg(feature = "num-traits")] + impl<$generic_param: $generic_param_bound> num_traits::Zero for $self { + #[inline] + fn zero() -> Self { + Self::new(0) + } + #[inline] + fn is_zero(&self) -> bool { + self == &Self::zero() + } + } + + #[cfg(not(feature = "num-traits"))] + impl<$generic_param: $generic_param_bound> $crate::num_traits::Zero for $self { + #[inline] + fn zero() -> Self { + Self::new(0) + } + } + + #[cfg(feature = "num-traits")] + impl<$generic_param: $generic_param_bound> num_traits::One for $self { + #[inline] + fn one() -> Self { + Self::new(1) + } + #[inline] + fn is_one(&self) -> bool { + self == &Self::one() + } + } + + #[cfg(not(feature = "num-traits"))] + impl<$generic_param: $generic_param_bound> $crate::num_traits::One for $self { + #[inline] + fn one() -> Self { + Self::new(1) + } + } + + #[cfg(feature = "num-traits")] + impl<$generic_param: $generic_param_bound> num_traits::Pow for $self { + type Output=$self; + #[inline] + fn pow(self, rhs: u64) -> Self::Output { + self.pow(rhs) + } + } + impl_basic_traits!($($rest)*); }; } diff --git a/src/num_traits.rs b/src/num_traits.rs new file mode 100644 index 0000000..36d3b56 --- /dev/null +++ b/src/num_traits.rs @@ -0,0 +1,59 @@ +/// A type that has an additive identity element. +pub trait Zero { + /// The additive identity element. + fn zero() -> Self; +} +#[cfg(feature = "num-traits")] +impl Zero for T { + fn zero() -> Self { + num_traits::Zero::zero() + } +} + +/// A type that has a multiplicative identity element. +pub trait One { + /// The multiplicative identity element. + fn one() -> Self; +} +#[cfg(feature = "num-traits")] +impl One for T { + fn one() -> Self { + num_traits::One::one() + } +} + +macro_rules! impl_zero { + ($zero: literal, $one: literal: $($t: ty),*) => { + $( + #[cfg(not(feature="num-traits"))] + impl Zero for $t { + fn zero() -> Self { + $zero + } + } + + #[cfg(not(feature="num-traits"))] + 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); + +#[cfg(not(feature = "num-traits"))] +impl Zero for core::num::Wrapping { + fn zero() -> Self { + Self(T::zero()) + } +} +#[cfg(not(feature = "num-traits"))] +impl One for core::num::Wrapping { + fn one() -> Self { + Self(T::one()) + } +} diff --git a/src/segtree.rs b/src/segtree.rs index 573b9ff..90b0037 100644 --- a/src/segtree.rs +++ b/src/segtree.rs @@ -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;