1use super::*;
2use crate::utils::bound::{Array, Dim};
3use crate::{Idx, assert};
4#[derive(Debug)]
6pub struct Ref<'a, I: Index, N: Shape = usize> {
7 pub(super) forward: &'a [N::Idx<I>],
8 pub(super) inverse: &'a [N::Idx<I>],
9}
10impl<I: Index, N: Shape> Copy for Ref<'_, I, N> {}
11impl<I: Index, N: Shape> Clone for Ref<'_, I, N> {
12 #[inline]
13 fn clone(&self) -> Self {
14 *self
15 }
16}
17impl<'short, I: Index, N: Shape> Reborrow<'short> for Ref<'_, I, N> {
18 type Target = Ref<'short, I, N>;
19
20 #[inline]
21 fn rb(&'short self) -> Self::Target {
22 *self
23 }
24}
25impl<'short, I: Index, N: Shape> ReborrowMut<'short> for Ref<'_, I, N> {
26 type Target = Ref<'short, I, N>;
27
28 #[inline]
29 fn rb_mut(&'short mut self) -> Self::Target {
30 *self
31 }
32}
33impl<'a, I: Index, N: Shape> IntoConst for Ref<'a, I, N> {
34 type Target = Ref<'a, I, N>;
35
36 #[inline]
37 fn into_const(self) -> Self::Target {
38 self
39 }
40}
41impl<
42 I: Index,
43 N: Shape,
44 Inner: for<'short> Reborrow<'short, Target = Ref<'short, I, N>>,
45> generic::Perm<Inner>
46{
47 #[inline]
49 pub fn as_ref(&self) -> PermRef<'_, I, N> {
50 PermRef { 0: self.0.rb() }
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 PermRef {
60 0: Ref {
61 forward: unsafe {
62 core::slice::from_raw_parts(
63 self.forward.as_ptr() as _,
64 dim.unbound(),
65 )
66 },
67 inverse: unsafe {
68 core::slice::from_raw_parts(
69 self.inverse.as_ptr() as _,
70 dim.unbound(),
71 )
72 },
73 },
74 }
75 }
76
77 #[inline]
87 #[track_caller]
88 pub fn new_checked(
89 forward: &'a [Idx<N, I>],
90 inverse: &'a [Idx<N, I>],
91 dim: N,
92 ) -> Self {
93 #[track_caller]
94 fn check<I: Index>(forward: &[I], inverse: &[I], n: usize) {
95 assert!(all(
96 n <= I::Signed::MAX.zx(),
97 forward.len() == n,
98 inverse.len() == n,
99 ));
100 for (i, &p) in forward.iter().enumerate() {
101 let p = p.to_signed().zx();
102 assert!(p < n);
103 assert!(inverse[p].to_signed().zx() == i);
104 }
105 }
106 check(
107 I::canonicalize(N::cast_idx_slice(forward)),
108 I::canonicalize(N::cast_idx_slice(inverse)),
109 dim.unbound(),
110 );
111 Self {
112 0: Ref { forward, inverse },
113 }
114 }
115
116 #[inline]
125 #[track_caller]
126 pub unsafe fn new_unchecked(
127 forward: &'a [Idx<N, I>],
128 inverse: &'a [Idx<N, I>],
129 dim: N,
130 ) -> Self {
131 assert!(all(
132 dim.unbound() <= I::Signed::MAX.zx(),
133 forward.len() == dim.unbound(),
134 inverse.len() == dim.unbound(),
135 ));
136 Self {
137 0: Ref { forward, inverse },
138 }
139 }
140
141 #[inline]
143 pub fn arrays(self) -> (&'a [Idx<N, I>], &'a [Idx<N, I>]) {
144 (self.forward, self.inverse)
145 }
146
147 #[inline]
149 pub fn len(&self) -> N {
150 unsafe { N::new_unbound(self.forward.len()) }
151 }
152
153 #[inline]
155 pub fn inverse(self) -> Self {
156 Self {
157 0: Ref {
158 forward: self.inverse,
159 inverse: self.forward,
160 },
161 }
162 }
163
164 #[inline]
166 pub fn transpose(self) -> Self {
167 self.inverse()
168 }
169
170 #[inline(always)]
172 pub fn canonicalized(self) -> PermRef<'a, I::FixedWidth, N> {
173 unsafe {
174 PermRef {
175 0: Ref {
176 forward: core::slice::from_raw_parts(
177 self.forward.as_ptr() as _,
178 self.forward.len(),
179 ),
180 inverse: core::slice::from_raw_parts(
181 self.inverse.as_ptr() as _,
182 self.inverse.len(),
183 ),
184 },
185 }
186 }
187 }
188
189 #[inline(always)]
191 pub fn uncanonicalized<J: Index>(self) -> PermRef<'a, J, N> {
192 assert!(core::mem::size_of::<J>() == core::mem::size_of::<I>());
193 unsafe {
194 PermRef {
195 0: Ref {
196 forward: core::slice::from_raw_parts(
197 self.forward.as_ptr() as _,
198 self.forward.len(),
199 ),
200 inverse: core::slice::from_raw_parts(
201 self.inverse.as_ptr() as _,
202 self.inverse.len(),
203 ),
204 },
205 }
206 }
207 }
208}
209impl<'a, 'N, I: Index> PermRef<'a, I, Dim<'N>> {
210 #[inline]
212 pub fn bound_arrays(
213 self,
214 ) -> (
215 &'a Array<'N, Idx<Dim<'N>, I>>,
216 &'a Array<'N, Idx<Dim<'N>, I>>,
217 ) {
218 unsafe {
219 (
220 &*(self.forward as *const [Idx<Dim<'N>, I>]
221 as *const Array<'N, Idx<Dim<'N>, I>>),
222 &*(self.inverse as *const [Idx<Dim<'N>, I>]
223 as *const Array<'N, Idx<Dim<'N>, I>>),
224 )
225 }
226 }
227}