feanor_math/matrix/
submatrix.rs

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