mirror of
https://github.com/logos-storage/plonky2.git
synced 2026-01-14 19:53:08 +00:00
* Split into crates
I kept other changes to a minimum, so 95% of this is just moving things. One complication that came up is that since `PrimeField` is now outside the plonky2 crate, these two impls now conflict:
```
impl<F: PrimeField> From<HashOut<F>> for Vec<u8> { ... }
impl<F: PrimeField> From<HashOut<F>> for Vec<F> { ... }
```
with this note:
```
note: upstream crates may add a new impl of trait `plonky2_field::field_types::PrimeField` for type `u8` in future versions
```
I worked around this by adding a `GenericHashOut` trait with methods like `to_bytes()` instead of overloading `From`/`Into`. Personally I prefer the explicitness anyway.
* Move out permutation network stuff also
* Fix imports
* Fix import
* Also move out insertion
* Comment
* fmt
* PR feedback
76 lines
2.1 KiB
Rust
76 lines
2.1 KiB
Rust
use std::collections::HashMap;
|
|
use std::hash::Hash;
|
|
|
|
use bimap::BiMap;
|
|
|
|
/// Given two lists which are permutations of one another, creates a BiMap which maps an index in
|
|
/// one list to an index in the other list with the same associated value.
|
|
///
|
|
/// If the lists contain duplicates, then multiple permutations with this property exist, and an
|
|
/// arbitrary one of them will be returned.
|
|
pub fn bimap_from_lists<T: Eq + Hash>(a: Vec<T>, b: Vec<T>) -> BiMap<usize, usize> {
|
|
assert_eq!(a.len(), b.len(), "Vectors differ in length");
|
|
|
|
let mut b_values_to_indices = HashMap::new();
|
|
for (i, value) in b.iter().enumerate() {
|
|
b_values_to_indices
|
|
.entry(value)
|
|
.or_insert_with(Vec::new)
|
|
.push(i);
|
|
}
|
|
|
|
let mut bimap = BiMap::new();
|
|
for (i, value) in a.iter().enumerate() {
|
|
if let Some(j) = b_values_to_indices.get_mut(&value).and_then(Vec::pop) {
|
|
bimap.insert(i, j);
|
|
} else {
|
|
panic!("Value in first list not found in second list");
|
|
}
|
|
}
|
|
|
|
bimap
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use crate::bimap::bimap_from_lists;
|
|
|
|
#[test]
|
|
fn empty_lists() {
|
|
let empty: Vec<char> = Vec::new();
|
|
let bimap = bimap_from_lists(empty.clone(), empty);
|
|
assert!(bimap.is_empty());
|
|
}
|
|
|
|
#[test]
|
|
fn without_duplicates() {
|
|
let bimap = bimap_from_lists(vec!['a', 'b', 'c'], vec!['b', 'c', 'a']);
|
|
assert_eq!(bimap.get_by_left(&0), Some(&2));
|
|
assert_eq!(bimap.get_by_left(&1), Some(&0));
|
|
assert_eq!(bimap.get_by_left(&2), Some(&1));
|
|
}
|
|
|
|
#[test]
|
|
fn with_duplicates() {
|
|
let first = vec!['a', 'a', 'b'];
|
|
let second = vec!['a', 'b', 'a'];
|
|
let bimap = bimap_from_lists(first.clone(), second.clone());
|
|
for i in 0..3 {
|
|
let j = *bimap.get_by_left(&i).unwrap();
|
|
assert_eq!(first[i], second[j]);
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
#[should_panic]
|
|
fn lengths_differ() {
|
|
bimap_from_lists(vec!['a', 'a', 'b'], vec!['a', 'b']);
|
|
}
|
|
|
|
#[test]
|
|
#[should_panic]
|
|
fn not_a_permutation() {
|
|
bimap_from_lists(vec!['a', 'a', 'b'], vec!['a', 'b', 'b']);
|
|
}
|
|
}
|