Skip to main content

feanor_math/matrix/
submatrix.rs

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