Split {Idx, IndexVec, IndexSlice}
into their own modules
This commit is contained in:
parent
64bcb32651
commit
e496fbec92
150 changed files with 472 additions and 454 deletions
|
@ -1,6 +1,3 @@
|
|||
use crate::vec::{Idx, IndexVec};
|
||||
use arrayvec::ArrayVec;
|
||||
use smallvec::{smallvec, SmallVec};
|
||||
use std::fmt;
|
||||
use std::iter;
|
||||
use std::marker::PhantomData;
|
||||
|
@ -9,8 +6,13 @@ use std::ops::{BitAnd, BitAndAssign, BitOrAssign, Bound, Not, Range, RangeBounds
|
|||
use std::rc::Rc;
|
||||
use std::slice;
|
||||
|
||||
use arrayvec::ArrayVec;
|
||||
use smallvec::{smallvec, SmallVec};
|
||||
|
||||
use rustc_macros::{Decodable, Encodable};
|
||||
|
||||
use crate::{Idx, IndexVec};
|
||||
|
||||
use Chunk::*;
|
||||
|
||||
#[cfg(test)]
|
||||
|
|
45
compiler/rustc_index/src/idx.rs
Normal file
45
compiler/rustc_index/src/idx.rs
Normal file
|
@ -0,0 +1,45 @@
|
|||
use std::fmt::Debug;
|
||||
use std::hash::Hash;
|
||||
|
||||
/// Represents some newtyped `usize` wrapper.
|
||||
///
|
||||
/// Purpose: avoid mixing indexes for different bitvector domains.
|
||||
pub trait Idx: Copy + 'static + Eq + PartialEq + Debug + Hash {
|
||||
fn new(idx: usize) -> Self;
|
||||
|
||||
fn index(self) -> usize;
|
||||
|
||||
#[inline]
|
||||
fn increment_by(&mut self, amount: usize) {
|
||||
*self = self.plus(amount);
|
||||
}
|
||||
|
||||
#[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)
|
||||
}
|
||||
}
|
||||
|
||||
impl Idx for usize {
|
||||
#[inline]
|
||||
fn new(idx: usize) -> Self {
|
||||
idx
|
||||
}
|
||||
#[inline]
|
||||
fn index(self) -> usize {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl Idx for u32 {
|
||||
#[inline]
|
||||
fn new(idx: usize) -> Self {
|
||||
assert!(idx <= u32::MAX as usize);
|
||||
idx as u32
|
||||
}
|
||||
#[inline]
|
||||
fn index(self) -> usize {
|
||||
self as usize
|
||||
}
|
||||
}
|
|
@ -3,10 +3,11 @@ use std::marker::PhantomData;
|
|||
use std::ops::RangeBounds;
|
||||
use std::ops::{Bound, Range};
|
||||
|
||||
use crate::vec::Idx;
|
||||
use crate::vec::IndexVec;
|
||||
use smallvec::SmallVec;
|
||||
|
||||
use crate::idx::Idx;
|
||||
use crate::vec::IndexVec;
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
|
|
|
@ -17,7 +17,12 @@
|
|||
pub mod bit_set;
|
||||
#[cfg(feature = "nightly")]
|
||||
pub mod interval;
|
||||
pub mod vec;
|
||||
|
||||
mod idx;
|
||||
mod slice;
|
||||
mod vec;
|
||||
|
||||
pub use {idx::Idx, slice::IndexSlice, vec::IndexVec};
|
||||
|
||||
#[cfg(feature = "rustc_macros")]
|
||||
pub use rustc_macros::newtype_index;
|
||||
|
|
255
compiler/rustc_index/src/slice.rs
Normal file
255
compiler/rustc_index/src/slice.rs
Normal file
|
@ -0,0 +1,255 @@
|
|||
use std::{
|
||||
fmt,
|
||||
marker::PhantomData,
|
||||
ops::{Index, IndexMut},
|
||||
slice,
|
||||
};
|
||||
|
||||
use crate::{idx::Idx, vec::IndexVec};
|
||||
|
||||
/// A view into contiguous `T`s, indexed by `I` rather than by `usize`.
|
||||
///
|
||||
/// One common pattern you'll see is code that uses [`IndexVec::from_elem`]
|
||||
/// to create the storage needed for a particular "universe" (aka the set of all
|
||||
/// the possible keys that need an associated value) then passes that working
|
||||
/// area as `&mut IndexSlice<I, T>` to clarify that nothing will be added nor
|
||||
/// removed during processing (and, as a bonus, to chase fewer pointers).
|
||||
#[derive(PartialEq, Eq, Hash)]
|
||||
#[repr(transparent)]
|
||||
pub struct IndexSlice<I: Idx, T> {
|
||||
_marker: PhantomData<fn(&I)>,
|
||||
pub raw: [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;
|
||||
// SAFETY: `IndexSlice` is `repr(transparent)` over a normal slice
|
||||
unsafe { &*(ptr as *const Self) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn from_raw_mut(raw: &mut [T]) -> &mut Self {
|
||||
let ptr: *mut [T] = raw;
|
||||
// SAFETY: `IndexSlice` is `repr(transparent)` over a normal slice
|
||||
unsafe { &mut *(ptr as *mut Self) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn len(&self) -> usize {
|
||||
self.raw.len()
|
||||
}
|
||||
|
||||
/// Gives the next index that will be assigned when `push` is called.
|
||||
///
|
||||
/// Manual bounds checks can be done using `idx < slice.next_index()`
|
||||
/// (as opposed to `idx.index() < slice.len()`).
|
||||
#[inline]
|
||||
pub fn next_index(&self) -> I {
|
||||
I::new(self.len())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.raw.is_empty()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn iter(&self) -> slice::Iter<'_, T> {
|
||||
self.raw.iter()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn iter_enumerated(
|
||||
&self,
|
||||
) -> impl DoubleEndedIterator<Item = (I, &T)> + ExactSizeIterator + '_ {
|
||||
self.raw.iter().enumerate().map(|(n, t)| (I::new(n), t))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn indices(
|
||||
&self,
|
||||
) -> impl DoubleEndedIterator<Item = I> + ExactSizeIterator + Clone + 'static {
|
||||
(0..self.len()).map(|n| I::new(n))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn iter_mut(&mut self) -> slice::IterMut<'_, T> {
|
||||
self.raw.iter_mut()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn iter_enumerated_mut(
|
||||
&mut self,
|
||||
) -> impl DoubleEndedIterator<Item = (I, &mut T)> + ExactSizeIterator + '_ {
|
||||
self.raw.iter_mut().enumerate().map(|(n, t)| (I::new(n), t))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn last_index(&self) -> Option<I> {
|
||||
self.len().checked_sub(1).map(I::new)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn swap(&mut self, a: I, b: I) {
|
||||
self.raw.swap(a.index(), b.index())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn get(&self, index: I) -> Option<&T> {
|
||||
self.raw.get(index.index())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn get_mut(&mut self, index: I) -> Option<&mut T> {
|
||||
self.raw.get_mut(index.index())
|
||||
}
|
||||
|
||||
/// Returns mutable references to two distinct elements, `a` and `b`.
|
||||
///
|
||||
/// Panics if `a == b`.
|
||||
#[inline]
|
||||
pub fn pick2_mut(&mut self, a: I, b: I) -> (&mut T, &mut T) {
|
||||
let (ai, bi) = (a.index(), b.index());
|
||||
assert!(ai != bi);
|
||||
|
||||
if ai < bi {
|
||||
let (c1, c2) = self.raw.split_at_mut(bi);
|
||||
(&mut c1[ai], &mut c2[0])
|
||||
} else {
|
||||
let (c2, c1) = self.pick2_mut(b, a);
|
||||
(c1, c2)
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns mutable references to three distinct elements.
|
||||
///
|
||||
/// Panics if the elements are not distinct.
|
||||
#[inline]
|
||||
pub fn pick3_mut(&mut self, a: I, b: I, c: I) -> (&mut T, &mut T, &mut T) {
|
||||
let (ai, bi, ci) = (a.index(), b.index(), c.index());
|
||||
assert!(ai != bi && bi != ci && ci != ai);
|
||||
let len = self.raw.len();
|
||||
assert!(ai < len && bi < len && ci < len);
|
||||
let ptr = self.raw.as_mut_ptr();
|
||||
unsafe { (&mut *ptr.add(ai), &mut *ptr.add(bi), &mut *ptr.add(ci)) }
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: Idx, T: Ord> IndexSlice<I, T> {
|
||||
#[inline]
|
||||
pub fn binary_search(&self, value: &T) -> Result<I, I> {
|
||||
match self.raw.binary_search(value) {
|
||||
Ok(i) => Ok(Idx::new(i)),
|
||||
Err(i) => Err(Idx::new(i)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Whether `IndexSlice` is `Send` depends only on the data,
|
||||
// not the phantom data.
|
||||
unsafe impl<I: Idx, T> Send for IndexSlice<I, T> where T: Send {}
|
||||
|
||||
impl<I: Idx, T: fmt::Debug> fmt::Debug for IndexSlice<I, T> {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt::Debug::fmt(&self.raw, fmt)
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: Idx, T> Index<I> for IndexSlice<I, T> {
|
||||
type Output = T;
|
||||
|
||||
#[inline]
|
||||
fn index(&self, index: I) -> &T {
|
||||
&self.raw[index.index()]
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: Idx, T> IndexMut<I> for IndexSlice<I, T> {
|
||||
#[inline]
|
||||
fn index_mut(&mut self, index: I) -> &mut T {
|
||||
&mut self.raw[index.index()]
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: Idx, T: Clone> ToOwned for IndexSlice<I, T> {
|
||||
type Owned = IndexVec<I, T>;
|
||||
|
||||
fn to_owned(&self) -> IndexVec<I, T> {
|
||||
IndexVec::from_raw(self.raw.to_owned())
|
||||
}
|
||||
|
||||
fn clone_into(&self, target: &mut IndexVec<I, T>) {
|
||||
self.raw.clone_into(&mut target.raw)
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: Idx, T> Default for &IndexSlice<I, T> {
|
||||
#[inline]
|
||||
fn default() -> Self {
|
||||
IndexSlice::from_raw(Default::default())
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: Idx, T> Default for &mut IndexSlice<I, T> {
|
||||
#[inline]
|
||||
fn default() -> Self {
|
||||
IndexSlice::from_raw_mut(Default::default())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, I: Idx, T> IntoIterator for &'a IndexSlice<I, T> {
|
||||
type Item = &'a T;
|
||||
type IntoIter = slice::Iter<'a, T>;
|
||||
|
||||
#[inline]
|
||||
fn into_iter(self) -> slice::Iter<'a, T> {
|
||||
self.raw.iter()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, I: Idx, T> IntoIterator for &'a mut IndexSlice<I, T> {
|
||||
type Item = &'a mut T;
|
||||
type IntoIter = slice::IterMut<'a, T>;
|
||||
|
||||
#[inline]
|
||||
fn into_iter(self) -> slice::IterMut<'a, T> {
|
||||
self.raw.iter_mut()
|
||||
}
|
||||
}
|
|
@ -3,55 +3,14 @@ use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
|
|||
|
||||
use std::borrow::{Borrow, BorrowMut};
|
||||
use std::fmt;
|
||||
use std::fmt::Debug;
|
||||
use std::hash::Hash;
|
||||
use std::marker::PhantomData;
|
||||
use std::ops::{Deref, DerefMut, Index, IndexMut, RangeBounds};
|
||||
use std::ops::{Deref, DerefMut, RangeBounds};
|
||||
use std::slice;
|
||||
use std::vec;
|
||||
|
||||
/// Represents some newtyped `usize` wrapper.
|
||||
///
|
||||
/// Purpose: avoid mixing indexes for different bitvector domains.
|
||||
pub trait Idx: Copy + 'static + Eq + PartialEq + Debug + Hash {
|
||||
fn new(idx: usize) -> Self;
|
||||
|
||||
fn index(self) -> usize;
|
||||
|
||||
#[inline]
|
||||
fn increment_by(&mut self, amount: usize) {
|
||||
*self = self.plus(amount);
|
||||
}
|
||||
|
||||
#[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)
|
||||
}
|
||||
}
|
||||
|
||||
impl Idx for usize {
|
||||
#[inline]
|
||||
fn new(idx: usize) -> Self {
|
||||
idx
|
||||
}
|
||||
#[inline]
|
||||
fn index(self) -> usize {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl Idx for u32 {
|
||||
#[inline]
|
||||
fn new(idx: usize) -> Self {
|
||||
assert!(idx <= u32::MAX as usize);
|
||||
idx as u32
|
||||
}
|
||||
#[inline]
|
||||
fn index(self) -> usize {
|
||||
self as usize
|
||||
}
|
||||
}
|
||||
use crate::idx::Idx;
|
||||
use crate::slice::IndexSlice;
|
||||
|
||||
/// An owned contiguous collection of `T`s, indexed by `I` rather than by `usize`.
|
||||
///
|
||||
|
@ -66,28 +25,10 @@ pub struct IndexVec<I: Idx, T> {
|
|||
_marker: PhantomData<fn(&I)>,
|
||||
}
|
||||
|
||||
/// A view into contiguous `T`s, indexed by `I` rather than by `usize`.
|
||||
///
|
||||
/// One common pattern you'll see is code that uses [`IndexVec::from_elem`]
|
||||
/// to create the storage needed for a particular "universe" (aka the set of all
|
||||
/// the possible keys that need an associated value) then passes that working
|
||||
/// area as `&mut IndexSlice<I, T>` to clarify that nothing will be added nor
|
||||
/// removed during processing (and, as a bonus, to chase fewer pointers).
|
||||
#[derive(PartialEq, Eq, Hash)]
|
||||
#[repr(transparent)]
|
||||
pub struct IndexSlice<I: Idx, T> {
|
||||
_marker: PhantomData<fn(&I)>,
|
||||
pub raw: [T],
|
||||
}
|
||||
|
||||
// Whether `IndexVec` is `Send` depends only on the data,
|
||||
// not the phantom data.
|
||||
unsafe impl<I: Idx, T> Send for IndexVec<I, T> where T: Send {}
|
||||
|
||||
// Whether `IndexSlice` is `Send` depends only on the data,
|
||||
// not the phantom data.
|
||||
unsafe impl<I: Idx, T> Send for IndexSlice<I, T> where T: Send {}
|
||||
|
||||
#[cfg(feature = "rustc_serialize")]
|
||||
impl<S: Encoder, I: Idx, T: Encodable<S>> Encodable<S> for IndexVec<I, T> {
|
||||
fn encode(&self, s: &mut S) {
|
||||
|
@ -108,12 +49,6 @@ impl<I: Idx, T: fmt::Debug> fmt::Debug for IndexVec<I, T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<I: Idx, T: fmt::Debug> fmt::Debug for IndexSlice<I, T> {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt::Debug::fmt(&self.raw, fmt)
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: Idx, T> IndexVec<I, T> {
|
||||
#[inline]
|
||||
pub fn new() -> Self {
|
||||
|
@ -283,169 +218,6 @@ impl<I: Idx, T> BorrowMut<IndexSlice<I, T>> for IndexVec<I, T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<I: Idx, T: Clone> ToOwned for IndexSlice<I, T> {
|
||||
type Owned = IndexVec<I, T>;
|
||||
|
||||
fn to_owned(&self) -> IndexVec<I, T> {
|
||||
IndexVec::from_raw(self.raw.to_owned())
|
||||
}
|
||||
|
||||
fn clone_into(&self, target: &mut IndexVec<I, T>) {
|
||||
self.raw.clone_into(&mut target.raw)
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
// SAFETY: `IndexSlice` is `repr(transparent)` over a normal slice
|
||||
unsafe { &*(ptr as *const Self) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn from_raw_mut(raw: &mut [T]) -> &mut Self {
|
||||
let ptr: *mut [T] = raw;
|
||||
// SAFETY: `IndexSlice` is `repr(transparent)` over a normal slice
|
||||
unsafe { &mut *(ptr as *mut Self) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn len(&self) -> usize {
|
||||
self.raw.len()
|
||||
}
|
||||
|
||||
/// Gives the next index that will be assigned when `push` is called.
|
||||
///
|
||||
/// Manual bounds checks can be done using `idx < slice.next_index()`
|
||||
/// (as opposed to `idx.index() < slice.len()`).
|
||||
#[inline]
|
||||
pub fn next_index(&self) -> I {
|
||||
I::new(self.len())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.raw.is_empty()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn iter(&self) -> slice::Iter<'_, T> {
|
||||
self.raw.iter()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn iter_enumerated(
|
||||
&self,
|
||||
) -> impl DoubleEndedIterator<Item = (I, &T)> + ExactSizeIterator + '_ {
|
||||
self.raw.iter().enumerate().map(|(n, t)| (I::new(n), t))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn indices(
|
||||
&self,
|
||||
) -> impl DoubleEndedIterator<Item = I> + ExactSizeIterator + Clone + 'static {
|
||||
(0..self.len()).map(|n| I::new(n))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn iter_mut(&mut self) -> slice::IterMut<'_, T> {
|
||||
self.raw.iter_mut()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn iter_enumerated_mut(
|
||||
&mut self,
|
||||
) -> impl DoubleEndedIterator<Item = (I, &mut T)> + ExactSizeIterator + '_ {
|
||||
self.raw.iter_mut().enumerate().map(|(n, t)| (I::new(n), t))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn last_index(&self) -> Option<I> {
|
||||
self.len().checked_sub(1).map(I::new)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn swap(&mut self, a: I, b: I) {
|
||||
self.raw.swap(a.index(), b.index())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn get(&self, index: I) -> Option<&T> {
|
||||
self.raw.get(index.index())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn get_mut(&mut self, index: I) -> Option<&mut T> {
|
||||
self.raw.get_mut(index.index())
|
||||
}
|
||||
|
||||
/// Returns mutable references to two distinct elements, `a` and `b`.
|
||||
///
|
||||
/// Panics if `a == b`.
|
||||
#[inline]
|
||||
pub fn pick2_mut(&mut self, a: I, b: I) -> (&mut T, &mut T) {
|
||||
let (ai, bi) = (a.index(), b.index());
|
||||
assert!(ai != bi);
|
||||
|
||||
if ai < bi {
|
||||
let (c1, c2) = self.raw.split_at_mut(bi);
|
||||
(&mut c1[ai], &mut c2[0])
|
||||
} else {
|
||||
let (c2, c1) = self.pick2_mut(b, a);
|
||||
(c1, c2)
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns mutable references to three distinct elements.
|
||||
///
|
||||
/// Panics if the elements are not distinct.
|
||||
#[inline]
|
||||
pub fn pick3_mut(&mut self, a: I, b: I, c: I) -> (&mut T, &mut T, &mut T) {
|
||||
let (ai, bi, ci) = (a.index(), b.index(), c.index());
|
||||
assert!(ai != bi && bi != ci && ci != ai);
|
||||
let len = self.raw.len();
|
||||
assert!(ai < len && bi < len && ci < len);
|
||||
let ptr = self.raw.as_mut_ptr();
|
||||
unsafe { (&mut *ptr.add(ai), &mut *ptr.add(bi), &mut *ptr.add(ci)) }
|
||||
}
|
||||
}
|
||||
|
||||
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]
|
||||
|
@ -471,32 +243,6 @@ impl<I: Idx, T: Clone> IndexVec<I, T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<I: Idx, T: Ord> IndexSlice<I, T> {
|
||||
#[inline]
|
||||
pub fn binary_search(&self, value: &T) -> Result<I, I> {
|
||||
match self.raw.binary_search(value) {
|
||||
Ok(i) => Ok(Idx::new(i)),
|
||||
Err(i) => Err(Idx::new(i)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: Idx, T> Index<I> for IndexSlice<I, T> {
|
||||
type Output = T;
|
||||
|
||||
#[inline]
|
||||
fn index(&self, index: I) -> &T {
|
||||
&self.raw[index.index()]
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: Idx, T> IndexMut<I> for IndexSlice<I, T> {
|
||||
#[inline]
|
||||
fn index_mut(&mut self, index: I) -> &mut T {
|
||||
&mut self.raw[index.index()]
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: Idx, T> Default for IndexVec<I, T> {
|
||||
#[inline]
|
||||
fn default() -> Self {
|
||||
|
@ -504,20 +250,6 @@ impl<I: Idx, T> Default for IndexVec<I, T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<I: Idx, T> Default for &IndexSlice<I, T> {
|
||||
#[inline]
|
||||
fn default() -> Self {
|
||||
IndexSlice::from_raw(Default::default())
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: Idx, T> Default for &mut IndexSlice<I, T> {
|
||||
#[inline]
|
||||
fn default() -> Self {
|
||||
IndexSlice::from_raw_mut(Default::default())
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: Idx, T> Extend<T> for IndexVec<I, T> {
|
||||
#[inline]
|
||||
fn extend<J: IntoIterator<Item = T>>(&mut self, iter: J) {
|
||||
|
@ -584,25 +316,5 @@ impl<'a, I: Idx, T> IntoIterator for &'a mut IndexVec<I, T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a, I: Idx, T> IntoIterator for &'a IndexSlice<I, T> {
|
||||
type Item = &'a T;
|
||||
type IntoIter = slice::Iter<'a, T>;
|
||||
|
||||
#[inline]
|
||||
fn into_iter(self) -> slice::Iter<'a, T> {
|
||||
self.raw.iter()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, I: Idx, T> IntoIterator for &'a mut IndexSlice<I, T> {
|
||||
type Item = &'a mut T;
|
||||
type IntoIter = slice::IterMut<'a, T>;
|
||||
|
||||
#[inline]
|
||||
fn into_iter(self) -> slice::IterMut<'a, T> {
|
||||
self.raw.iter_mut()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue