1
Fork 0

Use FieldIdx in FieldsShape

Finally got to the main motivating example from the MCP :)
This commit is contained in:
Scott McMurray 2023-04-02 23:21:09 -07:00
parent bf41e753ec
commit 21bb8ef24e
7 changed files with 133 additions and 101 deletions

View file

@ -24,6 +24,7 @@ pub trait Idx: Copy + 'static + Eq + PartialEq + Debug + Hash {
}
#[inline]
#[must_use = "Use `increment_by` if you wanted to update the index in-place"]
fn plus(self, amount: usize) -> Self {
Self::new(self.index() + amount)
}
@ -283,6 +284,11 @@ impl<I: Idx, T: Clone> ToOwned for IndexSlice<I, T> {
}
impl<I: Idx, T> IndexSlice<I, T> {
#[inline]
pub fn empty() -> &'static Self {
Default::default()
}
#[inline]
pub fn from_raw(raw: &[T]) -> &Self {
let ptr: *const [T] = raw;
@ -398,6 +404,36 @@ impl<I: Idx, T> IndexSlice<I, T> {
}
}
impl<I: Idx, J: Idx> IndexSlice<I, J> {
/// Invert a bijective mapping, i.e. `invert(map)[y] = x` if `map[x] = y`,
/// assuming the values in `self` are a permutation of `0..self.len()`.
///
/// This is used to go between `memory_index` (source field order to memory order)
/// and `inverse_memory_index` (memory order to source field order).
/// See also `FieldsShape::Arbitrary::memory_index` for more details.
// FIXME(eddyb) build a better abstraction for permutations, if possible.
pub fn invert_bijective_mapping(&self) -> IndexVec<J, I> {
debug_assert_eq!(
self.iter().map(|x| x.index() as u128).sum::<u128>(),
(0..self.len() as u128).sum::<u128>(),
"The values aren't 0..N in input {self:?}",
);
let mut inverse = IndexVec::from_elem_n(Idx::new(0), self.len());
for (i1, &i2) in self.iter_enumerated() {
inverse[i2] = i1;
}
debug_assert_eq!(
inverse.iter().map(|x| x.index() as u128).sum::<u128>(),
(0..inverse.len() as u128).sum::<u128>(),
"The values aren't 0..N in result {self:?}",
);
inverse
}
}
/// `IndexVec` is often used as a map, so it provides some map-like APIs.
impl<I: Idx, T> IndexVec<I, Option<T>> {
#[inline]
@ -502,6 +538,13 @@ impl<I: Idx, T> FromIterator<T> for IndexVec<I, T> {
}
}
impl<I: Idx, T, const N: usize> From<[T; N]> for IndexVec<I, T> {
#[inline]
fn from(array: [T; N]) -> Self {
IndexVec::from_raw(array.into())
}
}
impl<I: Idx, T> IntoIterator for IndexVec<I, T> {
type Item = T;
type IntoIter = vec::IntoIter<T>;