Skip to main content

feanor_math/matrix/
submatrix.rs

1use std::fmt::{Debug, Formatter};
2use std::marker::PhantomData;
3use std::ops::{Deref, Range};
4use std::ptr::{NonNull, addr_of_mut};
5
6#[cfg(feature = "ndarray")]
7use ndarray::{ArrayBase, DataMut, Ix2};
8
9use crate::seq::{SwappableVectorViewMut, VectorView, VectorViewMut};
10
11/// Trait for objects that can be considered a contiguous part of memory. In particular,
12/// the pointer returned by `get_pointer()` should be interpreted as the pointer to the first
13/// element of a range of elements of type `T` (basically a C-style array). In some
14/// sense, this is thus the unsafe equivalent of `Deref<Target = [T]>`.
15///
16/// # Safety
17///
18/// Since we use this to provide iterators that do not follow the natural layout of
19/// the data, the following restrictions are necessary:
20///  - Calling multiple times `get_pointer()` on the same reference is valid, and all resulting
21///    pointers are valid to be dereferenced.
22///  - In the above situation, we may also keep multiple mutable references that were obtained by
23///    dereferencing the pointers, *as long as they don't alias, i.e. refer to different elements*.
24///  - If `Self: Sync` then `T: Send` and the above situation should be valid even if the pointers
25///    returned by `get_pointer()` are produced and used from different threads.
26pub unsafe trait AsPointerToSlice<T> {
27    /// Returns a pointer to the first element of multiple, contiguous `T`s.
28    ///
29    /// # Safety
30    ///
31    /// Requires that `self_` is a pointer to a valid object of this type. Note that
32    /// it is legal to call this function while there exist mutable references to `T`s
33    /// that were obtained by dereferencing an earlier result of `get_pointer()`. This
34    /// means that in some situations, the passed `self_` may not be dereferenced without
35    /// violating the aliasing rules.
36    ///
37    /// However, it must be guaranteed that no mutable reference to an part of `self_` that
38    /// is not pointed to by a result of `get_pointer()` exists. Immutable references may exist.
39    ///
40    /// For additional detail, see the trait-level doc [`AsPointerToSlice`].
41    unsafe fn get_pointer(self_: NonNull<Self>) -> NonNull<T>;
42}
43
44unsafe impl<T> AsPointerToSlice<T> for Vec<T> {
45    unsafe fn get_pointer(self_: NonNull<Self>) -> NonNull<T> {
46        // Safe, because "This method guarantees that for the purpose of the aliasing model, this
47        // method does not materialize a reference to the underlying slice" (quote from the doc of
48        // [`Vec::as_mut_ptr()`])
49        unsafe { NonNull::new((*self_.as_ptr()).as_mut_ptr()).unwrap() }
50    }
51}
52
53/// Newtype for `[T; SIZE]` that implements `Deref<Target = [T]>` so that it can be used
54/// to store columns and access them through [`Submatrix`].
55///
56/// This is necessary, since [`Submatrix::from_2d`] requires that `V: Deref<Target = [T]>`.
57#[repr(transparent)]
58#[derive(Clone, Copy, PartialEq, Eq)]
59pub struct DerefArray<T, const SIZE: usize> {
60    /// The wrapped array
61    pub data: [T; SIZE],
62}
63
64impl<T: std::fmt::Debug, const SIZE: usize> std::fmt::Debug for DerefArray<T, SIZE> {
65    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { self.data.fmt(f) }
66}
67
68impl<T, const SIZE: usize> From<[T; SIZE]> for DerefArray<T, SIZE> {
69    fn from(value: [T; SIZE]) -> Self { Self { data: value } }
70}
71
72impl<'a, T, const SIZE: usize> From<&'a [T; SIZE]> for &'a DerefArray<T, SIZE> {
73    fn from(value: &'a [T; SIZE]) -> Self { unsafe { std::mem::transmute(value) } }
74}
75
76impl<'a, T, const SIZE: usize> From<&'a mut [T; SIZE]> for &'a mut DerefArray<T, SIZE> {
77    fn from(value: &'a mut [T; SIZE]) -> Self { unsafe { std::mem::transmute(value) } }
78}
79
80impl<T, const SIZE: usize> Deref for DerefArray<T, SIZE> {
81    type Target = [T];
82
83    fn deref(&self) -> &Self::Target { &self.data[..] }
84}
85
86unsafe impl<T, const SIZE: usize> AsPointerToSlice<T> for DerefArray<T, SIZE> {
87    unsafe fn get_pointer(self_: NonNull<Self>) -> NonNull<T> {
88        unsafe {
89            let self_ptr = self_.as_ptr();
90            let data_ptr = addr_of_mut!((*self_ptr).data);
91            NonNull::new((*data_ptr).as_mut_ptr()).unwrap()
92        }
93    }
94}
95
96/// Represents a contiguous batch of `T`s by their first element.
97/// In other words, a pointer to the batch is equal to a pointer to
98/// the first value.
99#[repr(transparent)]
100pub struct AsFirstElement<T>(T);
101
102unsafe impl<'a, T> AsPointerToSlice<T> for AsFirstElement<T> {
103    unsafe fn get_pointer(self_: NonNull<Self>) -> NonNull<T> { unsafe { std::mem::transmute(self_) } }
104}
105
106/// A submatrix that works on raw pointers, thus does not care about mutability
107/// and borrowing. It already takes care about bounds checking and indexing.
108/// Nevertheless, it is quite difficult to use this correctly, best not use it at
109/// all. I mainly made it public to allow doctests.
110///
111/// More concretely, when having a 2d-structure, given by a sequence of `V`s, we
112/// can consider a rectangular sub-block. This is encapsulated by SubmatrixRaw.
113///
114/// # Safety
115///
116/// The individual safety contracts are described at the corresponding functions.
117/// However, in total be careful when actuall transforming the entry pointers
118/// (given by [`SubmatrixRaw::entry_at`] or [`SubmatrixRaw::row_at`]) into references.
119/// Since `SubmatrixRaw` does not borrow-check (and is `Copy`!), it is easy to create
120/// aliasing pointers, that must not be converted into references.
121///
122/// ## Example of illegal use
123/// ```rust
124/// # use feanor_math::matrix::*;
125/// # use core::ptr::NonNull;
126/// let mut data = [1, 2, 3];
127/// // this is actuall safe and intended use
128/// let mut matrix = unsafe {
129///     SubmatrixRaw::<AsFirstElement<i64>, i64>::new(
130///         std::mem::transmute(NonNull::new(data.as_mut_ptr()).unwrap()),
131///         1,
132///         3,
133///         0,
134///         3,
135///     )
136/// };
137/// // this is safe, but note that ptr1 and ptr2 alias...
138/// let mut ptr1: NonNull<i64> = matrix.entry_at(0, 0);
139/// let mut ptr2: NonNull<i64> = matrix.entry_at(0, 0);
140/// // this is UB now!
141/// let (ref1, ref2) = unsafe { (ptr1.as_mut(), ptr2.as_mut()) };
142/// ```
143#[stability::unstable(feature = "enable")]
144pub struct SubmatrixRaw<V, T>
145where
146    V: AsPointerToSlice<T>,
147{
148    entry: PhantomData<*mut T>,
149    rows: NonNull<V>,
150    row_count: usize,
151    row_step: isize,
152    col_start: usize,
153    col_count: usize,
154}
155
156/// Requiring `T: Sync` is the more conservative choice. If `SubmatrixRaw`
157/// acts as a mutable reference, we would only require `T: Send`, but we also
158/// want `SubmatrixRaw` to be usable as an immutable reference, thus it can be
159/// shared between threads, which requires `T: Sync`.
160unsafe impl<V, T> Send for SubmatrixRaw<V, T>
161where
162    V: AsPointerToSlice<T> + Sync,
163    T: Sync,
164{
165}
166
167unsafe impl<V, T> Sync for SubmatrixRaw<V, T>
168where
169    V: AsPointerToSlice<T> + Sync,
170    T: Sync,
171{
172}
173
174impl<V, T> Clone for SubmatrixRaw<V, T>
175where
176    V: AsPointerToSlice<T>,
177{
178    fn clone(&self) -> Self { *self }
179}
180
181impl<V, T> Copy for SubmatrixRaw<V, T> where V: AsPointerToSlice<T> {}
182
183impl<V, T> SubmatrixRaw<V, T>
184where
185    V: AsPointerToSlice<T>,
186{
187    /// Create a new SubmatrixRaw object.
188    ///
189    /// # Safety
190    ///
191    /// We require that each pointer `rows.offset(row_step * i)` for `0 <= i < row_count` points to
192    /// a valid object and can be dereferenced. Furthermore, if `ptr` is the pointer returned by
193    /// `[`AsPointerToSlice::get_pointer()`]`, then `ptr.offset(i + cols_start)` must point to a
194    /// valid `T` for `0 <= i < col_count`.
195    ///
196    /// Furthermore, we require any two of these (for different i) to represent disjunct "slices",
197    /// i.e. if they give pointers `ptr1` and `ptr2` (via [`AsPointerToSlice::get_pointer()`]),
198    /// then `ptr1.offset(cols_start + k)` and `ptr2.offset(cols_start + l)` for `0 <= k, l <
199    /// col_count` never alias.
200    #[stability::unstable(feature = "enable")]
201    pub unsafe fn new(
202        rows: NonNull<V>,
203        row_count: usize,
204        row_step: isize,
205        cols_start: usize,
206        col_count: usize,
207    ) -> Self {
208        Self {
209            entry: PhantomData,
210            row_count,
211            row_step,
212            rows,
213            col_start: cols_start,
214            col_count,
215        }
216    }
217
218    #[stability::unstable(feature = "enable")]
219    pub fn restrict_rows(mut self, rows: Range<usize>) -> Self {
220        assert!(rows.start <= rows.end);
221        assert!(rows.end <= self.row_count);
222        // this is safe since we require (during the constructor) that all pointers `rows.offset(i *
223        // row_step)` are valid for `0 <= i < row_count`. Technically, this is not
224        // completely legal, as in the case `rows.start == rows.end == row_count`, the
225        // resulting pointer might point outside of the allocated area
226        // - this is legal only when we are exactly one byte after it, but if `row_step` has a weird value,
227        //   this does
228        // not work. However, `row_step` has suitable values in all safe interfaces.
229        unsafe {
230            self.row_count = rows.end - rows.start;
231            self.rows = self.rows.offset(rows.start as isize * self.row_step);
232        }
233        self
234    }
235
236    #[stability::unstable(feature = "enable")]
237    pub fn restrict_cols(mut self, cols: Range<usize>) -> Self {
238        assert!(cols.end <= self.col_count);
239        self.col_count = cols.end - cols.start;
240        self.col_start += cols.start;
241        self
242    }
243
244    /// Returns a pointer to the `row`-th row of the matrix.
245    /// Be carefull about aliasing when making this into a reference!
246    #[stability::unstable(feature = "enable")]
247    pub fn row_at(&self, row: usize) -> NonNull<[T]> {
248        assert!(row < self.row_count);
249        // this is safe since `row < row_count` and we require `rows.offset(row * row_step)` to
250        // point to a valid element of `V`
251        let row_ref = unsafe { V::get_pointer(self.rows.offset(row as isize * self.row_step)) };
252        // similarly safe by constructor requirements
253        unsafe { NonNull::slice_from_raw_parts(row_ref.offset(self.col_start as isize), self.col_count) }
254    }
255
256    /// Returns a pointer to the `(row, col)`-th entry of the matrix.
257    /// Be carefull about aliasing when making this into a reference!
258    #[stability::unstable(feature = "enable")]
259    pub fn entry_at(&self, row: usize, col: usize) -> NonNull<T> {
260        assert!(
261            row < self.row_count,
262            "Row index {} out of range 0..{}",
263            row,
264            self.row_count
265        );
266        assert!(
267            col < self.col_count,
268            "Col index {} out of range 0..{}",
269            col,
270            self.col_count
271        );
272        // this is safe since `row < row_count` and we require `rows.offset(row * row_step)` to
273        // point to a valid element of `V`
274        let row_ref = unsafe { V::get_pointer(self.rows.offset(row as isize * self.row_step)) };
275        // similarly safe by constructor requirements
276        unsafe { row_ref.offset(self.col_start as isize + col as isize) }
277    }
278}
279
280/// An immutable view on a column of a matrix [`Submatrix`].
281pub struct Column<'a, V, T>
282where
283    V: AsPointerToSlice<T>,
284{
285    entry: PhantomData<&'a T>,
286    raw_data: SubmatrixRaw<V, T>,
287}
288
289impl<'a, V, T> Column<'a, V, T>
290where
291    V: AsPointerToSlice<T>,
292{
293    /// Creates a new column object representing the given submatrix. Thus,
294    /// the submatrix must only have one column.
295    ///
296    /// # Safety
297    ///
298    /// Since `Column` represents immutable borrowing, callers of this method
299    /// must ensure that for the lifetime `'a`, there are no mutable references
300    /// to any object pointed to by `raw_data` (this includes both the "row descriptors"
301    /// `V` and the actual elements `T`).
302    unsafe fn new(raw_data: SubmatrixRaw<V, T>) -> Self {
303        assert!(raw_data.col_count == 1);
304        Self {
305            entry: PhantomData,
306            raw_data,
307        }
308    }
309}
310
311impl<'a, V, T: Debug> Debug for Column<'a, V, T>
312where
313    V: AsPointerToSlice<T>,
314{
315    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
316        let mut output = f.debug_list();
317        for x in self.as_iter() {
318            _ = output.entry(x);
319        }
320        output.finish()
321    }
322}
323
324impl<'a, V, T> Clone for Column<'a, V, T>
325where
326    V: AsPointerToSlice<T>,
327{
328    fn clone(&self) -> Self { *self }
329}
330
331impl<'a, V, T> Copy for Column<'a, V, T> where V: AsPointerToSlice<T> {}
332
333impl<'a, V, T> VectorView<T> for Column<'a, V, T>
334where
335    V: AsPointerToSlice<T>,
336{
337    fn len(&self) -> usize { self.raw_data.row_count }
338
339    fn at(&self, i: usize) -> &T {
340        // safe since we assume that there are no mutable references to `raw_data`
341        unsafe { self.raw_data.entry_at(i, 0).as_ref() }
342    }
343}
344
345/// A mutable view on a column of a matrix [`SubmatrixMut`].
346///
347/// Clearly must not be Copy/Clone.
348pub struct ColumnMut<'a, V, T>
349where
350    V: AsPointerToSlice<T>,
351{
352    entry: PhantomData<&'a mut T>,
353    raw_data: SubmatrixRaw<V, T>,
354}
355
356impl<'a, V, T: Debug> Debug for ColumnMut<'a, V, T>
357where
358    V: AsPointerToSlice<T>,
359{
360    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { self.as_const().fmt(f) }
361}
362
363impl<'a, V, T> ColumnMut<'a, V, T>
364where
365    V: AsPointerToSlice<T>,
366{
367    /// Creates a new column object representing the given submatrix. Thus,
368    /// the submatrix must only have one column.
369    ///
370    /// # Safety
371    ///
372    /// Since `ColumnMut` represents mutable borrowing, callers of this method
373    /// must ensure that for the lifetime `'a`, there are no other references
374    /// to any matrix entry pointed to by `raw_data` (meaning the "content" elements
375    /// `T`). It is allowed to have immutable references to the "row descriptors" `V`
376    /// (assuming they are strictly different from the content `T`).
377    unsafe fn new(raw_data: SubmatrixRaw<V, T>) -> Self {
378        assert!(raw_data.col_count == 1);
379        Self {
380            entry: PhantomData,
381            raw_data,
382        }
383    }
384
385    /// "Reborrows" the [`ColumnMut`], which is somewhat like cloning the submatrix, but
386    /// disallows the cloned object to be used while its copy is alive. This is necessary
387    /// to follow the aliasing rules of Rust.
388    pub fn reborrow<'b>(&'b mut self) -> ColumnMut<'b, V, T> {
389        ColumnMut {
390            entry: PhantomData,
391            raw_data: self.raw_data,
392        }
393    }
394
395    /// Returns mutable references to two different entries of the column.
396    ///
397    /// This requires `i != j`, otherwise the function will panic. This
398    /// is necessary, since otherwise the two references would violate the
399    /// borrowing rules of Rust.
400    pub fn two_entries(&mut self, i: usize, j: usize) -> (&mut T, &mut T) {
401        assert!(i != j);
402        // safe since i != j
403        unsafe {
404            (
405                self.raw_data.entry_at(i, 0).as_mut(),
406                self.raw_data.entry_at(j, 0).as_mut(),
407            )
408        }
409    }
410
411    /// Returns an immutable view on this matrix column.
412    pub fn as_const<'b>(&'b self) -> Column<'b, V, T> {
413        Column {
414            entry: PhantomData,
415            raw_data: self.raw_data,
416        }
417    }
418}
419
420unsafe impl<'a, V, T> Send for ColumnMut<'a, V, T>
421where
422    V: AsPointerToSlice<T> + Sync,
423    T: Send,
424{
425}
426
427impl<'a, V, T> VectorView<T> for ColumnMut<'a, V, T>
428where
429    V: AsPointerToSlice<T>,
430{
431    fn len(&self) -> usize { self.raw_data.row_count }
432
433    fn at(&self, i: usize) -> &T {
434        // safe since we assume that there are no other references to `raw_data`
435        unsafe { self.raw_data.entry_at(i, 0).as_ref() }
436    }
437}
438
439/// Iterator over mutable references to the entries of a column
440/// of a matrix [`SubmatrixMut`].
441pub struct ColumnMutIter<'a, V, T>
442where
443    V: AsPointerToSlice<T>,
444{
445    column_mut: ColumnMut<'a, V, T>,
446}
447
448impl<'a, V, T> Iterator for ColumnMutIter<'a, V, T>
449where
450    V: AsPointerToSlice<T>,
451{
452    type Item = &'a mut T;
453
454    fn next(&mut self) -> Option<Self::Item> {
455        if self.column_mut.raw_data.row_count > 0 {
456            let mut result = self.column_mut.raw_data.entry_at(0, 0);
457            self.column_mut.raw_data = self
458                .column_mut
459                .raw_data
460                .restrict_rows(1..self.column_mut.raw_data.row_count);
461            // safe since for the result lifetime, one cannot legally access this value using only
462            // the new value of `self.column_mut.raw_data`
463            unsafe { Some(result.as_mut()) }
464        } else {
465            None
466        }
467    }
468}
469
470impl<'a, V, T> IntoIterator for ColumnMut<'a, V, T>
471where
472    V: AsPointerToSlice<T>,
473{
474    type Item = &'a mut T;
475    type IntoIter = ColumnMutIter<'a, V, T>;
476
477    fn into_iter(self) -> ColumnMutIter<'a, V, T> { ColumnMutIter { column_mut: self } }
478}
479
480impl<'a, V, T> VectorViewMut<T> for ColumnMut<'a, V, T>
481where
482    V: AsPointerToSlice<T>,
483{
484    fn at_mut(&mut self, i: usize) -> &mut T {
485        // safe since self is borrow mutably
486        unsafe { self.raw_data.entry_at(i, 0).as_mut() }
487    }
488}
489
490impl<'a, V, T> SwappableVectorViewMut<T> for ColumnMut<'a, V, T>
491where
492    V: AsPointerToSlice<T>,
493{
494    fn swap(&mut self, i: usize, j: usize) {
495        if i != j {
496            // safe since i != j, so these pointers do not alias; I think it is also safe for
497            // zero sized type, even though it is slightly weird since the pointer might point
498            // to the same location even if i != j
499            unsafe {
500                std::mem::swap(
501                    self.raw_data.entry_at(i, 0).as_mut(),
502                    self.raw_data.entry_at(j, 0).as_mut(),
503                );
504            }
505        }
506    }
507}
508
509/// Immutable view on a matrix that stores elements of type `T`.
510///
511/// Note that a [`Submatrix`] never owns the data, but always behaves like
512/// a reference. In particular, this means that [`Submatrix`] is `Copy`,
513/// unconditionally. The equivalent to a mutable reference is given by
514/// [`SubmatrixMut`].
515///
516/// This view is designed to work with various underlying representations
517/// of the matrix, as described by [`AsPointerToSlice`].
518pub struct Submatrix<'a, V, T>
519where
520    V: 'a + AsPointerToSlice<T>,
521{
522    entry: PhantomData<&'a T>,
523    raw_data: SubmatrixRaw<V, T>,
524}
525
526impl<'a, V, T> Submatrix<'a, V, T>
527where
528    V: 'a + AsPointerToSlice<T>,
529{
530    /// Returns the submatrix that references only the entries whose row resp. column
531    /// indices are within the given ranges.
532    pub fn submatrix(self, rows: Range<usize>, cols: Range<usize>) -> Self {
533        self.restrict_rows(rows).restrict_cols(cols)
534    }
535
536    /// Returns the submatrix that references only the entries whose row indices are within the
537    /// given range.
538    pub fn restrict_rows(self, rows: Range<usize>) -> Self {
539        Self {
540            entry: PhantomData,
541            raw_data: self.raw_data.restrict_rows(rows),
542        }
543    }
544
545    /// Consumes the submatrix and produces a reference to its `(i, j)`-th entry.
546    ///
547    /// In most cases, you will use [`Submatrix::at()`] instead, but in rare occasions,
548    /// `into_at()` might be necessary to provide a reference whose lifetime is not
549    /// coupled to the lifetime of the submatrix object.
550    pub fn into_at(self, i: usize, j: usize) -> &'a T { &self.into_row_at(i)[j] }
551
552    /// Returns a reference to the `(i, j)`-th entry of this matrix.
553    pub fn at(&self, i: usize, j: usize) -> &T { &self.row_at(i)[j] }
554
555    /// Returns the submatrix that references only the entries whose column indices are within the
556    /// given range.
557    pub fn restrict_cols(self, cols: Range<usize>) -> Self {
558        Self {
559            entry: PhantomData,
560            raw_data: self.raw_data.restrict_cols(cols),
561        }
562    }
563
564    /// Returns an iterator over all rows of the matrix.
565    pub fn row_iter(self) -> impl 'a + Clone + ExactSizeIterator<Item = &'a [T]> {
566        (0..self.raw_data.row_count).map(move |i|
567        // safe since there are no immutable references to self.raw_data    
568        unsafe {
569            self.raw_data.row_at(i).as_ref()
570        })
571    }
572
573    /// Returns an iterator over all columns of the matrix.
574    pub fn col_iter(self) -> impl 'a + Clone + ExactSizeIterator<Item = Column<'a, V, T>> {
575        (0..self.raw_data.col_count).map(move |j| {
576            debug_assert!(j < self.raw_data.col_count);
577            let mut result_raw = self.raw_data;
578            result_raw.col_start += j;
579            result_raw.col_count = 1;
580            // safe since there are no immutable references to self.raw_data
581            unsafe {
582                return Column::new(result_raw);
583            }
584        })
585    }
586
587    /// Consumes the submatrix and produces a reference to its `i`-th row.
588    ///
589    /// In most cases, you will use [`Submatrix::row_at()`] instead, but in rare occasions,
590    /// `into_row_at()` might be necessary to provide a reference whose lifetime is not
591    /// coupled to the lifetime of the submatrix object.
592    pub fn into_row_at(self, i: usize) -> &'a [T] {
593        // safe since there are no mutable references to self.raw_data
594        unsafe { self.raw_data.row_at(i).as_ref() }
595    }
596
597    /// Returns a view on the `i`-th row of this matrix.
598    pub fn row_at(&self, i: usize) -> &[T] {
599        // safe since there are no immutable references to self.raw_data
600        unsafe { self.raw_data.row_at(i).as_ref() }
601    }
602
603    /// Consumes the submatrix and produces a reference to its `j`-th column.
604    ///
605    /// In most cases, you will use [`Submatrix::col_at()`] instead, but in rare occasions,
606    /// `into_col_at()` might be necessary to provide a reference whose lifetime is not
607    /// coupled to the lifetime of the submatrix object.
608    pub fn into_col_at(self, j: usize) -> Column<'a, V, T> {
609        assert!(j < self.raw_data.col_count);
610        let mut result_raw = self.raw_data;
611        result_raw.col_start += j;
612        result_raw.col_count = 1;
613        // safe since there are no immutable references to self.raw_data
614        unsafe {
615            return Column::new(result_raw);
616        }
617    }
618
619    /// Returns a view on the `j`-th column of this matrix.
620    pub fn col_at<'b>(&'b self, j: usize) -> Column<'b, V, T> {
621        assert!(j < self.raw_data.col_count);
622        let mut result_raw = self.raw_data;
623        result_raw.col_start += j;
624        result_raw.col_count = 1;
625        // safe since there are no immutable references to self.raw_data
626        unsafe {
627            return Column::new(result_raw);
628        }
629    }
630
631    /// Returns the number of columns of this matrix.
632    pub fn col_count(&self) -> usize { self.raw_data.col_count }
633
634    /// Returns the number of rows of this matrix.
635    pub fn row_count(&self) -> usize { self.raw_data.row_count }
636}
637
638impl<'a, V, T: Debug> Debug for Submatrix<'a, V, T>
639where
640    V: 'a + AsPointerToSlice<T>,
641{
642    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
643        let mut output = f.debug_list();
644        for row in self.row_iter() {
645            _ = output.entry(&row);
646        }
647        output.finish()
648    }
649}
650
651impl<'a, V, T> Clone for Submatrix<'a, V, T>
652where
653    V: 'a + AsPointerToSlice<T>,
654{
655    fn clone(&self) -> Self { *self }
656}
657
658impl<'a, V, T> Copy for Submatrix<'a, V, T> where V: 'a + AsPointerToSlice<T> {}
659
660/// Mutable view on a matrix that stores elements of type `T`.
661///
662/// As for [`Submatrix`], a [`SubmatrixMut`] never owns the data, but
663/// behaves similarly to a mutable reference.
664///
665/// This view is designed to work with various underlying representations
666/// of the matrix, as described by [`AsPointerToSlice`].
667pub struct SubmatrixMut<'a, V, T>
668where
669    V: 'a + AsPointerToSlice<T>,
670{
671    entry: PhantomData<&'a mut T>,
672    raw_data: SubmatrixRaw<V, T>,
673}
674
675impl<'a, V, T> SubmatrixMut<'a, V, T>
676where
677    V: 'a + AsPointerToSlice<T>,
678{
679    /// Returns the submatrix that references only the entries whose row resp. column
680    /// indices are within the given ranges.
681    pub fn submatrix(self, rows: Range<usize>, cols: Range<usize>) -> Self {
682        self.restrict_rows(rows).restrict_cols(cols)
683    }
684
685    /// Returns the submatrix that references only the entries whose row indices are within the
686    /// given range.
687    pub fn restrict_rows(self, rows: Range<usize>) -> Self {
688        Self {
689            entry: PhantomData,
690            raw_data: self.raw_data.restrict_rows(rows),
691        }
692    }
693
694    /// Returns the submatrix that references only the entries whose column indices are within the
695    /// given range.
696    pub fn restrict_cols(self, cols: Range<usize>) -> Self {
697        Self {
698            entry: PhantomData,
699            raw_data: self.raw_data.restrict_cols(cols),
700        }
701    }
702
703    /// Returns the two submatrices referencing the entries whose row index is within the given
704    /// ranges.
705    ///
706    /// The ranges must not overlap, so that the returned matrices don't alias the same entry.
707    pub fn split_rows(self, fst_rows: Range<usize>, snd_rows: Range<usize>) -> (Self, Self) {
708        assert!(fst_rows.end <= snd_rows.start || snd_rows.end <= fst_rows.start);
709        (
710            Self {
711                entry: PhantomData,
712                raw_data: self.raw_data.restrict_rows(fst_rows),
713            },
714            Self {
715                entry: PhantomData,
716                raw_data: self.raw_data.restrict_rows(snd_rows),
717            },
718        )
719    }
720
721    /// Returns the two submatrices referencing the entries whose column index is within the given
722    /// ranges.
723    ///
724    /// The ranges must not overlap, so that the returned matrices don't alias the same entry.
725    pub fn split_cols(self, fst_cols: Range<usize>, snd_cols: Range<usize>) -> (Self, Self) {
726        assert!(fst_cols.end <= snd_cols.start || snd_cols.end <= fst_cols.start);
727        (
728            Self {
729                entry: PhantomData,
730                raw_data: self.raw_data.restrict_cols(fst_cols),
731            },
732            Self {
733                entry: PhantomData,
734                raw_data: self.raw_data.restrict_cols(snd_cols),
735            },
736        )
737    }
738
739    /// Returns an iterator over (mutable views onto) the rows of this matrix.
740    pub fn row_iter(self) -> impl 'a + ExactSizeIterator<Item = &'a mut [T]> {
741        (0..self.raw_data.row_count).map(move |i|
742        // safe since each access goes to a different location
743        unsafe {
744            self.raw_data.row_at(i).as_mut()
745        })
746    }
747
748    /// Returns an iterator over (mutable views onto) the columns of this matrix.
749    pub fn col_iter(self) -> impl 'a + ExactSizeIterator<Item = ColumnMut<'a, V, T>> {
750        (0..self.raw_data.col_count).map(move |j| {
751            let mut result_raw = self.raw_data;
752            result_raw.col_start += j;
753            result_raw.col_count = 1;
754            // safe since each time, the `result_raw` don't overlap
755            unsafe {
756                return ColumnMut::new(result_raw);
757            }
758        })
759    }
760
761    /// Consumes the submatrix and produces a reference to its `(i, j)`-th entry.
762    ///
763    /// In most cases, you will use [`SubmatrixMut::at_mut()`] instead, but in rare occasions,
764    /// `into_at_mut()` might be necessary to provide a reference whose lifetime is not
765    /// coupled to the lifetime of the submatrix object.
766    pub fn into_at_mut(self, i: usize, j: usize) -> &'a mut T { &mut self.into_row_mut_at(i)[j] }
767
768    /// Returns a mutable reference to the `(i, j)`-th entry of this matrix.
769    pub fn at_mut(&mut self, i: usize, j: usize) -> &mut T { &mut self.row_mut_at(i)[j] }
770
771    /// Returns a reference to the `(i, j)`-th entry of this matrix.
772    pub fn at(&self, i: usize, j: usize) -> &T { self.as_const().into_at(i, j) }
773
774    /// Returns a view onto the `i`-th row of this matrix.
775    pub fn row_at(&self, i: usize) -> &[T] { self.as_const().into_row_at(i) }
776
777    /// Consumes the submatrix and produces a reference to its `i`-th row.
778    ///
779    /// In most cases, you will use [`SubmatrixMut::row_mut_at()`] instead, but in rare occasions,
780    /// `into_row_mut_at()` might be necessary to provide a reference whose lifetime is not
781    /// coupled to the lifetime of the submatrix object.
782    pub fn into_row_mut_at(self, i: usize) -> &'a mut [T] {
783        // safe since self is exists borrowed for 'a
784        unsafe { self.raw_data.row_at(i).as_mut() }
785    }
786
787    /// Returns a mutable view onto the `i`-th row of this matrix.
788    pub fn row_mut_at(&mut self, i: usize) -> &mut [T] { self.reborrow().into_row_mut_at(i) }
789
790    /// Returns a view onto the `i`-th column of this matrix.
791    pub fn col_at<'b>(&'b self, j: usize) -> Column<'b, V, T> { self.as_const().into_col_at(j) }
792
793    /// Returns a mutable view onto the `j`-th row of this matrix.
794    pub fn col_mut_at<'b>(&'b mut self, j: usize) -> ColumnMut<'b, V, T> {
795        assert!(j < self.raw_data.col_count);
796        let mut result_raw = self.raw_data;
797        result_raw.col_start += j;
798        result_raw.col_count = 1;
799        // safe since self is mutably borrowed for 'b
800        unsafe {
801            return ColumnMut::new(result_raw);
802        }
803    }
804
805    /// "Reborrows" the [`SubmatrixMut`], which is somewhat like cloning the submatrix, but
806    /// disallows the cloned object to be used while its copy is alive. This is necessary
807    /// to follow the aliasing rules of Rust.
808    pub fn reborrow<'b>(&'b mut self) -> SubmatrixMut<'b, V, T> {
809        SubmatrixMut {
810            entry: PhantomData,
811            raw_data: self.raw_data,
812        }
813    }
814
815    /// Returns an immutable view on the data of this matrix.
816    pub fn as_const<'b>(&'b self) -> Submatrix<'b, V, T> {
817        Submatrix {
818            entry: PhantomData,
819            raw_data: self.raw_data,
820        }
821    }
822
823    /// Returns the number of columns of this matrix.
824    pub fn col_count(&self) -> usize { self.raw_data.col_count }
825
826    /// Returns the number of rows of this matrix.
827    pub fn row_count(&self) -> usize { self.raw_data.row_count }
828}
829
830impl<'a, V, T: Debug> Debug for SubmatrixMut<'a, V, T>
831where
832    V: 'a + AsPointerToSlice<T>,
833{
834    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { self.as_const().fmt(f) }
835}
836
837impl<'a, T> SubmatrixMut<'a, AsFirstElement<T>, T> {
838    /// Creates a view on the given data slice, interpreting it as a matrix of given shape.
839    /// Assumes row-major order, i.e. contigous subslices of `data` will be the rows of the
840    /// resulting matrix.
841    pub fn from_1d(data: &'a mut [T], row_count: usize, col_count: usize) -> Self {
842        assert_eq!(row_count * col_count, data.len());
843        unsafe {
844            Self {
845                entry: PhantomData,
846                raw_data: SubmatrixRaw::new(
847                    std::mem::transmute(NonNull::new(data.as_mut_ptr()).unwrap_unchecked()),
848                    row_count,
849                    col_count as isize,
850                    0,
851                    col_count,
852                ),
853            }
854        }
855    }
856
857    #[doc(cfg(feature = "ndarray"))]
858    #[cfg(feature = "ndarray")]
859    pub fn from_ndarray<S>(data: &'a mut ArrayBase<S, Ix2>) -> Self
860    where
861        S: DataMut<Elem = T>,
862    {
863        assert!(data.is_standard_layout());
864        let (nrows, ncols) = (data.nrows(), data.ncols());
865        return Self::new(data.as_slice_mut().unwrap(), nrows, ncols);
866    }
867}
868
869impl<'a, V: AsPointerToSlice<T> + Deref<Target = [T]>, T> SubmatrixMut<'a, V, T> {
870    /// Interprets the given slice of slices as a matrix, by using the elements
871    /// of the outer slice as the rows of the matrix.
872    pub fn from_2d(data: &'a mut [V]) -> Self {
873        assert!(!data.is_empty());
874        let row_count = data.len();
875        let col_count = data[0].len();
876        for row in data.iter() {
877            assert_eq!(col_count, row.len());
878        }
879        unsafe {
880            Self {
881                entry: PhantomData,
882                raw_data: SubmatrixRaw::new(
883                    NonNull::new(data.as_mut_ptr() as *mut _).unwrap_unchecked(),
884                    row_count,
885                    1,
886                    0,
887                    col_count,
888                ),
889            }
890        }
891    }
892}
893
894impl<'a, T> Submatrix<'a, AsFirstElement<T>, T> {
895    /// Creates a view on the given data slice, interpreting it as a matrix of given shape.
896    /// Assumes row-major order, i.e. contigous subslices of `data` will be the rows of the
897    /// resulting matrix.
898    pub fn from_1d(data: &'a [T], row_count: usize, col_count: usize) -> Self {
899        assert_eq!(row_count * col_count, data.len());
900        unsafe {
901            Self {
902                entry: PhantomData,
903                raw_data: SubmatrixRaw::new(
904                    std::mem::transmute(NonNull::new(data.as_ptr() as *mut T).unwrap_unchecked()),
905                    row_count,
906                    col_count as isize,
907                    0,
908                    col_count,
909                ),
910            }
911        }
912    }
913
914    #[doc(cfg(feature = "ndarray"))]
915    #[cfg(feature = "ndarray")]
916    pub fn from_ndarray<S>(data: &'a ArrayBase<S, Ix2>) -> Self
917    where
918        S: DataMut<Elem = T>,
919    {
920        let (nrows, ncols) = (data.nrows(), data.ncols());
921        return Self::new(data.as_slice().unwrap(), nrows, ncols);
922    }
923}
924
925impl<'a, V: AsPointerToSlice<T> + Deref<Target = [T]>, T> Submatrix<'a, V, T> {
926    /// Interprets the given slice of slices as a matrix, by using the elements
927    /// of the outer slice as the rows of the matrix.
928    pub fn from_2d(data: &'a [V]) -> Self {
929        assert!(!data.is_empty());
930        let row_count = data.len();
931        let col_count = data[0].len();
932        for row in data.iter() {
933            assert_eq!(col_count, row.len());
934        }
935        unsafe {
936            Self {
937                entry: PhantomData,
938                raw_data: SubmatrixRaw::new(
939                    NonNull::new(data.as_ptr() as *mut _).unwrap_unchecked(),
940                    row_count,
941                    1,
942                    0,
943                    col_count,
944                ),
945            }
946        }
947    }
948}
949
950#[cfg(test)]
951fn assert_submatrix_eq<V: AsPointerToSlice<T>, T: PartialEq + Debug, const N: usize, const M: usize>(
952    expected: [[T; M]; N],
953    actual: &mut SubmatrixMut<V, T>,
954) {
955    assert_eq!(N, actual.row_count());
956    assert_eq!(M, actual.col_count());
957    for i in 0..N {
958        for j in 0..M {
959            assert_eq!(&expected[i][j], actual.at(i, j));
960            assert_eq!(&expected[i][j], actual.as_const().at(i, j));
961        }
962    }
963}
964
965#[cfg(test)]
966fn with_testmatrix_vec<F>(f: F)
967where
968    F: FnOnce(SubmatrixMut<Vec<i64>, i64>),
969{
970    let mut data = vec![vec![1, 2, 3, 4, 5], vec![6, 7, 8, 9, 10], vec![11, 12, 13, 14, 15]];
971    let matrix = SubmatrixMut::<Vec<_>, _>::from_2d(&mut data[..]);
972    f(matrix)
973}
974
975#[cfg(test)]
976fn with_testmatrix_array<F>(f: F)
977where
978    F: FnOnce(SubmatrixMut<DerefArray<i64, 5>, i64>),
979{
980    let mut data = vec![
981        DerefArray::from([1, 2, 3, 4, 5]),
982        DerefArray::from([6, 7, 8, 9, 10]),
983        DerefArray::from([11, 12, 13, 14, 15]),
984    ];
985    let matrix = SubmatrixMut::<DerefArray<_, 5>, _>::from_2d(&mut data[..]);
986    f(matrix)
987}
988
989#[cfg(test)]
990fn with_testmatrix_linmem<F>(f: F)
991where
992    F: FnOnce(SubmatrixMut<AsFirstElement<i64>, i64>),
993{
994    let mut data = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
995    let matrix = SubmatrixMut::<AsFirstElement<_>, _>::from_1d(&mut data[..], 3, 5);
996    f(matrix)
997}
998
999#[cfg(feature = "ndarray")]
1000#[cfg(test)]
1001fn with_testmatrix_ndarray<F>(f: F)
1002where
1003    F: FnOnce(SubmatrixMut<AsFirstElement<i64>, i64>),
1004{
1005    use ndarray::array;
1006
1007    let mut data = array![[1, 2, 3, 4, 5], [6, 7, 8, 9, 10], [11, 12, 13, 14, 15]];
1008    let matrix = SubmatrixMut::<AsFirstElement<_>, _>::from_ndarray(&mut data);
1009    f(matrix)
1010}
1011
1012#[cfg(not(feature = "ndarray"))]
1013#[cfg(test)]
1014fn with_testmatrix_ndarray<F>(_: F)
1015where
1016    F: FnOnce(SubmatrixMut<AsFirstElement<i64>, i64>),
1017{
1018    // do nothing
1019}
1020
1021#[cfg(test)]
1022fn test_submatrix<V: AsPointerToSlice<i64>>(mut matrix: SubmatrixMut<V, i64>) {
1023    assert_submatrix_eq([[1, 2, 3, 4, 5], [6, 7, 8, 9, 10], [11, 12, 13, 14, 15]], &mut matrix);
1024    assert_submatrix_eq([[2, 3], [7, 8]], &mut matrix.reborrow().submatrix(0..2, 1..3));
1025    assert_submatrix_eq([[8, 9, 10]], &mut matrix.reborrow().submatrix(1..2, 2..5));
1026    assert_submatrix_eq([[8, 9, 10], [13, 14, 15]], &mut matrix.reborrow().submatrix(1..3, 2..5));
1027
1028    let (mut left, mut right) = matrix.split_cols(0..3, 3..5);
1029    assert_submatrix_eq([[1, 2, 3], [6, 7, 8], [11, 12, 13]], &mut left);
1030    assert_submatrix_eq([[4, 5], [9, 10], [14, 15]], &mut right);
1031}
1032
1033#[test]
1034fn test_submatrix_wrapper() {
1035    with_testmatrix_vec(test_submatrix);
1036    with_testmatrix_array(test_submatrix);
1037    with_testmatrix_linmem(test_submatrix);
1038    with_testmatrix_ndarray(test_submatrix);
1039}
1040
1041#[cfg(test)]
1042fn test_submatrix_mutate<V: AsPointerToSlice<i64>>(mut matrix: SubmatrixMut<V, i64>) {
1043    assert_submatrix_eq([[1, 2, 3, 4, 5], [6, 7, 8, 9, 10], [11, 12, 13, 14, 15]], &mut matrix);
1044    let (mut left, mut right) = matrix.split_cols(0..3, 3..5);
1045    assert_submatrix_eq([[1, 2, 3], [6, 7, 8], [11, 12, 13]], &mut left);
1046    assert_submatrix_eq([[4, 5], [9, 10], [14, 15]], &mut right);
1047    *left.at_mut(1, 1) += 1;
1048    *right.at_mut(0, 0) += 1;
1049    *right.at_mut(2, 1) += 1;
1050    assert_submatrix_eq([[1, 2, 3], [6, 8, 8], [11, 12, 13]], &mut left);
1051    assert_submatrix_eq([[5, 5], [9, 10], [14, 16]], &mut right);
1052
1053    let (mut top, mut bottom) = left.split_rows(0..1, 1..3);
1054    assert_submatrix_eq([[1, 2, 3]], &mut top);
1055    assert_submatrix_eq([[6, 8, 8], [11, 12, 13]], &mut bottom);
1056    *top.at_mut(0, 0) -= 1;
1057    *top.at_mut(0, 2) += 3;
1058    *bottom.at_mut(0, 2) -= 1;
1059    *bottom.at_mut(1, 0) += 3;
1060    assert_submatrix_eq([[0, 2, 6]], &mut top);
1061    assert_submatrix_eq([[6, 8, 7], [14, 12, 13]], &mut bottom);
1062}
1063
1064#[test]
1065fn test_submatrix_mutate_wrapper() {
1066    with_testmatrix_vec(test_submatrix_mutate);
1067    with_testmatrix_array(test_submatrix_mutate);
1068    with_testmatrix_linmem(test_submatrix_mutate);
1069    with_testmatrix_ndarray(test_submatrix_mutate);
1070}
1071
1072#[cfg(test)]
1073fn test_submatrix_col_iter<V: AsPointerToSlice<i64>>(mut matrix: SubmatrixMut<V, i64>) {
1074    assert_submatrix_eq([[1, 2, 3, 4, 5], [6, 7, 8, 9, 10], [11, 12, 13, 14, 15]], &mut matrix);
1075    {
1076        let mut it = matrix.reborrow().col_iter();
1077        assert_eq!(
1078            vec![2, 7, 12],
1079            it.by_ref()
1080                .skip(1)
1081                .next()
1082                .unwrap()
1083                .into_iter()
1084                .map(|x| *x)
1085                .collect::<Vec<_>>()
1086        );
1087        assert_eq!(
1088            vec![4, 9, 14],
1089            it.by_ref()
1090                .skip(1)
1091                .next()
1092                .unwrap()
1093                .into_iter()
1094                .map(|x| *x)
1095                .collect::<Vec<_>>()
1096        );
1097        let mut last_col = it.next().unwrap();
1098        for x in last_col.reborrow() {
1099            *x *= 2;
1100        }
1101        assert_eq!(vec![10, 20, 30], last_col.into_iter().map(|x| *x).collect::<Vec<_>>());
1102    }
1103    assert_submatrix_eq([[1, 2, 3, 4, 10], [6, 7, 8, 9, 20], [11, 12, 13, 14, 30]], &mut matrix);
1104
1105    let (left, _right) = matrix.reborrow().split_cols(0..2, 3..4);
1106    {
1107        let mut it = left.col_iter();
1108        let mut col1 = it.next().unwrap();
1109        let mut col2 = it.next().unwrap();
1110        assert!(it.next().is_none());
1111        assert_eq!(vec![1, 6, 11], col1.as_iter().map(|x| *x).collect::<Vec<_>>());
1112        assert_eq!(vec![2, 7, 12], col2.as_iter().map(|x| *x).collect::<Vec<_>>());
1113        assert_eq!(
1114            vec![1, 6, 11],
1115            col1.reborrow().into_iter().map(|x| *x).collect::<Vec<_>>()
1116        );
1117        assert_eq!(
1118            vec![2, 7, 12],
1119            col2.reborrow().into_iter().map(|x| *x).collect::<Vec<_>>()
1120        );
1121        *col1.into_iter().skip(1).next().unwrap() += 5;
1122    }
1123    assert_submatrix_eq([[1, 2, 3, 4, 10], [11, 7, 8, 9, 20], [11, 12, 13, 14, 30]], &mut matrix);
1124
1125    let (_left, right) = matrix.reborrow().split_cols(0..2, 3..4);
1126    {
1127        let mut it = right.col_iter();
1128        let mut col = it.next().unwrap();
1129        assert!(it.next().is_none());
1130        assert_eq!(vec![4, 9, 14], col.reborrow().as_iter().map(|x| *x).collect::<Vec<_>>());
1131        *col.into_iter().next().unwrap() += 3;
1132    }
1133    assert_submatrix_eq([[1, 2, 3, 7, 10], [11, 7, 8, 9, 20], [11, 12, 13, 14, 30]], &mut matrix);
1134}
1135
1136#[test]
1137fn test_submatrix_col_iter_wrapper() {
1138    with_testmatrix_vec(test_submatrix_col_iter);
1139    with_testmatrix_array(test_submatrix_col_iter);
1140    with_testmatrix_linmem(test_submatrix_col_iter);
1141    with_testmatrix_ndarray(test_submatrix_col_iter);
1142}
1143
1144#[cfg(test)]
1145fn test_submatrix_row_iter<V: AsPointerToSlice<i64>>(mut matrix: SubmatrixMut<V, i64>) {
1146    assert_submatrix_eq([[1, 2, 3, 4, 5], [6, 7, 8, 9, 10], [11, 12, 13, 14, 15]], &mut matrix);
1147    {
1148        let mut it = matrix.reborrow().row_iter();
1149        assert_eq!(&[6, 7, 8, 9, 10], it.by_ref().skip(1).next().unwrap());
1150        let row = it.next().unwrap();
1151        assert!(it.next().is_none());
1152        row[1] += 6;
1153        row[4] *= 2;
1154    }
1155    assert_submatrix_eq([[1, 2, 3, 4, 5], [6, 7, 8, 9, 10], [11, 18, 13, 14, 30]], &mut matrix);
1156    let (mut left, mut right) = matrix.reborrow().split_cols(0..2, 3..4);
1157    {
1158        let mut it = left.reborrow().row_iter();
1159        let row1 = it.next().unwrap();
1160        let row2 = it.next().unwrap();
1161        assert!(it.next().is_some());
1162        assert!(it.next().is_none());
1163        assert_eq!(&[1, 2], row1);
1164        assert_eq!(&[6, 7], row2);
1165    }
1166    {
1167        let mut it = left.reborrow().row_iter();
1168        let row1 = it.next().unwrap();
1169        let row2 = it.next().unwrap();
1170        assert!(it.next().is_some());
1171        assert!(it.next().is_none());
1172        assert_eq!(&[1, 2], row1);
1173        assert_eq!(&[6, 7], row2);
1174        row2[1] += 1;
1175    }
1176    assert_submatrix_eq([[1, 2], [6, 8], [11, 18]], &mut left);
1177    {
1178        right = right.submatrix(1..3, 0..1);
1179        let mut it = right.reborrow().row_iter();
1180        let row1 = it.next().unwrap();
1181        let row2 = it.next().unwrap();
1182        assert_eq!(&[9], row1);
1183        assert_eq!(&[14], row2);
1184        row1[0] += 1;
1185    }
1186    assert_submatrix_eq([[10], [14]], &mut right);
1187}
1188
1189#[test]
1190fn test_submatrix_row_iter_wrapper() {
1191    with_testmatrix_vec(test_submatrix_row_iter);
1192    with_testmatrix_array(test_submatrix_row_iter);
1193    with_testmatrix_linmem(test_submatrix_row_iter);
1194    with_testmatrix_ndarray(test_submatrix_row_iter);
1195}
1196
1197#[cfg(test)]
1198fn test_submatrix_col_at<V: AsPointerToSlice<i64>>(mut matrix: SubmatrixMut<V, i64>) {
1199    assert_submatrix_eq([[1, 2, 3, 4, 5], [6, 7, 8, 9, 10], [11, 12, 13, 14, 15]], &mut matrix);
1200    assert_eq!(
1201        &[2, 7, 12],
1202        &matrix.col_at(1).as_iter().copied().collect::<Vec<_>>()[..]
1203    );
1204    assert_eq!(
1205        &[2, 7, 12],
1206        &matrix.as_const().col_at(1).as_iter().copied().collect::<Vec<_>>()[..]
1207    );
1208    assert_eq!(
1209        &[5, 10, 15],
1210        &matrix.col_at(4).as_iter().copied().collect::<Vec<_>>()[..]
1211    );
1212    assert_eq!(
1213        &[5, 10, 15],
1214        &matrix.as_const().col_at(4).as_iter().copied().collect::<Vec<_>>()[..]
1215    );
1216
1217    {
1218        let (mut top, mut bottom) = matrix.reborrow().restrict_rows(0..2).split_rows(0..1, 1..2);
1219        assert_eq!(&[1], &top.col_mut_at(0).as_iter().copied().collect::<Vec<_>>()[..]);
1220        assert_eq!(
1221            &[1],
1222            &top.as_const().col_at(0).as_iter().copied().collect::<Vec<_>>()[..]
1223        );
1224        assert_eq!(&[1], &top.col_at(0).as_iter().copied().collect::<Vec<_>>()[..]);
1225        assert_eq!(&[5], &top.col_mut_at(4).as_iter().copied().collect::<Vec<_>>()[..]);
1226        assert_eq!(
1227            &[5],
1228            &top.as_const().col_at(4).as_iter().copied().collect::<Vec<_>>()[..]
1229        );
1230        assert_eq!(&[5], &top.col_at(4).as_iter().copied().collect::<Vec<_>>()[..]);
1231
1232        assert_eq!(&[6], &bottom.col_mut_at(0).as_iter().copied().collect::<Vec<_>>()[..]);
1233        assert_eq!(
1234            &[6],
1235            &bottom.as_const().col_at(0).as_iter().copied().collect::<Vec<_>>()[..]
1236        );
1237        assert_eq!(&[6], &bottom.col_at(0).as_iter().copied().collect::<Vec<_>>()[..]);
1238        assert_eq!(&[10], &bottom.col_mut_at(4).as_iter().copied().collect::<Vec<_>>()[..]);
1239        assert_eq!(
1240            &[10],
1241            &bottom.as_const().col_at(4).as_iter().copied().collect::<Vec<_>>()[..]
1242        );
1243        assert_eq!(&[10], &bottom.col_at(4).as_iter().copied().collect::<Vec<_>>()[..]);
1244    }
1245}
1246
1247#[test]
1248fn test_submatrix_col_at_wrapper() {
1249    with_testmatrix_vec(test_submatrix_col_at);
1250    with_testmatrix_array(test_submatrix_col_at);
1251    with_testmatrix_linmem(test_submatrix_col_at);
1252    with_testmatrix_ndarray(test_submatrix_col_at);
1253}
1254
1255#[cfg(test)]
1256fn test_submatrix_row_at<V: AsPointerToSlice<i64>>(mut matrix: SubmatrixMut<V, i64>) {
1257    assert_submatrix_eq([[1, 2, 3, 4, 5], [6, 7, 8, 9, 10], [11, 12, 13, 14, 15]], &mut matrix);
1258    assert_eq!(
1259        &[2, 7, 12],
1260        &matrix.col_at(1).as_iter().copied().collect::<Vec<_>>()[..]
1261    );
1262    assert_eq!(
1263        &[2, 7, 12],
1264        &matrix.as_const().col_at(1).as_iter().copied().collect::<Vec<_>>()[..]
1265    );
1266    assert_eq!(
1267        &[5, 10, 15],
1268        &matrix.col_at(4).as_iter().copied().collect::<Vec<_>>()[..]
1269    );
1270    assert_eq!(
1271        &[5, 10, 15],
1272        &matrix.as_const().col_at(4).as_iter().copied().collect::<Vec<_>>()[..]
1273    );
1274
1275    {
1276        let (mut left, mut right) = matrix.reborrow().restrict_cols(1..5).split_cols(0..2, 2..4);
1277        assert_eq!(&[2, 3], left.row_mut_at(0));
1278        assert_eq!(&[4, 5], right.row_mut_at(0));
1279        assert_eq!(&[2, 3], left.as_const().row_at(0));
1280        assert_eq!(&[4, 5], right.as_const().row_at(0));
1281        assert_eq!(&[2, 3], left.row_at(0));
1282        assert_eq!(&[4, 5], right.row_at(0));
1283
1284        assert_eq!(&[7, 8], left.row_mut_at(1));
1285        assert_eq!(&[9, 10], right.row_mut_at(1));
1286        assert_eq!(&[7, 8], left.as_const().row_at(1));
1287        assert_eq!(&[9, 10], right.as_const().row_at(1));
1288        assert_eq!(&[7, 8], left.row_at(1));
1289        assert_eq!(&[9, 10], right.row_at(1));
1290    }
1291}
1292
1293#[test]
1294fn test_submatrix_row_at_wrapper() {
1295    with_testmatrix_vec(test_submatrix_row_at);
1296    with_testmatrix_array(test_submatrix_row_at);
1297    with_testmatrix_linmem(test_submatrix_row_at);
1298    with_testmatrix_ndarray(test_submatrix_row_at);
1299}