1use crate::Idx;
2use crate::internal_prelude::*;
3use dyn_stack::StackReq;
4use linalg::zip::{Last, Zip};
5use reborrow::*;
6#[track_caller]
33#[inline(never)]
34pub fn swap_cols<N: Shape, T>(a: ColMut<'_, T, N>, b: ColMut<'_, T, N>) {
35 fn swap<T>() -> impl FnMut(Zip<&mut T, Last<&mut T>>) {
36 |unzip!(a, b)| core::mem::swap(a, b)
37 }
38 zip!(a, b).for_each(swap::<T>());
39}
40#[track_caller]
67#[inline]
68pub fn swap_rows<N: Shape, T>(a: RowMut<'_, T, N>, b: RowMut<'_, T, N>) {
69 swap_cols(a.transpose_mut(), b.transpose_mut())
70}
71#[track_caller]
97#[inline]
98pub fn swap_rows_idx<M: Shape, N: Shape, T>(
99 mat: MatMut<'_, T, M, N>,
100 a: Idx<M>,
101 b: Idx<M>,
102) {
103 if a != b {
104 let (a, b) = mat.two_rows_mut(a, b);
105 swap_rows(a, b);
106 }
107}
108#[track_caller]
134#[inline]
135pub fn swap_cols_idx<M: Shape, N: Shape, T>(
136 mat: MatMut<'_, T, M, N>,
137 a: Idx<N>,
138 b: Idx<N>,
139) {
140 if a != b {
141 let (a, b) = mat.two_cols_mut(a, b);
142 swap_cols(a, b);
143 }
144}
145mod permown;
146mod permref;
147pub type Perm<I, N = usize> = generic::Perm<Own<I, N>>;
149pub type PermRef<'a, I, N = usize> = generic::Perm<Ref<'a, I, N>>;
151pub use permown::Own;
152pub use permref::Ref;
153pub mod generic {
155 use core::fmt::Debug;
156 use reborrow::*;
157 #[derive(Copy, Clone)]
159 #[repr(transparent)]
160 pub struct Perm<Inner>(pub Inner);
161 impl<Inner: Debug> Debug for Perm<Inner> {
162 #[inline(always)]
163 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
164 self.0.fmt(f)
165 }
166 }
167 impl<Inner> Perm<Inner> {
168 #[inline(always)]
170 pub fn from_inner_ref(inner: &Inner) -> &Self {
171 unsafe { &*(inner as *const Inner as *const Self) }
172 }
173
174 #[inline(always)]
176 pub fn from_inner_mut(inner: &mut Inner) -> &mut Self {
177 unsafe { &mut *(inner as *mut Inner as *mut Self) }
178 }
179 }
180 impl<Inner> core::ops::Deref for Perm<Inner> {
181 type Target = Inner;
182
183 #[inline(always)]
184 fn deref(&self) -> &Self::Target {
185 &self.0
186 }
187 }
188 impl<Inner> core::ops::DerefMut for Perm<Inner> {
189 #[inline(always)]
190 fn deref_mut(&mut self) -> &mut Self::Target {
191 &mut self.0
192 }
193 }
194 impl<'short, Inner: Reborrow<'short>> Reborrow<'short> for Perm<Inner> {
195 type Target = Perm<Inner::Target>;
196
197 #[inline(always)]
198 fn rb(&'short self) -> Self::Target {
199 Perm(self.0.rb())
200 }
201 }
202 impl<'short, Inner: ReborrowMut<'short>> ReborrowMut<'short> for Perm<Inner> {
203 type Target = Perm<Inner::Target>;
204
205 #[inline(always)]
206 fn rb_mut(&'short mut self) -> Self::Target {
207 Perm(self.0.rb_mut())
208 }
209 }
210 impl<Inner: IntoConst> IntoConst for Perm<Inner> {
211 type Target = Perm<Inner::Target>;
212
213 #[inline(always)]
214 fn into_const(self) -> Self::Target {
215 Perm(self.0.into_const())
216 }
217 }
218}
219use self::linalg::temp_mat_scratch;
220#[inline]
229#[track_caller]
230pub fn permute_cols<I: Index, T: ComplexField>(
231 dst: MatMut<'_, T>,
232 src: MatRef<'_, T>,
233 perm_indices: PermRef<'_, I>,
234) {
235 Assert!(all(
236 src.nrows() == dst.nrows(),
237 src.ncols() == dst.ncols(),
238 perm_indices.arrays().0.len() == src.ncols(),
239 ));
240 permute_rows(
241 dst.transpose_mut(),
242 src.transpose(),
243 perm_indices.canonicalized(),
244 );
245}
246#[inline]
255#[track_caller]
256pub fn permute_rows<I: Index, T: ComplexField>(
257 dst: MatMut<'_, T>,
258 src: MatRef<'_, T>,
259 perm_indices: PermRef<'_, I>,
260) {
261 #[track_caller]
262 fn implementation<I: Index, T: ComplexField>(
263 dst: MatMut<'_, T>,
264 src: MatRef<'_, T>,
265 perm_indices: PermRef<'_, I>,
266 ) {
267 Assert!(all(
268 src.nrows() == dst.nrows(),
269 src.ncols() == dst.ncols(),
270 perm_indices.len() == src.nrows(),
271 ));
272 with_dim!(m, src.nrows());
273 with_dim!(n, src.ncols());
274 let mut dst = dst.as_shape_mut(m, n);
275 let src = src.as_shape(m, n);
276 let perm = perm_indices.as_shape(m).bound_arrays().0;
277 if dst.rb().row_stride().unsigned_abs()
278 < dst.rb().col_stride().unsigned_abs()
279 {
280 for j in n.indices() {
281 for i in m.indices() {
282 dst[(i, j)] = src[(perm[i].zx(), j)].copy();
283 }
284 }
285 } else {
286 for i in m.indices() {
287 let src_i = src.row(perm[i].zx());
288 let mut dst_i = dst.rb_mut().row_mut(i);
289 dst_i.copy_from(src_i);
290 }
291 }
292 }
293 implementation(dst, src, perm_indices.canonicalized())
294}
295pub fn permute_rows_in_place_scratch<I: Index, T: ComplexField>(
298 nrows: usize,
299 ncols: usize,
300) -> StackReq {
301 temp_mat_scratch::<T>(nrows, ncols)
302}
303pub fn permute_cols_in_place_scratch<I: Index, T: ComplexField>(
306 nrows: usize,
307 ncols: usize,
308) -> StackReq {
309 temp_mat_scratch::<T>(nrows, ncols)
310}
311#[inline]
319#[track_caller]
320pub fn permute_rows_in_place<I: Index, T: ComplexField>(
321 matrix: MatMut<'_, T>,
322 perm_indices: PermRef<'_, I>,
323 stack: &mut MemStack,
324) {
325 #[inline]
326 #[track_caller]
327 fn implementation<T: ComplexField, I: Index>(
328 matrix: MatMut<'_, T>,
329 perm_indices: PermRef<'_, I>,
330 stack: &mut MemStack,
331 ) {
332 let mut matrix = matrix;
333 let (mut tmp, _) =
334 unsafe { temp_mat_uninit(matrix.nrows(), matrix.ncols(), stack) };
335 let mut tmp = tmp.as_mat_mut();
336 tmp.copy_from(matrix.rb());
337 permute_rows(matrix.rb_mut(), tmp.rb(), perm_indices);
338 }
339 implementation(matrix, perm_indices.canonicalized(), stack)
340}
341#[inline]
349#[track_caller]
350pub fn permute_cols_in_place<I: Index, T: ComplexField>(
351 matrix: MatMut<'_, T>,
352 perm_indices: PermRef<'_, I>,
353 stack: &mut MemStack,
354) {
355 #[inline]
356 #[track_caller]
357 fn implementation<I: Index, T: ComplexField>(
358 matrix: MatMut<'_, T>,
359 perm_indices: PermRef<'_, I>,
360 stack: &mut MemStack,
361 ) {
362 let mut matrix = matrix;
363 let (mut tmp, _) =
364 unsafe { temp_mat_uninit(matrix.nrows(), matrix.ncols(), stack) };
365 let mut tmp = tmp.as_mat_mut();
366 tmp.copy_from(matrix.rb());
367 permute_cols(matrix.rb_mut(), tmp.rb(), perm_indices);
368 }
369 implementation(matrix, perm_indices.canonicalized(), stack)
370}