arnaucube
arnaucube/hyperplonkPublic Self-hosted repository
hyperplonk/poly-iop/src/utils.rs
poly-iop/src/utils.rsRaw
  1//! useful macros.
  2
  3/// Takes as input a struct, and converts them to a series of bytes. All traits
  4/// that implement `CanonicalSerialize` can be automatically converted to bytes
  5/// in this manner.
  6#[macro_export]
  7macro_rules! to_bytes {
  8    ($x:expr) => {{
  9        let mut buf = ark_std::vec![];
 10        ark_serialize::CanonicalSerialize::serialize($x, &mut buf).map(|_| buf)
 11    }};
 12}
 13
 14/// Decompose an integer into a binary vector in little endian.
 15#[allow(dead_code)]
 16pub(crate) fn bit_decompose(input: u64, num_var: usize) -> Vec<bool> {
 17    let mut res = Vec::with_capacity(num_var);
 18    let mut i = input;
 19    for _ in 0..num_var {
 20        res.push(i & 1 == 1);
 21        i >>= 1;
 22    }
 23    res
 24}
 25
 26/// Project a little endian binary vector into an integer.
 27#[allow(dead_code)]
 28pub(crate) fn project(input: &[bool]) -> u64 {
 29    let mut res = 0;
 30    for &e in input.iter().rev() {
 31        res <<= 1;
 32        res += e as u64;
 33    }
 34    res
 35}
 36
 37// Input index
 38// - `i := (i_0, ...i_{n-1})`,
 39// - `num_vars := n`
 40// return three elements:
 41// - `x0 := (i_1, ..., i_{n-1}, 0)`
 42// - `x1 := (i_1, ..., i_{n-1}, 1)`
 43// - `sign := i_0`
 44#[inline]
 45pub(crate) fn get_index(i: usize, num_vars: usize) -> (usize, usize, bool) {
 46    let bit_sequence = bit_decompose(i as u64, num_vars);
 47
 48    // the last bit comes first here because of LE encoding
 49    let x0 = project(&[[false].as_ref(), bit_sequence[..num_vars - 1].as_ref()].concat()) as usize;
 50    let x1 = project(&[[true].as_ref(), bit_sequence[..num_vars - 1].as_ref()].concat()) as usize;
 51
 52    (x0, x1, bit_sequence[num_vars - 1])
 53}
 54
 55#[cfg(test)]
 56mod test {
 57    use super::{bit_decompose, get_index, project};
 58    use ark_bls12_381::Fr;
 59    use ark_serialize::CanonicalSerialize;
 60    use ark_std::{rand::RngCore, test_rng, One};
 61
 62    #[test]
 63    fn test_to_bytes() {
 64        let f1 = Fr::one();
 65
 66        let mut bytes = ark_std::vec![];
 67        f1.serialize(&mut bytes).unwrap();
 68        assert_eq!(bytes, to_bytes!(&f1).unwrap());
 69    }
 70
 71    #[test]
 72    fn test_decomposition() {
 73        let mut rng = test_rng();
 74        for _ in 0..100 {
 75            let t = rng.next_u64();
 76            let b = bit_decompose(t, 64);
 77            let r = project(&b);
 78            assert_eq!(t, r)
 79        }
 80    }
 81
 82    #[test]
 83    fn test_get_index() {
 84        let a = 0b1010;
 85        let (x0, x1, sign) = get_index(a, 4);
 86        assert_eq!(x0, 0b0100);
 87        assert_eq!(x1, 0b0101);
 88        assert!(sign);
 89
 90        let (x0, x1, sign) = get_index(a, 5);
 91        assert_eq!(x0, 0b10100);
 92        assert_eq!(x1, 0b10101);
 93        assert!(!sign);
 94
 95        let a = 0b1111;
 96        let (x0, x1, sign) = get_index(a, 4);
 97        assert_eq!(x0, 0b1110);
 98        assert_eq!(x1, 0b1111);
 99        assert!(sign);
100    }
101}