pub trait SemiRing {
type T: Clone;
type Additive: AbelianMonoid<T = Self::T>;
type Multiplicative: Monoid<T = Self::T>;
// Provided methods
fn zero() -> Self::T { ... }
fn one() -> Self::T { ... }
fn add(x: &Self::T, y: &Self::T) -> Self::T { ... }
fn mul(x: &Self::T, y: &Self::T) -> Self::T { ... }
fn add_assign(x: &mut Self::T, y: &Self::T) { ... }
fn mul_assign(x: &mut Self::T, y: &Self::T) { ... }
}
Required Associated Types§
type T: Clone
type Additive: AbelianMonoid<T = Self::T>
type Multiplicative: Monoid<T = Self::T>
Provided Methods§
Sourcefn zero() -> Self::T
fn zero() -> Self::T
additive identity: $0$
Examples found in repository?
More examples
crates/competitive/src/math/floor_sum.rs (line 125)
124 fn to_x() -> FloorSumData<R, X, Y> {
125 let mut dp = array![array![R::zero(); Y]; X];
126 dp[0][0] = R::one();
127 FloorSumData {
128 dp,
129 dx: R::one(),
130 dy: R::zero(),
131 _marker: PhantomData,
132 }
133 }
134 fn to_y() -> FloorSumData<R, X, Y> {
135 FloorSumData {
136 dp: array![array![R::zero(); Y]; X],
137 dx: R::zero(),
138 dy: R::one(),
139 _marker: PhantomData,
140 }
141 }
142}
143
144impl<R, const X: usize, const Y: usize> FloorSum<R, X, Y>
145where
146 R: Ring,
147 R::Additive: Invertible,
148{
149 fn offset(x: i64, y: i64) -> FloorSumData<R, X, Y> {
150 FloorSumData {
151 dp: array![array![R::zero(); Y]; X],
152 dx: R::Additive::signed_pow(R::one(), x),
153 dy: R::Additive::signed_pow(R::one(), y),
154 _marker: PhantomData,
155 }
156 }
157}
158
159impl<R, const X: usize, const Y: usize> Magma for FloorSum<R, X, Y>
160where
161 R: SemiRing,
162{
163 type T = FloorSumData<R, X, Y>;
164
165 fn operate(a: &Self::T, b: &Self::T) -> Self::T {
166 let mut a = a.clone();
167 let mut b = b.clone();
168 let mut pow_x = array![R::zero(); X];
169 let mut pow_y = array![R::zero(); Y];
170 pow_x[0] = R::one();
171 pow_y[0] = R::one();
172 for i in 1..X {
173 pow_x[i] = R::mul(&pow_x[i - 1], &a.dx);
174 }
175 for j in 1..Y {
176 pow_y[j] = R::mul(&pow_y[j - 1], &a.dy);
177 }
178 macro_rules! go {
179 ($N:ident) => {
180 let mut comb = array![array![R::zero(); $N]; $N];
181 comb[0][0] = R::one();
182 let mut i = 0;
183 while i + 1 < $N {
184 let mut j = 0;
185 while j <= i {
186 let x = comb[i][j].clone();
187 R::add_assign(&mut comb[i + 1][j], &x);
188 R::add_assign(&mut comb[i + 1][j + 1], &x);
189 j += 1;
190 }
191 i += 1;
192 }
193 for i in 0..X {
194 for j in (0..Y).rev() {
195 for k in j + 1..Y {
196 let mut x = b.dp[i][j].clone();
197 R::mul_assign(&mut x, &comb[k][j]);
198 R::mul_assign(&mut x, &pow_y[k - j]);
199 R::add_assign(&mut b.dp[i][k], &x);
200 }
201 }
202 }
203 for j in 0..Y {
204 for i in (0..X).rev() {
205 for k in i..X {
206 let mut x = b.dp[i][j].clone();
207 R::mul_assign(&mut x, &comb[k][i]);
208 R::mul_assign(&mut x, &pow_x[k - i]);
209 R::add_assign(&mut a.dp[k][j], &x);
210 }
211 }
212 }
213 };
214 }
215 if X <= Y {
216 go!(Y);
217 } else {
218 go!(X);
219 }
220 R::add_assign(&mut a.dx, &b.dx);
221 R::add_assign(&mut a.dy, &b.dy);
222 a
223 }
224}
225
226impl<R, const X: usize, const Y: usize> Unital for FloorSum<R, X, Y>
227where
228 R: SemiRing,
229{
230 fn unit() -> Self::T {
231 FloorSumData {
232 dp: array![array![R::zero(); Y]; X],
233 dx: R::zero(),
234 dy: R::zero(),
235 _marker: PhantomData,
236 }
237 }
crates/competitive/src/math/subset_convolve.rs (line 23)
21 fn transform(t: Self::T, len: usize) -> Self::F {
22 let k = len.trailing_zeros() as usize;
23 let mut f = vec![vec![R::zero(); len]; k + 1];
24 for (i, t) in t.iter().enumerate() {
25 let f = &mut f[i.count_ones() as usize][i];
26 *f = R::add(f, t);
27 }
28 for f in f.iter_mut() {
29 BitwiseorConvolve::<R::Additive>::zeta_transform(f);
30 }
31 f
32 }
33
34 fn inverse_transform(mut f: Self::F, len: usize) -> Self::T {
35 for f in f.iter_mut() {
36 BitwiseorConvolve::<R::Additive>::mobius_transform(f);
37 }
38 let mut t = vec![R::zero(); len];
39 for (i, t) in t.iter_mut().enumerate() {
40 *t = R::add(t, &f[i.count_ones() as usize][i]);
41 }
42 t
43 }
Sourcefn one() -> Self::T
fn one() -> Self::T
multiplicative identity: $1$
Examples found in repository?
More examples
crates/competitive/src/string/rolling_hash.rs (line 508)
505 fn new(base: R::T) -> Self {
506 Self {
507 base,
508 pow: vec![R::one()],
509 }
510 }
511 fn ensure_pow(&mut self, len: usize) {
512 if self.pow.len() <= len {
513 self.pow.reserve(len - self.pow.len() + 1);
514 if self.pow.is_empty() {
515 self.pow.push(R::one());
516 }
517 for _ in 0..=len - self.pow.len() {
518 self.pow.push(R::mul(self.pow.last().unwrap(), &self.base));
519 }
520 }
521 }
crates/competitive/src/math/floor_sum.rs (line 126)
124 fn to_x() -> FloorSumData<R, X, Y> {
125 let mut dp = array![array![R::zero(); Y]; X];
126 dp[0][0] = R::one();
127 FloorSumData {
128 dp,
129 dx: R::one(),
130 dy: R::zero(),
131 _marker: PhantomData,
132 }
133 }
134 fn to_y() -> FloorSumData<R, X, Y> {
135 FloorSumData {
136 dp: array![array![R::zero(); Y]; X],
137 dx: R::zero(),
138 dy: R::one(),
139 _marker: PhantomData,
140 }
141 }
142}
143
144impl<R, const X: usize, const Y: usize> FloorSum<R, X, Y>
145where
146 R: Ring,
147 R::Additive: Invertible,
148{
149 fn offset(x: i64, y: i64) -> FloorSumData<R, X, Y> {
150 FloorSumData {
151 dp: array![array![R::zero(); Y]; X],
152 dx: R::Additive::signed_pow(R::one(), x),
153 dy: R::Additive::signed_pow(R::one(), y),
154 _marker: PhantomData,
155 }
156 }
157}
158
159impl<R, const X: usize, const Y: usize> Magma for FloorSum<R, X, Y>
160where
161 R: SemiRing,
162{
163 type T = FloorSumData<R, X, Y>;
164
165 fn operate(a: &Self::T, b: &Self::T) -> Self::T {
166 let mut a = a.clone();
167 let mut b = b.clone();
168 let mut pow_x = array![R::zero(); X];
169 let mut pow_y = array![R::zero(); Y];
170 pow_x[0] = R::one();
171 pow_y[0] = R::one();
172 for i in 1..X {
173 pow_x[i] = R::mul(&pow_x[i - 1], &a.dx);
174 }
175 for j in 1..Y {
176 pow_y[j] = R::mul(&pow_y[j - 1], &a.dy);
177 }
178 macro_rules! go {
179 ($N:ident) => {
180 let mut comb = array![array![R::zero(); $N]; $N];
181 comb[0][0] = R::one();
182 let mut i = 0;
183 while i + 1 < $N {
184 let mut j = 0;
185 while j <= i {
186 let x = comb[i][j].clone();
187 R::add_assign(&mut comb[i + 1][j], &x);
188 R::add_assign(&mut comb[i + 1][j + 1], &x);
189 j += 1;
190 }
191 i += 1;
192 }
193 for i in 0..X {
194 for j in (0..Y).rev() {
195 for k in j + 1..Y {
196 let mut x = b.dp[i][j].clone();
197 R::mul_assign(&mut x, &comb[k][j]);
198 R::mul_assign(&mut x, &pow_y[k - j]);
199 R::add_assign(&mut b.dp[i][k], &x);
200 }
201 }
202 }
203 for j in 0..Y {
204 for i in (0..X).rev() {
205 for k in i..X {
206 let mut x = b.dp[i][j].clone();
207 R::mul_assign(&mut x, &comb[k][i]);
208 R::mul_assign(&mut x, &pow_x[k - i]);
209 R::add_assign(&mut a.dp[k][j], &x);
210 }
211 }
212 }
213 };
214 }
215 if X <= Y {
216 go!(Y);
217 } else {
218 go!(X);
219 }
220 R::add_assign(&mut a.dx, &b.dx);
221 R::add_assign(&mut a.dy, &b.dy);
222 a
223 }
Sourcefn add(x: &Self::T, y: &Self::T) -> Self::T
fn add(x: &Self::T, y: &Self::T) -> Self::T
additive operaion: $+$
Examples found in repository?
More examples
crates/competitive/src/graph/shortest_path.rs (line 101)
98 fn add_assign(x: &mut Self::T, y: &Self::T) -> bool {
99 match x.0.cmp(&y.0) {
100 Ordering::Equal => {
101 x.1 = S::add(&x.1, &y.1);
102 false
103 }
104 Ordering::Greater => {
105 *x = y.clone();
106 true
107 }
108 _ => false,
109 }
110 }
crates/competitive/src/math/subset_convolve.rs (line 26)
21 fn transform(t: Self::T, len: usize) -> Self::F {
22 let k = len.trailing_zeros() as usize;
23 let mut f = vec![vec![R::zero(); len]; k + 1];
24 for (i, t) in t.iter().enumerate() {
25 let f = &mut f[i.count_ones() as usize][i];
26 *f = R::add(f, t);
27 }
28 for f in f.iter_mut() {
29 BitwiseorConvolve::<R::Additive>::zeta_transform(f);
30 }
31 f
32 }
33
34 fn inverse_transform(mut f: Self::F, len: usize) -> Self::T {
35 for f in f.iter_mut() {
36 BitwiseorConvolve::<R::Additive>::mobius_transform(f);
37 }
38 let mut t = vec![R::zero(); len];
39 for (i, t) in t.iter_mut().enumerate() {
40 *t = R::add(t, &f[i.count_ones() as usize][i]);
41 }
42 t
43 }
44
45 fn multiply(f: &mut Self::F, g: &Self::F) {
46 for i in (0..f.len()).rev() {
47 let (lf, rf) = f.split_at_mut(i);
48 for (x, y) in rf[0].iter_mut().zip(&g[0]) {
49 *x = R::mul(x, y);
50 }
51 for (x, y) in lf.iter().rev().zip(g.iter().skip(1)) {
52 for ((x, y), z) in x.iter().zip(y).zip(&mut rf[0]) {
53 *z = R::add(z, &R::mul(x, y));
54 }
55 }
56 }
57 }
crates/competitive/src/math/quotient_array.rs (line 100)
82 pub fn min_25_sieve<R>(&self, mut f: impl FnMut(u64, u32) -> T) -> Self
83 where
84 T: Clone + One,
85 R: Ring<T = T>,
86 R::Additive: Invertible,
87 {
88 let mut dp = self.clone();
89 with_prime_list(self.isqrtn, |pl| {
90 for &p in pl.primes_lte(self.isqrtn).iter().rev() {
91 let k = self.quotient_index(p);
92 for (i, q) in Self::index_iter(self.n, self.isqrtn).enumerate() {
93 let mut pc = p;
94 if pc * p > q {
95 break;
96 }
97 let mut c = 1;
98 while q / p >= pc {
99 let x = R::mul(&f(p, c), &(R::sub(&dp[q / pc], &self.data[k])));
100 let x = R::add(&x, &f(p, c + 1));
101 dp.data[i] = R::add(&dp.data[i], &x);
102 c += 1;
103 pc *= p;
104 }
105 }
106 }
107 });
108 for x in &mut dp.data {
109 *x = R::add(x, &T::one());
110 }
111 dp
112 }
Sourcefn mul(x: &Self::T, y: &Self::T) -> Self::T
fn mul(x: &Self::T, y: &Self::T) -> Self::T
multiplicative operaion: $+$
Examples found in repository?
More examples
crates/competitive/src/math/bitwiseand_convolve.rs (line 53)
51 fn multiply(f: &mut Self::F, g: &Self::F) {
52 for (f, g) in f.iter_mut().zip(g) {
53 *f = R::mul(f, g);
54 }
55 }
56
57 fn convolve(a: Self::T, b: Self::T) -> Self::T {
58 assert_eq!(a.len(), b.len());
59 let len = a.len();
60 let same = a == b;
61 let mut a = Self::transform(a, len);
62 if same {
63 for a in a.iter_mut() {
64 *a = R::mul(a, a);
65 }
66 } else {
67 let b = Self::transform(b, len);
68 Self::multiply(&mut a, &b);
69 }
70 Self::inverse_transform(a, len)
71 }
crates/competitive/src/math/bitwiseor_convolve.rs (line 53)
51 fn multiply(f: &mut Self::F, g: &Self::F) {
52 for (f, g) in f.iter_mut().zip(g) {
53 *f = R::mul(f, g);
54 }
55 }
56
57 fn convolve(a: Self::T, b: Self::T) -> Self::T {
58 assert_eq!(a.len(), b.len());
59 let len = a.len();
60 let same = a == b;
61 let mut a = Self::transform(a, len);
62 if same {
63 for a in a.iter_mut() {
64 *a = R::mul(a, a);
65 }
66 } else {
67 let b = Self::transform(b, len);
68 Self::multiply(&mut a, &b);
69 }
70 Self::inverse_transform(a, len)
71 }
crates/competitive/src/math/bitwisexor_convolve.rs (line 52)
50 fn multiply(f: &mut Self::F, g: &Self::F) {
51 for (f, g) in f.iter_mut().zip(g) {
52 *f = R::mul(f, g);
53 }
54 }
55
56 fn convolve(a: Self::T, b: Self::T) -> Self::T {
57 assert_eq!(a.len(), b.len());
58 let len = a.len();
59 let same = a == b;
60 let mut a = Self::transform(a, len);
61 if same {
62 for a in a.iter_mut() {
63 *a = R::mul(a, a);
64 }
65 } else {
66 let b = Self::transform(b, len);
67 Self::multiply(&mut a, &b);
68 }
69 Self::inverse_transform(a, len)
70 }
71}
72
73impl<R> ConvolveSteps for BitwisexorConvolve<R, true>
74where
75 R: Field,
76 R::T: PartialEq,
77 R::Additive: Invertible,
78 R::Multiplicative: Invertible,
79 R::T: TryFrom<usize>,
80 <R::T as TryFrom<usize>>::Error: Debug,
81{
82 type T = Vec<R::T>;
83 type F = Vec<R::T>;
84
85 fn length(t: &Self::T) -> usize {
86 t.len()
87 }
88
89 fn transform(mut t: Self::T, _len: usize) -> Self::F {
90 BitwisexorConvolve::<R::Additive, true>::hadamard_transform(&mut t);
91 t
92 }
93
94 fn inverse_transform(mut f: Self::F, len: usize) -> Self::T {
95 BitwisexorConvolve::<R::Additive, true>::hadamard_transform(&mut f);
96 let len = R::T::try_from(len).unwrap();
97 for f in f.iter_mut() {
98 *f = R::div(f, &len);
99 }
100 f
101 }
102
103 fn multiply(f: &mut Self::F, g: &Self::F) {
104 for (f, g) in f.iter_mut().zip(g) {
105 *f = R::mul(f, g);
106 }
107 }
108
109 fn convolve(a: Self::T, b: Self::T) -> Self::T {
110 assert_eq!(a.len(), b.len());
111 let len = a.len();
112 let same = a == b;
113 let mut a = Self::transform(a, len);
114 if same {
115 for a in a.iter_mut() {
116 *a = R::mul(a, a);
117 }
118 } else {
119 let b = Self::transform(b, len);
120 Self::multiply(&mut a, &b);
121 }
122 Self::inverse_transform(a, len)
123 }
Sourcefn add_assign(x: &mut Self::T, y: &Self::T)
fn add_assign(x: &mut Self::T, y: &Self::T)
Examples found in repository?
crates/competitive/src/math/floor_sum.rs (line 220)
165 fn operate(a: &Self::T, b: &Self::T) -> Self::T {
166 let mut a = a.clone();
167 let mut b = b.clone();
168 let mut pow_x = array![R::zero(); X];
169 let mut pow_y = array![R::zero(); Y];
170 pow_x[0] = R::one();
171 pow_y[0] = R::one();
172 for i in 1..X {
173 pow_x[i] = R::mul(&pow_x[i - 1], &a.dx);
174 }
175 for j in 1..Y {
176 pow_y[j] = R::mul(&pow_y[j - 1], &a.dy);
177 }
178 macro_rules! go {
179 ($N:ident) => {
180 let mut comb = array![array![R::zero(); $N]; $N];
181 comb[0][0] = R::one();
182 let mut i = 0;
183 while i + 1 < $N {
184 let mut j = 0;
185 while j <= i {
186 let x = comb[i][j].clone();
187 R::add_assign(&mut comb[i + 1][j], &x);
188 R::add_assign(&mut comb[i + 1][j + 1], &x);
189 j += 1;
190 }
191 i += 1;
192 }
193 for i in 0..X {
194 for j in (0..Y).rev() {
195 for k in j + 1..Y {
196 let mut x = b.dp[i][j].clone();
197 R::mul_assign(&mut x, &comb[k][j]);
198 R::mul_assign(&mut x, &pow_y[k - j]);
199 R::add_assign(&mut b.dp[i][k], &x);
200 }
201 }
202 }
203 for j in 0..Y {
204 for i in (0..X).rev() {
205 for k in i..X {
206 let mut x = b.dp[i][j].clone();
207 R::mul_assign(&mut x, &comb[k][i]);
208 R::mul_assign(&mut x, &pow_x[k - i]);
209 R::add_assign(&mut a.dp[k][j], &x);
210 }
211 }
212 }
213 };
214 }
215 if X <= Y {
216 go!(Y);
217 } else {
218 go!(X);
219 }
220 R::add_assign(&mut a.dx, &b.dx);
221 R::add_assign(&mut a.dy, &b.dy);
222 a
223 }
fn mul_assign(x: &mut Self::T, y: &Self::T)
Dyn Compatibility§
This trait is not dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.