sp1_core_machine/utils/
mod.rs1pub mod concurrency;
2mod logger;
3mod prove;
4mod span;
5mod test;
6pub mod uni_stark;
7
8pub use logger::*;
9use p3_field::Field;
10pub use prove::*;
11use sp1_curves::params::Limbs;
12pub use span::*;
13pub use test::*;
14pub use uni_stark::*;
15
16use crate::memory::MemoryCols;
17
18use generic_array::ArrayLength;
19use p3_maybe_rayon::prelude::{ParallelBridge, ParallelIterator};
20
21pub use sp1_primitives::consts::{
22 bytes_to_words_le, bytes_to_words_le_vec, num_to_comma_separated, words_to_bytes_le,
23 words_to_bytes_le_vec,
24};
25
26pub const fn indices_arr<const N: usize>() -> [usize; N] {
27 let mut indices_arr = [0; N];
28 let mut i = 0;
29 while i < N {
30 indices_arr[i] = i;
31 i += 1;
32 }
33 indices_arr
34}
35
36pub fn pad_to_power_of_two<const N: usize, T: Clone + Default>(values: &mut Vec<T>) {
37 debug_assert!(values.len().is_multiple_of(N));
38 let mut n_real_rows = values.len() / N;
39 if n_real_rows < 16 {
40 n_real_rows = 16;
41 }
42 values.resize(n_real_rows.next_power_of_two() * N, T::default());
43}
44
45pub fn limbs_from_prev_access<T: Copy, N: ArrayLength, M: MemoryCols<T>>(
46 cols: &[M],
47) -> Limbs<T, N> {
48 let vec = cols.iter().flat_map(|access| access.prev_value().0).collect::<Vec<T>>();
49
50 let sized = vec.try_into().unwrap_or_else(|_| panic!("failed to convert to limbs"));
51 Limbs(sized)
52}
53
54pub fn limbs_from_access<T: Copy, N: ArrayLength, M: MemoryCols<T>>(cols: &[M]) -> Limbs<T, N> {
55 let vec = cols.iter().flat_map(|access| access.value().0).collect::<Vec<T>>();
56
57 let sized = vec.try_into().unwrap_or_else(|_| panic!("failed to convert to limbs"));
58 Limbs(sized)
59}
60
61pub fn pad_rows_fixed<R: Clone>(
68 rows: &mut Vec<R>,
69 row_fn: impl Fn() -> R,
70 size_log2: Option<usize>,
71) {
72 let nb_rows = rows.len();
73 let dummy_row = row_fn();
74 rows.resize(next_power_of_two(nb_rows, size_log2), dummy_row);
75}
76
77pub fn next_power_of_two(n: usize, fixed_power: Option<usize>) -> usize {
80 match fixed_power {
81 Some(power) => {
82 let padded_nb_rows = 1 << power;
83 if n * 2 < padded_nb_rows {
84 tracing::debug!(
85 "fixed log2 rows can be potentially reduced: got {}, expected {}",
86 n,
87 padded_nb_rows
88 );
89 }
90 if n > padded_nb_rows {
91 panic!("fixed log2 rows is too small: got {n}, expected {padded_nb_rows}");
92 }
93 padded_nb_rows
94 }
95 None => {
96 let mut padded_nb_rows = n.next_power_of_two();
97 if padded_nb_rows < 16 {
98 padded_nb_rows = 16;
99 }
100 padded_nb_rows
101 }
102 }
103}
104
105pub fn chunk_vec<T>(mut vec: Vec<T>, chunk_size: usize) -> Vec<Vec<T>> {
106 let mut result = Vec::new();
107 while !vec.is_empty() {
108 let current_chunk_size = std::cmp::min(chunk_size, vec.len());
109 let current_chunk = vec.drain(..current_chunk_size).collect::<Vec<T>>();
110 result.push(current_chunk);
111 }
112 result
113}
114
115#[inline]
116pub fn log2_strict_usize(n: usize) -> usize {
117 let res = n.trailing_zeros();
118 assert_eq!(n.wrapping_shr(res), 1, "Not a power of two: {n}");
119 res as usize
120}
121
122pub fn par_for_each_row<P, F>(vec: &mut [F], num_elements_per_event: usize, processor: P)
123where
124 F: Send,
125 P: Fn(usize, &mut [F]) + Send + Sync,
126{
127 assert!(vec.len().is_multiple_of(num_elements_per_event));
129 let len = vec.len() / num_elements_per_event;
130 let cpus = num_cpus::get();
131 let ceil_div = len.div_ceil(cpus);
132 let chunk_size = std::cmp::max(ceil_div, cpus);
133
134 vec.chunks_mut(chunk_size * num_elements_per_event).enumerate().par_bridge().for_each(
135 |(i, chunk)| {
136 chunk.chunks_mut(num_elements_per_event).enumerate().for_each(|(j, row)| {
137 assert!(row.len() == num_elements_per_event);
138 processor(i * chunk_size + j, row);
139 });
140 },
141 );
142}
143
144pub fn sp1_debug_mode() -> bool {
151 let value = std::env::var("SP1_DEBUG").unwrap_or_else(|_| "false".to_string());
152 value == "1" || value.to_lowercase() == "true"
153}
154
155pub fn zeroed_f_vec<F: Field>(len: usize) -> Vec<F> {
160 debug_assert!(std::mem::size_of::<F>() == 4);
161
162 let vec = vec![0u32; len];
163 unsafe { std::mem::transmute::<Vec<u32>, Vec<F>>(vec) }
164}