use super::*;
use crate::utils::bound::{Array, Dim};
use crate::{Idx, assert};
#[derive(Debug)]
pub struct Ref<'a, I: Index, N: Shape = usize> {
pub(super) forward: &'a [N::Idx<I>],
pub(super) inverse: &'a [N::Idx<I>],
}
impl<I: Index, N: Shape> Copy for Ref<'_, I, N> {}
impl<I: Index, N: Shape> Clone for Ref<'_, I, N> {
#[inline]
fn clone(&self) -> Self {
*self
}
}
impl<'short, I: Index, N: Shape> Reborrow<'short> for Ref<'_, I, N> {
type Target = Ref<'short, I, N>;
#[inline]
fn rb(&'short self) -> Self::Target {
*self
}
}
impl<'short, I: Index, N: Shape> ReborrowMut<'short> for Ref<'_, I, N> {
type Target = Ref<'short, I, N>;
#[inline]
fn rb_mut(&'short mut self) -> Self::Target {
*self
}
}
impl<'a, I: Index, N: Shape> IntoConst for Ref<'a, I, N> {
type Target = Ref<'a, I, N>;
#[inline]
fn into_const(self) -> Self::Target {
self
}
}
impl<
I: Index,
N: Shape,
Inner: for<'short> Reborrow<'short, Target = Ref<'short, I, N>>,
> generic::Perm<Inner>
{
#[inline]
pub fn as_ref(&self) -> PermRef<'_, I, N> {
PermRef { 0: self.0.rb() }
}
}
impl<'a, I: Index, N: Shape> PermRef<'a, I, N> {
#[inline]
pub fn as_shape<M: Shape>(self, dim: M) -> PermRef<'a, I, M> {
assert!(self.len().unbound() == dim.unbound());
PermRef {
0: Ref {
forward: unsafe {
core::slice::from_raw_parts(
self.forward.as_ptr() as _,
dim.unbound(),
)
},
inverse: unsafe {
core::slice::from_raw_parts(
self.inverse.as_ptr() as _,
dim.unbound(),
)
},
},
}
}
#[inline]
#[track_caller]
pub fn new_checked(
forward: &'a [Idx<N, I>],
inverse: &'a [Idx<N, I>],
dim: N,
) -> Self {
#[track_caller]
fn check<I: Index>(forward: &[I], inverse: &[I], n: usize) {
assert!(all(
n <= I::Signed::MAX.zx(),
forward.len() == n,
inverse.len() == n,
));
for (i, &p) in forward.iter().enumerate() {
let p = p.to_signed().zx();
assert!(p < n);
assert!(inverse[p].to_signed().zx() == i);
}
}
check(
I::canonicalize(N::cast_idx_slice(forward)),
I::canonicalize(N::cast_idx_slice(inverse)),
dim.unbound(),
);
Self {
0: Ref { forward, inverse },
}
}
#[inline]
#[track_caller]
pub unsafe fn new_unchecked(
forward: &'a [Idx<N, I>],
inverse: &'a [Idx<N, I>],
dim: N,
) -> Self {
assert!(all(
dim.unbound() <= I::Signed::MAX.zx(),
forward.len() == dim.unbound(),
inverse.len() == dim.unbound(),
));
Self {
0: Ref { forward, inverse },
}
}
#[inline]
pub fn arrays(self) -> (&'a [Idx<N, I>], &'a [Idx<N, I>]) {
(self.forward, self.inverse)
}
#[inline]
pub fn len(&self) -> N {
unsafe { N::new_unbound(self.forward.len()) }
}
#[inline]
pub fn inverse(self) -> Self {
Self {
0: Ref {
forward: self.inverse,
inverse: self.forward,
},
}
}
#[inline]
pub fn transpose(self) -> Self {
self.inverse()
}
#[inline(always)]
pub fn canonicalized(self) -> PermRef<'a, I::FixedWidth, N> {
unsafe {
PermRef {
0: Ref {
forward: core::slice::from_raw_parts(
self.forward.as_ptr() as _,
self.forward.len(),
),
inverse: core::slice::from_raw_parts(
self.inverse.as_ptr() as _,
self.inverse.len(),
),
},
}
}
}
#[inline(always)]
pub fn uncanonicalized<J: Index>(self) -> PermRef<'a, J, N> {
assert!(core::mem::size_of::<J>() == core::mem::size_of::<I>());
unsafe {
PermRef {
0: Ref {
forward: core::slice::from_raw_parts(
self.forward.as_ptr() as _,
self.forward.len(),
),
inverse: core::slice::from_raw_parts(
self.inverse.as_ptr() as _,
self.inverse.len(),
),
},
}
}
}
}
impl<'a, 'N, I: Index> PermRef<'a, I, Dim<'N>> {
#[inline]
pub fn bound_arrays(
self,
) -> (
&'a Array<'N, Idx<Dim<'N>, I>>,
&'a Array<'N, Idx<Dim<'N>, I>>,
) {
unsafe {
(
&*(self.forward as *const [Idx<Dim<'N>, I>]
as *const Array<'N, Idx<Dim<'N>, I>>),
&*(self.inverse as *const [Idx<Dim<'N>, I>]
as *const Array<'N, Idx<Dim<'N>, I>>),
)
}
}
}