diff --git a/util/Cargo.toml b/util/Cargo.toml index a1ab402a..4e0b4b15 100644 --- a/util/Cargo.toml +++ b/util/Cargo.toml @@ -5,3 +5,4 @@ version = "0.1.0" edition = "2021" [dependencies] +rand = { version = "0.8.5", default-features = false, features = ["getrandom"] } diff --git a/util/src/lib.rs b/util/src/lib.rs index b22a4236..eb297bd8 100644 --- a/util/src/lib.rs +++ b/util/src/lib.rs @@ -274,8 +274,50 @@ pub fn branch_hint() { #[cfg(test)] mod tests { + use rand::rngs::OsRng; + use rand::Rng; + use crate::{log2_ceil, log2_strict}; + #[test] + fn test_reverse_index_bits() { + let lengths = [32, 128, 1 << 16]; + let mut rng = OsRng; + for _ in 0..32 { + for length in lengths { + let mut rand_list: Vec = Vec::with_capacity(length); + rand_list.resize_with(length, || rng.gen()); + + let out = super::reverse_index_bits(&rand_list); + let expect = reverse_index_bits_naive(&rand_list); + + for (out, expect) in out.iter().zip(&expect) { + assert_eq!(out, expect); + } + } + } + } + + #[test] + fn test_reverse_index_bits_in_place() { + let lengths = [32, 128, 1 << 16]; + let mut rng = OsRng; + for _ in 0..32 { + for length in lengths { + let mut rand_list: Vec = Vec::with_capacity(length); + rand_list.resize_with(length, || rng.gen()); + + let expect = reverse_index_bits_naive(&rand_list); + + super::reverse_index_bits_in_place(&mut rand_list); + + for (got, expect) in rand_list.iter().zip(&expect) { + assert_eq!(got, expect); + } + } + } + } + #[test] fn test_log2_strict() { assert_eq!(log2_strict(1), 0); @@ -326,4 +368,17 @@ mod tests { assert_eq!(log2_ceil(usize::MAX - 1), usize::BITS as usize); assert_eq!(log2_ceil(usize::MAX), usize::BITS as usize); } + + fn reverse_index_bits_naive(arr: &[T]) -> Vec { + let n = arr.len(); + let n_power = log2_strict(n); + + let mut out = vec![None; n]; + for (i, v) in arr.iter().enumerate() { + let dst = i.reverse_bits() >> (64 - n_power); + out[dst] = Some(*v); + } + + out.into_iter().map(|x| x.unwrap()).collect() + } }