penumbra_sdk_proof_setup/
parallel_utils.rs

1pub fn transform<A, B, const N: usize>(data: [A; N], f: impl Fn(A) -> B) -> [B; N] {
2    match data.into_iter().map(f).collect::<Vec<B>>().try_into() {
3        Ok(x) => x,
4        _ => panic!("The size of the iterator should not have changed"),
5    }
6}
7
8#[cfg(not(feature = "parallel"))]
9pub fn transform_parallel<A, B, const N: usize>(data: [A; N], f: impl Fn(A) -> B) -> [B; N] {
10    transform(data, f)
11}
12
13#[cfg(feature = "parallel")]
14pub fn transform_parallel<A: Send, B: Sync + Send, const N: usize>(
15    data: [A; N],
16    f: impl Fn(A) -> B + Sync + Send,
17) -> [B; N] {
18    use rayon::prelude::*;
19    let out: Vec<B> = data.into_par_iter().map(f).collect();
20    // Note: we do it this way because we don't have a Debug implementation for B
21    match out.try_into() {
22        Ok(x) => x,
23        _ => panic!("The size of the iterator should not have changed"),
24    }
25}
26
27pub fn flatten_results<A, E, const N: usize>(data: [Result<A, E>; N]) -> Result<[A; N], E> {
28    let mut buf = Vec::with_capacity(N);
29    for x in data {
30        buf.push(x?);
31    }
32    match buf.try_into() {
33        Ok(x) => Ok(x),
34        _ => panic!("The size of the iterator should not have changed"),
35    }
36}
37
38#[cfg(not(feature = "parallel"))]
39pub fn zip_map_parallel<A: Send, B: Send, C: Sync + Send>(
40    a: &mut [A],
41    b: &mut [B],
42    f: impl Fn(&A, &B) -> C + Send + Sync,
43) -> Vec<C> {
44    a.iter().zip(b.iter()).map(|(a, b)| f(a, b)).collect()
45}
46
47#[cfg(feature = "parallel")]
48pub fn zip_map_parallel<A: Send, B: Send, C: Sync + Send>(
49    a: &mut [A],
50    b: &mut [B],
51    f: impl Fn(&A, &B) -> C + Send + Sync,
52) -> Vec<C> {
53    use rayon::prelude::*;
54
55    a.into_par_iter()
56        .zip(b.into_par_iter())
57        .map(|(a, b)| f(a, b))
58        .collect()
59}