openvm_stark_backend/
utils.rs

1use std::borrow::Cow;
2
3use cfg_if::cfg_if;
4use p3_field::Field;
5use tracing::instrument;
6
7use crate::air_builders::debug::USE_DEBUG_BUILDER;
8
9// Copied from valida-util
10/// Calculates and returns the multiplicative inverses of each field element, with zero
11/// values remaining unchanged.
12#[instrument(name = "batch_multiplicative_inverse", level = "info", skip_all)]
13pub fn batch_multiplicative_inverse_allowing_zero<F: Field>(values: Vec<F>) -> Vec<F> {
14    // Check if values are zero, and construct a new vector with only nonzero values
15    let mut nonzero_values = Vec::with_capacity(values.len());
16    let mut indices = Vec::with_capacity(values.len());
17    for (i, value) in values.iter().cloned().enumerate() {
18        if value.is_zero() {
19            continue;
20        }
21        nonzero_values.push(value);
22        indices.push(i);
23    }
24
25    // Compute the multiplicative inverse of nonzero values
26    let inverse_nonzero_values = p3_field::batch_multiplicative_inverse(&nonzero_values);
27
28    // Reconstruct the original vector
29    let mut result = values.clone();
30    for (i, index) in indices.into_iter().enumerate() {
31        result[index] = inverse_nonzero_values[i];
32    }
33
34    result
35}
36
37/// Disables the debug builder so there are not debug assert panics.
38/// Commonly used in negative tests to prevent panics.
39pub fn disable_debug_builder() {
40    USE_DEBUG_BUILDER.with(|debug| {
41        *debug.lock().unwrap() = false;
42    });
43}
44
45/// A span that will run the given closure `f`,
46/// and emit a metric with the given `name` using [`gauge`](metrics::gauge)
47/// when the feature `"bench-metrics"` is enabled.
48#[allow(unused_variables)]
49pub fn metrics_span<R, F: FnOnce() -> R>(name: impl Into<Cow<'static, str>>, f: F) -> R {
50    cfg_if! {
51        if #[cfg(feature = "bench-metrics")] {
52            let start = std::time::Instant::now();
53            let res = f();
54            metrics::gauge!(name.into()).set(start.elapsed().as_millis() as f64);
55            res
56        } else {
57            f()
58        }
59    }
60}
61
62#[macro_export]
63#[cfg(feature = "parallel")]
64macro_rules! parizip {
65    ( $first:expr $( , $rest:expr )* $(,)* ) => {
66        {
67            use rayon::iter::*;
68            (( $first $( , $rest)* )).into_par_iter()
69        }
70    };
71}
72#[macro_export]
73#[cfg(not(feature = "parallel"))]
74macro_rules! parizip {
75    ( $first:expr $( , $rest:expr )* $(,)* ) => {
76        itertools::izip!( $first $( , $rest)* )
77    };
78}