Skip to content

Commit

Permalink
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 d6abc90
Showing 1 changed file with 154 additions and 0 deletions.
154 changes: 154 additions & 0 deletions src/convolution.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,16 @@
//! Functions that calculate $(+, \times)$ convolution.
//!
//! Given two non-empty sequences $a_0, a_1, \ldots, a_{N - 1}$ and $b_0, b_1, \ldots, b_{M - 1}$, they calculate the sequence $c$ of length $N + M - 1$ defined by
//!
//! \\[
//! c_i = \sum_ {j = 0}^i a_j b_{i - j}
//! \\]
//!
//! # Major changes from the original ACL
//!
//! - Separated the overloaded `convolution` into `convolution<_>` and `convolution_raw<_, _>`.
//! - Renamed `convolution_ll` to `convolution_i64`.
macro_rules! modulus {
($($name:ident),*) => {
$(
Expand Down Expand Up @@ -29,6 +42,54 @@ use std::{
fmt,
};

/// Calculates the $(+, \times)$ convolution in $\mathbb{Z}/p\mathbb{Z}$.
///
/// See the [module-level documentation] for more details.
///
/// 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),
/// ],
/// );
/// ```
///
/// [module-level documentation]: ./index.html
#[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 +129,61 @@ where
a
}

/// Calculates the $(+, \times)$ convolution in $\mathbb{Z}/p\mathbb{Z}$.
///
/// See the [module-level documentation] for more details.
///
/// 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$
/// - $(0, m] \subseteq$ `T`
///
/// where $m$ is `M::VALUE`.
///
/// # Complexity
///
/// - $O(n \log n + \log m)$ where $n = |a| + |b|$.
///
/// # Panics
///
/// Panics if any element of the result ($\in [0,$ `M::VALUE`$)$) is outside of the range of `T`.
///
/// # Example
///
/// ```
/// use ac_library_rs::{Mod1000000007 as M, Modulus as _};
/// use proconio::{input, source::once::OnceSource};
///
/// const M: i32 = M::VALUE as _;
///
/// 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),
/// (-4i32).rem_euclid(M),
/// (-10i32).rem_euclid(M),
/// (-12i32).rem_euclid(M),
/// (-9i32).rem_euclid(M),
/// ],
/// );
/// ```
///
/// [module-level documentation]: ./index.html
pub fn convolution_raw<T, M>(a: &[T], b: &[T]) -> Vec<T>
where
T: RemEuclidU32 + TryFrom<u32> + Clone,
Expand All @@ -86,6 +202,44 @@ where
.collect()
}

/// Calculates the $(+, \times)$ convolution in `i64`.
///
/// See the [module-level documentation] for more details.
///
/// 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],
/// );
/// ```
///
/// [module-level documentation]: ./index.html
#[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 d6abc90

Please sign in to comment.