1use super::*;
2use crate::utils::bound::{Array, Dim};
3use crate::{Idx, assert};
4
5#[derive(Debug)]
7pub struct Ref<'a, I: Index, N: Shape = usize> {
8 pub(super) forward: &'a [N::Idx<I>],
9 pub(super) inverse: &'a [N::Idx<I>],
10}
11
12impl<I: Index, N: Shape> Copy for Ref<'_, I, N> {}
13impl<I: Index, N: Shape> Clone for Ref<'_, I, N> {
14 #[inline]
15 fn clone(&self) -> Self {
16 *self
17 }
18}
19
20impl<'short, I: Index, N: Shape> Reborrow<'short> for Ref<'_, I, N> {
21 type Target = Ref<'short, I, N>;
22
23 #[inline]
24 fn rb(&'short self) -> Self::Target {
25 *self
26 }
27}
28impl<'short, I: Index, N: Shape> ReborrowMut<'short> for Ref<'_, I, N> {
29 type Target = Ref<'short, I, N>;
30
31 #[inline]
32 fn rb_mut(&'short mut self) -> Self::Target {
33 *self
34 }
35}
36impl<'a, I: Index, N: Shape> IntoConst for Ref<'a, I, N> {
37 type Target = Ref<'a, I, N>;
38
39 #[inline]
40 fn into_const(self) -> Self::Target {
41 self
42 }
43}
44
45impl<I: Index, N: Shape, Inner: for<'short> Reborrow<'short, Target = Ref<'short, I, N>>> generic::Perm<Inner> {
46 #[inline]
48 pub fn as_ref(&self) -> PermRef<'_, I, N> {
49 PermRef { 0: self.0.rb() }
50 }
51}
52
53impl<'a, I: Index, N: Shape> PermRef<'a, I, N> {
54 #[inline]
57 pub fn as_shape<M: Shape>(self, dim: M) -> PermRef<'a, I, M> {
58 assert!(self.len().unbound() == dim.unbound());
59
60 PermRef {
61 0: Ref {
62 forward: unsafe { core::slice::from_raw_parts(self.forward.as_ptr() as _, dim.unbound()) },
63 inverse: unsafe { core::slice::from_raw_parts(self.inverse.as_ptr() as _, dim.unbound()) },
64 },
65 }
66 }
67
68 #[inline]
76 #[track_caller]
77 pub fn new_checked(forward: &'a [Idx<N, I>], inverse: &'a [Idx<N, I>], dim: N) -> Self {
78 #[track_caller]
79 fn check<I: Index>(forward: &[I], inverse: &[I], n: usize) {
80 assert!(all(n <= I::Signed::MAX.zx(), forward.len() == n, inverse.len() == n,));
81 for (i, &p) in forward.iter().enumerate() {
82 let p = p.to_signed().zx();
83 assert!(p < n);
84 assert!(inverse[p].to_signed().zx() == i);
85 }
86 }
87
88 check(
89 I::canonicalize(N::cast_idx_slice(forward)),
90 I::canonicalize(N::cast_idx_slice(inverse)),
91 dim.unbound(),
92 );
93 Self { 0: Ref { forward, inverse } }
94 }
95
96 #[inline]
103 #[track_caller]
104 pub unsafe fn new_unchecked(forward: &'a [Idx<N, I>], inverse: &'a [Idx<N, I>], dim: N) -> Self {
105 assert!(all(
106 dim.unbound() <= I::Signed::MAX.zx(),
107 forward.len() == dim.unbound(),
108 inverse.len() == dim.unbound(),
109 ));
110 Self { 0: Ref { forward, inverse } }
111 }
112
113 #[inline]
115 pub fn arrays(self) -> (&'a [Idx<N, I>], &'a [Idx<N, I>]) {
116 (self.forward, self.inverse)
117 }
118
119 #[inline]
121 pub fn len(&self) -> N {
122 unsafe { N::new_unbound(self.forward.len()) }
123 }
124
125 #[inline]
127 pub fn inverse(self) -> Self {
128 Self {
129 0: Ref {
130 forward: self.inverse,
131 inverse: self.forward,
132 },
133 }
134 }
135
136 #[inline(always)]
138 pub fn canonicalized(self) -> PermRef<'a, I::FixedWidth, N> {
139 unsafe {
140 PermRef {
141 0: Ref {
142 forward: core::slice::from_raw_parts(self.forward.as_ptr() as _, self.forward.len()),
143 inverse: core::slice::from_raw_parts(self.inverse.as_ptr() as _, self.inverse.len()),
144 },
145 }
146 }
147 }
148
149 #[inline(always)]
151 pub fn uncanonicalized<J: Index>(self) -> PermRef<'a, J, N> {
152 assert!(core::mem::size_of::<J>() == core::mem::size_of::<I>());
153 unsafe {
154 PermRef {
155 0: Ref {
156 forward: core::slice::from_raw_parts(self.forward.as_ptr() as _, self.forward.len()),
157 inverse: core::slice::from_raw_parts(self.inverse.as_ptr() as _, self.inverse.len()),
158 },
159 }
160 }
161 }
162}
163
164impl<'a, 'N, I: Index> PermRef<'a, I, Dim<'N>> {
165 #[inline]
167 pub fn bound_arrays(self) -> (&'a Array<'N, Idx<Dim<'N>, I>>, &'a Array<'N, Idx<Dim<'N>, I>>) {
168 unsafe {
169 (
170 &*(self.forward as *const [Idx<Dim<'N>, I>] as *const Array<'N, Idx<Dim<'N>, I>>),
171 &*(self.inverse as *const [Idx<Dim<'N>, I>] as *const Array<'N, Idx<Dim<'N>, I>>),
172 )
173 }
174 }
175}