Skip to content

Commit

Permalink
[WIP] Add document for convolution
Browse files Browse the repository at this point in the history
  • Loading branch information
qryxip committed Oct 19, 2020
1 parent a8c306d commit 119beb5
Showing 1 changed file with 132 additions and 0 deletions.
132 changes: 132 additions & 0 deletions src/convolution.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
//! Functions that calculate $(+, \times)$ convolution.
//!
//! 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
//!
//! \\[
//! c_i = \sum_ {j = 0}^i a_j b_{i - j}
//! \\]
macro_rules! modulus {
($($name:ident),*) => {
$(
Expand Down Expand Up @@ -29,6 +37,50 @@ use std::{
fmt,
};

/// Calculates the $(+, \times)$ convolution in $\mathbb{Z}/p\mathbb{Z}$.
///
/// Returns a empty `Vec` if `a` or `b` is empty.
///
/// # Constraints
///
/// - $2 \leq m \leq 2 \times 10^9$
/// - $m$ is a prime number.
/// - $\exists c \text{ s.t. } 2^c \mid (m - 1), |a| + |b| - 1 \leq 2^c$
///
/// where $m$ is `M::VALUE`.
///
/// # Complexity
///
/// - $O(n \log n + \log m)$ where $n = |a| + |b|$.
///
/// # Example
///
/// ```
/// use ac_library_rs::ModInt1000000007 as Mint;
/// use proconio::{input, source::once::OnceSource};
///
/// input! {
/// from OnceSource::from(
/// "3\n\
/// 1 2 3\n\
/// 3\n\
/// -1 -2 -3\n",
/// ),
/// a: [Mint],
/// b: [Mint],
/// }
///
/// assert_eq!(
/// ac_library_rs::convolution(&a, &b),
/// [
/// Mint::new(-1),
/// Mint::new(-4),
/// Mint::new(-10),
/// Mint::new(-12),
/// Mint::new(-9),
/// ],
/// );
/// ```
#[allow(clippy::many_single_char_names)]
pub fn convolution<M>(a: &[StaticModInt<M>], b: &[StaticModInt<M>]) -> Vec<StaticModInt<M>>
where
Expand Down Expand Up @@ -68,6 +120,52 @@ where
a
}

/// Calculates the $(+, \times)$ convolution in $\mathbb{Z}/p\mathbb{Z}$.
///
/// Returns a empty `Vec` if `a` or `b` is empty.
///
/// # Constraints
///
/// - $2 \leq m \leq 2 \times 10^9$
/// - $m$ is a prime number.
/// - $\exists c \text{ s.t. } 2^c \mid (m - 1), |a| + |b| - 1 \leq 2^c$
///
/// where $m$ is `M::VALUE`.
///
/// # Complexity
///
/// - $O(n \log n + \log m)$ where $n = |a| + |b|$.
///
/// # Example
///
/// ```
/// use ac_library_rs::{Mod1000000007 as M, Modulus as _};
/// use proconio::{input, source::once::OnceSource};
///
/// const M: u32 = M::VALUE;
///
/// input! {
/// from OnceSource::from(
/// "3\n\
/// 1 2 3\n\
/// 3\n\
/// -1 -2 -3\n",
/// ),
/// a: [i32],
/// b: [i32],
/// }
///
/// assert_eq!(
/// ac_library_rs::convolution::convolution_raw::<_, M>(&a, &b),
/// [
/// (-1i32).rem_euclid(M as i32),
/// (-4i32).rem_euclid(M as i32),
/// (-10i32).rem_euclid(M as i32),
/// (-12i32).rem_euclid(M as i32),
/// (-9i32).rem_euclid(M as i32),
/// ],
/// );
/// ```
pub fn convolution_raw<T, M>(a: &[T], b: &[T]) -> Vec<T>
where
T: RemEuclidU32 + TryFrom<u32> + Clone,
Expand All @@ -86,6 +184,40 @@ where
.collect()
}

/// Calculates the $(+, \times)$ convolution in `i64`.
///
/// Returns a empty `Vec` if `a` or `b` is empty.
///
/// # Constraints
///
/// - $|a| + |b| - 1 \leq 2^{24}$
/// - All elements of the result are inside of the range of `i64`
///
/// # Complexity
///
/// - $O(n \log n)$ where $n = |a| + |b|$.
///
/// # Example
///
/// ```
/// use proconio::{input, source::once::OnceSource};
///
/// input! {
/// from OnceSource::from(
/// "3\n\
/// 1 2 3\n\
/// 3\n\
/// -1 -2 -3\n",
/// ),
/// a: [i64],
/// b: [i64],
/// }
///
/// assert_eq!(
/// ac_library_rs::convolution_i64(&a, &b),
/// [-1, -4, -10, -12, -9],
/// );
/// ```
#[allow(clippy::many_single_char_names)]
pub fn convolution_i64(a: &[i64], b: &[i64]) -> Vec<i64> {
const M1: u64 = 754_974_721; // 2^24
Expand Down

0 comments on commit 119beb5

Please sign in to comment.