use p3_field::Field;
use tracing::instrument;
use crate::air_builders::debug::USE_DEBUG_BUILDER;
mod batch_inverse;
pub use batch_inverse::*;
#[instrument(name = "batch_multiplicative_inverse", level = "info", skip_all)]
pub fn batch_multiplicative_inverse_allowing_zero<F: Field>(values: Vec<F>) -> Vec<F> {
let mut nonzero_values = Vec::with_capacity(values.len());
let mut indices = Vec::with_capacity(values.len());
for (i, value) in values.iter().cloned().enumerate() {
if value.is_zero() {
continue;
}
nonzero_values.push(value);
indices.push(i);
}
let inverse_nonzero_values = p3_field::batch_multiplicative_inverse(&nonzero_values);
let mut result = values.clone();
for (i, index) in indices.into_iter().enumerate() {
result[index] = inverse_nonzero_values[i];
}
result
}
pub fn parallelize_chunks<T, F>(v: &mut [T], chunk_size: usize, f: F)
where
T: Send,
F: Fn(&mut [T], usize) + Send + Sync + Clone,
{
debug_assert_eq!(v.len() % chunk_size, 0);
#[cfg(not(feature = "parallel"))]
{
f(v, 0)
}
#[cfg(feature = "parallel")]
{
let f = &f;
let total_iters = v.len() / chunk_size;
let num_threads = rayon::current_num_threads();
let lo_slice_size = (total_iters / num_threads) * chunk_size;
let hi_slice_size = lo_slice_size + chunk_size;
let cutoff_thread_idx = total_iters % num_threads;
let split_pos = cutoff_thread_idx * hi_slice_size;
let (v_hi, v_lo) = v.split_at_mut(split_pos);
rayon::scope(|scope| {
if cutoff_thread_idx != 0 {
for (chunk_id, chunk) in v_hi.chunks_exact_mut(hi_slice_size).enumerate() {
let offset = chunk_id * hi_slice_size;
scope.spawn(move |_| f(chunk, offset));
}
}
if lo_slice_size != 0 {
for (chunk_id, chunk) in v_lo.chunks_exact_mut(lo_slice_size).enumerate() {
let offset = split_pos + (chunk_id * lo_slice_size);
scope.spawn(move |_| f(chunk, offset));
}
}
});
}
}
pub fn disable_debug_builder() {
USE_DEBUG_BUILDER.with(|debug| {
*debug.lock().unwrap() = false;
});
}
#[macro_export]
#[cfg(feature = "parallel")]
macro_rules! parizip {
( $first:expr $( , $rest:expr )* $(,)* ) => {
{
use rayon::iter::*;
( $first $( , $rest)* ).into_par_iter()
}
};
}
#[macro_export]
#[cfg(not(feature = "parallel"))]
macro_rules! parizip {
( $first:expr $( , $rest:expr )* $(,)* ) => {
itertools::izip!( $first $( , $rest)* )
};
}