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}