halo2_proofs 0.3.2

Fast PLONK-based zero-knowledge proving system with no trusted setup
Documentation
//! An interface for dealing with the kinds of parallel computations involved in
//! `halo2`. It's currently just a (very!) thin wrapper around `rayon` but may
//! be extended in the future to allow for various parallelism strategies.

#[cfg(all(
    feature = "multicore",
    target_arch = "wasm32",
    not(target_feature = "atomics")
))]
compile_error!(
    "The multicore feature flag is not supported on wasm32 architectures without atomics"
);

pub use maybe_rayon::{
    iter::{IntoParallelIterator, ParallelIterator},
    join, scope, Scope,
};

#[cfg(feature = "multicore")]
pub use maybe_rayon::{current_num_threads, iter::IndexedParallelIterator};

#[cfg(not(feature = "multicore"))]
pub fn current_num_threads() -> usize {
    1
}

#[cfg(not(feature = "multicore"))]
pub trait IndexedParallelIterator: std::iter::Iterator {}

pub trait TryFoldAndReduce<T, E> {
    /// Implements `iter.try_fold().try_reduce()` for `rayon::iter::ParallelIterator`,
    /// falling back on `Iterator::try_fold` when the `multicore` feature flag is
    /// disabled.
    /// The `try_fold_and_reduce` function can only be called by a iter with
    /// `Result<T, E>` item type because the `fold_op` must meet the trait
    /// bounds of both `try_fold` and `try_reduce` from rayon.   
    fn try_fold_and_reduce(
        self,
        identity: impl Fn() -> T + Send + Sync,
        fold_op: impl Fn(T, Result<T, E>) -> Result<T, E> + Send + Sync,
    ) -> Result<T, E>;
}

#[cfg(feature = "multicore")]
impl<T, E, I> TryFoldAndReduce<T, E> for I
where
    T: Send + Sync,
    E: Send + Sync,
    I: maybe_rayon::iter::ParallelIterator<Item = Result<T, E>>,
{
    fn try_fold_and_reduce(
        self,
        identity: impl Fn() -> T + Send + Sync,
        fold_op: impl Fn(T, Result<T, E>) -> Result<T, E> + Send + Sync,
    ) -> Result<T, E> {
        self.try_fold(&identity, &fold_op)
            .try_reduce(&identity, |a, b| fold_op(a, Ok(b)))
    }
}

#[cfg(not(feature = "multicore"))]
impl<T, E, I> TryFoldAndReduce<T, E> for I
where
    I: std::iter::Iterator<Item = Result<T, E>>,
{
    fn try_fold_and_reduce(
        mut self,
        identity: impl Fn() -> T + Send + Sync,
        fold_op: impl Fn(T, Result<T, E>) -> Result<T, E> + Send + Sync,
    ) -> Result<T, E> {
        self.try_fold(identity(), fold_op)
    }
}

pub(crate) trait TheBestReduce {
    type Item;

    /// Combines the best of `std::iter` and `rayon` reductions.
    fn the_best_reduce(
        self,
        identity: impl Fn() -> Self::Item + Send + Sync,
        op: impl Fn(Self::Item, Self::Item) -> Self::Item + Send + Sync,
    ) -> Option<Self::Item>;
}

#[cfg(feature = "multicore")]
impl<I> TheBestReduce for I
where
    I: maybe_rayon::iter::ParallelIterator,
{
    type Item = <Self as maybe_rayon::iter::ParallelIterator>::Item;

    fn the_best_reduce(
        self,
        identity: impl Fn() -> Self::Item + Send + Sync,
        op: impl Fn(Self::Item, Self::Item) -> Self::Item + Send + Sync,
    ) -> Option<Self::Item> {
        Some(self.reduce(identity, op))
    }
}

#[cfg(not(feature = "multicore"))]
impl<I> TheBestReduce for I
where
    I: std::iter::Iterator,
{
    type Item = <Self as std::iter::Iterator>::Item;

    fn the_best_reduce(
        self,
        _: impl Fn() -> Self::Item + Send + Sync,
        f: impl Fn(Self::Item, Self::Item) -> Self::Item + Send + Sync,
    ) -> Option<Self::Item> {
        self.reduce(f)
    }
}