competitive/math/
bitwiseor_convolve.rs1use super::{ConvolveSteps, Group, Invertible, Monoid, Ring, bitwise_transform};
2use std::marker::PhantomData;
3
4pub struct BitwiseorConvolve<M> {
5 _marker: PhantomData<fn() -> M>,
6}
7
8impl<M> BitwiseorConvolve<M>
9where
10 M: Monoid,
11{
12 pub fn zeta_transform(f: &mut [M::T]) {
14 bitwise_transform(f, |y, x| *x = M::operate(x, y));
15 }
16}
17
18impl<G> BitwiseorConvolve<G>
19where
20 G: Group,
21{
22 pub fn mobius_transform(f: &mut [G::T]) {
24 bitwise_transform(f, |y, x| *x = G::rinv_operate(x, y));
25 }
26}
27
28impl<R> ConvolveSteps for BitwiseorConvolve<R>
29where
30 R: Ring,
31 R::T: PartialEq,
32 R::Additive: Invertible,
33{
34 type T = Vec<R::T>;
35 type F = Vec<R::T>;
36
37 fn length(t: &Self::T) -> usize {
38 t.len()
39 }
40
41 fn transform(mut t: Self::T, _len: usize) -> Self::F {
42 BitwiseorConvolve::<R::Additive>::zeta_transform(&mut t);
43 t
44 }
45
46 fn inverse_transform(mut f: Self::F, _len: usize) -> Self::T {
47 BitwiseorConvolve::<R::Additive>::mobius_transform(&mut f);
48 f
49 }
50
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 }
72}
73
74#[cfg(test)]
75mod tests {
76 use super::*;
77 use crate::{
78 algebra::{AddMulOperation, AdditiveOperation},
79 rand,
80 tools::Xorshift,
81 };
82
83 const A: i64 = 100_000;
84
85 #[test]
86 fn test_bitwiseor_convolve() {
87 let mut rng = Xorshift::new();
88
89 for k in 0..12 {
90 let n = 1 << k;
91 rand!(rng, mut f: [-A..A; n]);
92 let mut g = vec![0i64; n];
93 let h = f.clone();
94 for (s, f) in f.iter().enumerate() {
95 for (t, g) in g.iter_mut().enumerate() {
96 if s | t == t {
97 *g += f;
98 }
99 }
100 }
101 BitwiseorConvolve::<AdditiveOperation<i64>>::zeta_transform(&mut f);
102 assert_eq!(f, g);
103 BitwiseorConvolve::<AdditiveOperation<i64>>::mobius_transform(&mut f);
104 assert_eq!(f, h);
105
106 rand!(rng, f: [-A..A; n], g: [-A..A; n]);
107 let mut h = vec![0i64; n];
108 for i in 0..n {
109 for j in 0..n {
110 h[i | j] += f[i] * g[j];
111 }
112 }
113 let i = BitwiseorConvolve::<AddMulOperation<i64>>::convolve(f, g);
114 assert_eq!(h, i);
115 }
116 }
117}