Skip to content

Commit 119beb5

Browse files
committed
[WIP] Add document for convolution
1 parent a8c306d commit 119beb5

File tree

1 file changed

+132
-0
lines changed

1 file changed

+132
-0
lines changed

src/convolution.rs

+132
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,11 @@
1+
//! Functions that calculate $(+, \times)$ convolution.
2+
//!
3+
//! Given two arrays $a_0, a_1, \ldots, a_{N - 1}$ and $a_0, a_1, \ldots, a_{M - 1}$, They calculate the array $c$ of length $N + M - 1$, defined by
4+
//!
5+
//! \\[
6+
//! c_i = \sum_ {j = 0}^i a_j b_{i - j}
7+
//! \\]
8+
19
macro_rules! modulus {
210
($($name:ident),*) => {
311
$(
@@ -29,6 +37,50 @@ use std::{
2937
fmt,
3038
};
3139

40+
/// Calculates the $(+, \times)$ convolution in $\mathbb{Z}/p\mathbb{Z}$.
41+
///
42+
/// Returns a empty `Vec` if `a` or `b` is empty.
43+
///
44+
/// # Constraints
45+
///
46+
/// - $2 \leq m \leq 2 \times 10^9$
47+
/// - $m$ is a prime number.
48+
/// - $\exists c \text{ s.t. } 2^c \mid (m - 1), |a| + |b| - 1 \leq 2^c$
49+
///
50+
/// where $m$ is `M::VALUE`.
51+
///
52+
/// # Complexity
53+
///
54+
/// - $O(n \log n + \log m)$ where $n = |a| + |b|$.
55+
///
56+
/// # Example
57+
///
58+
/// ```
59+
/// use ac_library_rs::ModInt1000000007 as Mint;
60+
/// use proconio::{input, source::once::OnceSource};
61+
///
62+
/// input! {
63+
/// from OnceSource::from(
64+
/// "3\n\
65+
/// 1 2 3\n\
66+
/// 3\n\
67+
/// -1 -2 -3\n",
68+
/// ),
69+
/// a: [Mint],
70+
/// b: [Mint],
71+
/// }
72+
///
73+
/// assert_eq!(
74+
/// ac_library_rs::convolution(&a, &b),
75+
/// [
76+
/// Mint::new(-1),
77+
/// Mint::new(-4),
78+
/// Mint::new(-10),
79+
/// Mint::new(-12),
80+
/// Mint::new(-9),
81+
/// ],
82+
/// );
83+
/// ```
3284
#[allow(clippy::many_single_char_names)]
3385
pub fn convolution<M>(a: &[StaticModInt<M>], b: &[StaticModInt<M>]) -> Vec<StaticModInt<M>>
3486
where
@@ -68,6 +120,52 @@ where
68120
a
69121
}
70122

123+
/// Calculates the $(+, \times)$ convolution in $\mathbb{Z}/p\mathbb{Z}$.
124+
///
125+
/// Returns a empty `Vec` if `a` or `b` is empty.
126+
///
127+
/// # Constraints
128+
///
129+
/// - $2 \leq m \leq 2 \times 10^9$
130+
/// - $m$ is a prime number.
131+
/// - $\exists c \text{ s.t. } 2^c \mid (m - 1), |a| + |b| - 1 \leq 2^c$
132+
///
133+
/// where $m$ is `M::VALUE`.
134+
///
135+
/// # Complexity
136+
///
137+
/// - $O(n \log n + \log m)$ where $n = |a| + |b|$.
138+
///
139+
/// # Example
140+
///
141+
/// ```
142+
/// use ac_library_rs::{Mod1000000007 as M, Modulus as _};
143+
/// use proconio::{input, source::once::OnceSource};
144+
///
145+
/// const M: u32 = M::VALUE;
146+
///
147+
/// input! {
148+
/// from OnceSource::from(
149+
/// "3\n\
150+
/// 1 2 3\n\
151+
/// 3\n\
152+
/// -1 -2 -3\n",
153+
/// ),
154+
/// a: [i32],
155+
/// b: [i32],
156+
/// }
157+
///
158+
/// assert_eq!(
159+
/// ac_library_rs::convolution::convolution_raw::<_, M>(&a, &b),
160+
/// [
161+
/// (-1i32).rem_euclid(M as i32),
162+
/// (-4i32).rem_euclid(M as i32),
163+
/// (-10i32).rem_euclid(M as i32),
164+
/// (-12i32).rem_euclid(M as i32),
165+
/// (-9i32).rem_euclid(M as i32),
166+
/// ],
167+
/// );
168+
/// ```
71169
pub fn convolution_raw<T, M>(a: &[T], b: &[T]) -> Vec<T>
72170
where
73171
T: RemEuclidU32 + TryFrom<u32> + Clone,
@@ -86,6 +184,40 @@ where
86184
.collect()
87185
}
88186

187+
/// Calculates the $(+, \times)$ convolution in `i64`.
188+
///
189+
/// Returns a empty `Vec` if `a` or `b` is empty.
190+
///
191+
/// # Constraints
192+
///
193+
/// - $|a| + |b| - 1 \leq 2^{24}$
194+
/// - All elements of the result are inside of the range of `i64`
195+
///
196+
/// # Complexity
197+
///
198+
/// - $O(n \log n)$ where $n = |a| + |b|$.
199+
///
200+
/// # Example
201+
///
202+
/// ```
203+
/// use proconio::{input, source::once::OnceSource};
204+
///
205+
/// input! {
206+
/// from OnceSource::from(
207+
/// "3\n\
208+
/// 1 2 3\n\
209+
/// 3\n\
210+
/// -1 -2 -3\n",
211+
/// ),
212+
/// a: [i64],
213+
/// b: [i64],
214+
/// }
215+
///
216+
/// assert_eq!(
217+
/// ac_library_rs::convolution_i64(&a, &b),
218+
/// [-1, -4, -10, -12, -9],
219+
/// );
220+
/// ```
89221
#[allow(clippy::many_single_char_names)]
90222
pub fn convolution_i64(a: &[i64], b: &[i64]) -> Vec<i64> {
91223
const M1: u64 = 754_974_721; // 2^24

0 commit comments

Comments
 (0)