arnaucube
arnaucube/sonobePublic Self-hosted repository
sonobe/src/utils/hypercube.rs
src/utils/hypercube.rsRaw
 1/// A boolean hypercube structure to create an ergonomic evaluation domain
 2use crate::utils::virtual_polynomial::bit_decompose;
 3use ark_ff::PrimeField;
 4
 5use std::marker::PhantomData;
 6
 7/// A boolean hypercube that returns its points as an iterator
 8/// If you iterate on it for 3 variables you will get points in little-endian order:
 9/// 000 -> 100 -> 010 -> 110 -> 001 -> 101 -> 011 -> 111
10#[derive(Debug, Clone)]
11pub struct BooleanHypercube<F: PrimeField> {
12    _f: PhantomData<F>,
13    n_vars: usize,
14    current: u64,
15    max: u64,
16}
17
18impl<F: PrimeField> BooleanHypercube<F> {
19    pub fn new(n_vars: usize) -> Self {
20        BooleanHypercube::<F> {
21            _f: PhantomData::<F>,
22            n_vars,
23            current: 0,
24            max: 2_u32.pow(n_vars as u32) as u64,
25        }
26    }
27
28    /// returns the entry at given i (which is the little-endian bit representation of i)
29    pub fn at_i(&self, i: usize) -> Vec<F> {
30        assert!(i < self.max as usize);
31        let bits = bit_decompose((i) as u64, self.n_vars);
32        bits.iter().map(|&x| F::from(x)).collect()
33    }
34}
35
36impl<F: PrimeField> Iterator for BooleanHypercube<F> {
37    type Item = Vec<F>;
38
39    fn next(&mut self) -> Option<Self::Item> {
40        let bits = bit_decompose(self.current, self.n_vars);
41        let result: Vec<F> = bits.iter().map(|&x| F::from(x)).collect();
42        self.current += 1;
43
44        if self.current > self.max {
45            return None;
46        }
47
48        Some(result)
49    }
50}
51
52#[cfg(test)]
53mod tests {
54    use super::*;
55    use crate::utils::vec::tests::to_F_dense_matrix;
56    use ark_pallas::Fr;
57
58    #[test]
59    fn test_hypercube() {
60        let expected_results = to_F_dense_matrix(vec![
61            vec![0, 0, 0],
62            vec![1, 0, 0],
63            vec![0, 1, 0],
64            vec![1, 1, 0],
65            vec![0, 0, 1],
66            vec![1, 0, 1],
67            vec![0, 1, 1],
68            vec![1, 1, 1],
69        ]);
70
71        let bhc = BooleanHypercube::<Fr>::new(3);
72        for (i, point) in bhc.clone().enumerate() {
73            assert_eq!(point, expected_results[i]);
74            assert_eq!(point, bhc.at_i(i));
75        }
76    }
77}