use crate::field::field_types::Field; use crate::polynomial::polynomial::PolynomialValues; pub(crate) mod context_tree; pub(crate) mod marking; pub(crate) mod partial_products; pub(crate) mod reducing; pub(crate) mod timing; pub(crate) fn bits_u64(n: u64) -> usize { (64 - n.leading_zeros()) as usize } pub(crate) const fn ceil_div_usize(a: usize, b: usize) -> usize { (a + b - 1) / b } pub(crate) fn pad_to_multiple_usize(a: usize, b: usize) -> usize { ceil_div_usize(a, b) * b } /// Computes `ceil(log_2(n))`. pub(crate) fn log2_ceil(n: usize) -> usize { n.next_power_of_two().trailing_zeros() as usize } /// Computes `log_2(n)`, panicking if `n` is not a power of two. pub(crate) fn log2_strict(n: usize) -> usize { assert!(n.is_power_of_two(), "Not a power of two: {}", n); log2_ceil(n) } pub(crate) fn transpose_poly_values(polys: Vec>) -> Vec> { let poly_values = polys.into_iter().map(|p| p.values).collect::>(); transpose(&poly_values) } pub fn transpose(matrix: &[Vec]) -> Vec> { let l = matrix.len(); let w = matrix[0].len(); let mut transposed = vec![vec![F::ZERO; l]; w]; for i in 0..w { for j in 0..l { transposed[i][j] = matrix[j][i]; } } transposed } /// Permutes `arr` such that each index is mapped to its reverse in binary. pub(crate) fn reverse_index_bits(arr: &[T]) -> Vec { let n = arr.len(); let n_power = log2_strict(n); let mut result = Vec::with_capacity(n); for i in 0..n { result.push(arr[reverse_bits(i, n_power)]); } result } pub(crate) fn reverse_index_bits_in_place(arr: &mut Vec) { let n = arr.len(); let n_power = log2_strict(n); for src in 0..n { let dst = reverse_bits(src, n_power); if src < dst { arr.swap(src, dst); } } } pub(crate) fn reverse_bits(n: usize, num_bits: usize) -> usize { // NB: The only reason we need overflowing_shr() here as opposed // to plain '>>' is to accommodate the case n == num_bits == 0, // which would become `0 >> 64`. Rust thinks that any shift of 64 // bits causes overflow, even when the argument is zero. n.reverse_bits() .overflowing_shr(usize::BITS - num_bits as u32) .0 } #[cfg(test)] mod tests { use crate::util::{reverse_bits, reverse_index_bits}; #[test] fn test_reverse_bits() { assert_eq!(reverse_bits(0b0000000000, 10), 0b0000000000); assert_eq!(reverse_bits(0b0000000001, 10), 0b1000000000); assert_eq!(reverse_bits(0b1000000000, 10), 0b0000000001); assert_eq!(reverse_bits(0b00000, 5), 0b00000); assert_eq!(reverse_bits(0b01011, 5), 0b11010); } #[test] fn test_reverse_index_bits() { assert_eq!(reverse_index_bits(&[10, 20, 30, 40]), vec![10, 30, 20, 40]); assert_eq!( reverse_index_bits(&[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]), vec![0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15] ); } }