use super::*;
use crate::{assert, Idx};
#[derive(Debug, Clone)]
pub struct Perm<I: Index, N: Shape = usize> {
pub(super) forward: alloc::boxed::Box<[N::Idx<I>]>,
pub(super) inverse: alloc::boxed::Box<[N::Idx<I>]>,
}
impl<I: Index, N: Shape> Perm<I, N> {
#[inline]
pub fn as_ref(&self) -> PermRef<'_, I, N> {
PermRef {
forward: &self.forward,
inverse: &self.inverse,
}
}
#[inline]
pub fn as_shape<M: Shape>(&self, dim: M) -> PermRef<'_, I, M> {
self.as_ref().as_shape(dim)
}
#[inline]
pub fn into_shape<M: Shape>(self, dim: M) -> Perm<I, M> {
assert!(self.len().unbound() == dim.unbound());
Perm {
forward: unsafe {
alloc::boxed::Box::from_raw(alloc::boxed::Box::into_raw(self.forward) as _)
},
inverse: unsafe {
alloc::boxed::Box::from_raw(alloc::boxed::Box::into_raw(self.inverse) as _)
},
}
}
#[inline]
#[track_caller]
pub fn new_checked(
forward: alloc::boxed::Box<[Idx<N, I>]>,
inverse: alloc::boxed::Box<[Idx<N, I>]>,
dim: N,
) -> Self {
PermRef::<'_, I, N>::new_checked(&forward, &inverse, dim);
Self { forward, inverse }
}
#[inline]
#[track_caller]
pub unsafe fn new_unchecked(
forward: alloc::boxed::Box<[Idx<N, I>]>,
inverse: alloc::boxed::Box<[Idx<N, I>]>,
) -> Self {
let n = forward.len();
assert!(all(
forward.len() == inverse.len(),
n <= I::Signed::MAX.zx(),
));
Self { forward, inverse }
}
#[inline]
pub fn into_arrays(
self,
) -> (
alloc::boxed::Box<[Idx<N, I>]>,
alloc::boxed::Box<[Idx<N, I>]>,
) {
(self.forward, self.inverse)
}
#[inline]
pub fn len(&self) -> N {
unsafe { N::new_unbound(self.forward.len()) }
}
#[inline]
pub fn into_inverse(self) -> Self {
Self {
forward: self.inverse,
inverse: self.forward,
}
}
}