Skip to main content

matrix_slice/
lib.rs

1//! Implements references to blocks of a matrix.
2//!
3//! Consider a reference to a slice (sometimes also just called slice). Typically, it is created by
4//! unsizing a reference to an array through type coercion, such as sing `&[0, 1, 2]` in a
5//! parameter to function that takes `&[u32]` which turns a reference `&[u32; 3]` to a slice
6//! `&[u32]`. The length of the slice, controlling the number of elements and thus the provenance
7//! of access that the reference allows, is stored in a tag alongside the pointer to its elements
8//! and initialized from the known length of the array. Since this tag is a runtime value we can
9//! manipulate it while upholding the invariants required by the type system.
10//!
11//! This is analogous to that but for blocks of a matrix. A block is a rectangular region of a
12//! matrix where the matrix provides an underlying pitch (or stride) between rows and a total
13//! number of elements and the block the number of rows and columns that are spanned, i.e. are
14//! allowed to be accessed by (mutable) reference.
15//!
16//! ## Treatment of empty blocks
17//!
18//! A block may have zero rows or zero columns. In either case the block is empty and provides no
19//! access to any elements yet will still return an empty slice for some operations that would
20//! otherwise access multiple elements. The memory address of such a block is **not** necessarily
21//! at its expected location but it will be in-bounds of the underlying matrix data.
22//!
23//! Consider the bottom right `2x2` block of a row-major `3x3` matrix.
24//!
25//! ```text
26//! +---+---+---+
27//! | x | x | x |
28//! +---+---+---+
29//! | x | 4 | 5 |
30//! +---+---+---+
31//! | x | 7 | 8 |
32//! +---+---+---+
33//! ```
34//!
35//! This block has a pitch of 3 but only spans 2 columns. If we would naively calculate the address
36//! of its past-the-end element we would get an element below `7` which is out-of-bounds. Hence if
37//! we split this at row 2, into itself and an empty `0x2` block, the latter block's data pointer
38//! would be created with undefined behavior. Instead, we sacrifice the ability to 'locate' such
39//! empty blocks and instead have them point at an arbitrary (empty) in-bounds slice within the
40//! matrix. (Currently, that is the start of the block from which it was created).
41#![no_std]
42use core::{cell::Cell, fmt, marker::PhantomData, ops, ptr::NonNull};
43
44/// The Readme of the crate and links to further documentation.
45///
46/// Note: This module only exists on `cfg(doc)` builds, do not refer to it.
47///
48#[cfg(doc)]
49#[doc = include_str!("../Readme.md")]
50pub mod docs {
51    /// A discussion of the approach, alternatives, trade-offs and context.
52    ///
53    #[doc = include_str!("../docs/development_log.md")]
54    pub const DEVELOPMENT_NOTES: () = ();
55
56    /// Documentation of each released version.
57    ///
58    #[doc = include_str!("../Changes.md")]
59    pub const CHANGELOG: () = ();
60}
61
62/// Create a block reference from a full matrix represented as an array of rows.
63///
64/// # Examples
65///
66/// ```
67/// let data = &mut [
68///    [0, 1, 2],
69///    [3, 4, 5],
70/// ];
71///
72/// let mut block = matrix_slice::from_array_rows(data);
73///
74/// assert_eq!(block.rows(), 2);
75/// assert_eq!(block.cols(), 3);
76///
77/// assert_eq!(block[(1, 1)], 4);
78/// ```
79pub fn from_array_rows<'a, T, const N: usize>(data: &'a [[T; N]]) -> BlockRef<'a, T> {
80    BlockRef {
81        block: BlockSlice {
82            rows: data.len(),
83            cols: N,
84            pitch: N,
85        },
86        data: NonNull::from_ref(data).cast(),
87        lifetime: PhantomData,
88    }
89}
90
91/// A reference to a block of a matrix with shared access to elements.
92#[derive(Copy, Clone)]
93pub struct BlockRef<'a, T> {
94    // Internal invariant: the size of the block is a subset of the provenance of the pointer.
95    data: NonNull<T>,
96    block: BlockSlice,
97    lifetime: PhantomData<&'a [T]>,
98}
99
100// SAFETY: See `&[T]`. The reference can be used to, potentially, get a `&T` for each element in
101// the block and thus the block itself provides the exact same properties as `T`. The `BlockRef` is
102// then `&[T]` itself and thus has properties of a reference to such a type. Refer to the
103// reference: <https://doc.rust-lang.org/stable/std/primitive.reference.html>
104//
105// We have `&T: Sync` iff `T: Sync`
106unsafe impl<T> Sync for BlockRef<'_, T> where T: Sync {}
107// We have `&T: Send` iff `T: Sync`
108unsafe impl<T> Send for BlockRef<'_, T> where T: Sync {}
109
110const _: () = {
111    // We can coerce a block to a shorter lifetime.
112    fn _coerce_block<'a, 'b: 'a, T>(v: BlockRef<'b, T>) -> BlockRef<'a, T> {
113        v
114    }
115
116    // We can coerce a reference to a block to a shorter lifetime.
117    fn _coerce_covariant<'lt, 'a, 'b: 'a, T>(v: &'lt BlockRef<'b, T>) -> &'lt BlockRef<'a, T> {
118        v
119    }
120
121    fn _coerce_covariant_fn<'lt, 'a, 'b: 'a, T>(v: fn(BlockRef<'a, T>)) -> fn(BlockRef<'b, T>) {
122        v
123    }
124
125    fn _coerce_item_covariant<'lt, 'a, 'b: 'a, T>(v: BlockRef<'lt, &'b T>) -> BlockRef<'lt, &'a T> {
126        v
127    }
128};
129
130/// Creates an empty block reference, within a matrix of a dangling slice.
131impl<T> Default for BlockRef<'_, T> {
132    fn default() -> Self {
133        from_array_rows::<T, 0>(&[])
134    }
135}
136
137impl<'data, T> BlockRef<'data, T> {
138    /// Create a new block reference from a raw slice and pitch.
139    ///
140    /// The resulting block refers to the whole matrix.
141    ///
142    /// # Panics
143    ///
144    /// Panics if the length of `data` is not a multiple of `pitch`.
145    pub fn new(data: &'data [T], pitch: usize) -> Self {
146        assert!(data.len().is_multiple_of(pitch));
147
148        BlockRef {
149            block: BlockSlice {
150                rows: data.len() / pitch,
151                cols: pitch,
152                pitch,
153            },
154            data: NonNull::from_ref(data).cast(),
155            lifetime: PhantomData,
156        }
157    }
158
159    /// Number of rows in this block.
160    pub fn rows(&self) -> usize {
161        self.block.rows
162    }
163
164    /// Number of columns in this block.
165    pub fn cols(&self) -> usize {
166        self.block.cols
167    }
168
169    /// Divide into two blocks at the given column.
170    ///
171    /// # Examples
172    ///
173    /// ```
174    /// let data = &[
175    ///     [0, 1, 2],
176    ///     [3, 4, 5],
177    /// ];
178    ///
179    /// let block = matrix_slice::from_array_rows(data);
180    /// let (left, right) = block.split_at_col(2);
181    ///
182    /// assert_eq!(left[(1, 0)], 3);
183    /// assert_eq!(right[(1, 0)], 5);
184    /// ```
185    pub fn split_at_col(self, mid: usize) -> (BlockRef<'data, T>, BlockRef<'data, T>) {
186        self.split_at_col_checked(mid).unwrap()
187    }
188
189    /// Divide into two blocks at the given column.
190    ///
191    /// See [`Self::split_at_col`] but returns `None` if out of bounds.
192    pub fn split_at_col_checked(
193        self,
194        mid: usize,
195    ) -> Option<(BlockRef<'data, T>, BlockRef<'data, T>)> {
196        if let Some((lhs, rhs, offset)) = self.block.split_at_col(mid) {
197            Some((
198                BlockRef {
199                    data: self.data,
200                    block: lhs,
201                    lifetime: self.lifetime,
202                },
203                BlockRef {
204                    // SAFETY: `split_at_col` guarantees that `offset` is in-bounds of the
205                    // provenance tracked by `self.block`, which is in-sync with the pointer field
206                    // (but we not necessary access these without synchronization). By extension
207                    // of being in-bounds of the allocation the offset does not overflow `isize`.
208                    data: unsafe { self.data.add(offset) },
209                    block: rhs,
210                    lifetime: self.lifetime,
211                },
212            ))
213        } else {
214            None
215        }
216    }
217
218    /// Divide into two blocks at the given row.
219    ///
220    /// # Examples
221    ///
222    /// ```
223    /// let data = &[
224    ///     [0, 1, 2],
225    ///     [3, 4, 5],
226    /// ];
227    ///
228    /// let block = matrix_slice::from_array_rows(data);
229    /// let (top, bot) = block.split_at_row(1);
230    ///
231    /// assert_eq!(top[(0, 2)], 2);
232    /// assert_eq!(bot[(0, 2)], 5);
233    /// ```
234    pub fn split_at_row(self, mid: usize) -> (BlockRef<'data, T>, BlockRef<'data, T>) {
235        self.split_at_row_checked(mid).unwrap()
236    }
237
238    /// Divide into two blocks at the given row.
239    ///
240    /// See [`Self::split_at_row`] but returns `None` if out of bounds.
241    pub fn split_at_row_checked(
242        self,
243        mid: usize,
244    ) -> Option<(BlockRef<'data, T>, BlockRef<'data, T>)> {
245        if let Some((lhs, rhs, offset)) = self.block.split_at_row(mid) {
246            Some((
247                BlockRef {
248                    data: self.data,
249                    block: lhs,
250                    lifetime: self.lifetime,
251                },
252                BlockRef {
253                    // SAFETY: `split_at_row` guarantees that `offset` is in-bounds of the
254                    // provenance tracked by `self.block`, which is in-sync with the pointer field
255                    // (but we not necessary access these without synchronization). By extension
256                    // of being in-bounds of the allocation the offset does not overflow `isize`.
257                    data: unsafe { self.data.add(offset) },
258                    block: rhs,
259                    lifetime: self.lifetime,
260                },
261            ))
262        } else {
263            None
264        }
265    }
266
267    /// Choose a single row and refer to its data.
268    ///
269    /// # Examples
270    ///
271    /// ```
272    /// let data = &[
273    ///     [0, 1, 2],
274    ///     [3, 4, 5],
275    ///     [6, 7, 8],
276    /// ];
277    ///
278    /// let block = matrix_slice::from_array_rows(data);
279    /// let row = block.row(1);
280    /// assert_eq!(row[0], 3);
281    /// ```
282    pub fn row(self, row: usize) -> VecRef<'data, T> {
283        self.row_checked(row).unwrap()
284    }
285
286    /// Choose a single row and refer to its data.
287    ///
288    /// See [`Self::row`] but returns `None` if out of bounds.
289    pub fn row_checked(self, row: usize) -> Option<VecRef<'data, T>> {
290        let (_, block, offset) = self.block.split_at_row(row)?;
291
292        if block.rows == 0 {
293            return None;
294        }
295
296        Some(VecRef {
297            block: VectorSlice {
298                count: block.cols,
299                pitch: 1,
300            },
301            // SAFETY: `split_at_row` guarantees that `offset` is in-bounds of the
302            // provenance tracked by `self.block`, which is in-sync with the pointer field
303            // (but we not necessary access these without synchronization). By extension
304            // of being in-bounds of the allocation the offset does not overflow `isize`.
305            data: unsafe { self.data.add(offset) },
306            lifetime: self.lifetime,
307        })
308    }
309
310    /// Choose a single column and refer to its data.
311    ///
312    /// # Examples
313    ///
314    /// ```
315    /// let data = &[
316    ///     [0, 1, 2],
317    ///     [3, 4, 5],
318    ///     [6, 7, 8],
319    /// ];
320    ///
321    /// let block = matrix_slice::from_array_rows(data);
322    /// let row = block.col(1);
323    /// assert_eq!(row[0], 1);
324    /// ```
325    pub fn col(self, col: usize) -> VecRef<'data, T> {
326        self.col_checked(col).unwrap()
327    }
328
329    /// Choose a single column and refer to its data.
330    ///
331    /// See [`Self::col`] but returns `None` if out of bounds.
332    pub fn col_checked(self, col: usize) -> Option<VecRef<'data, T>> {
333        let (_, block, offset) = self.block.split_at_col(col)?;
334
335        if block.cols == 0 {
336            return None;
337        }
338
339        Some(VecRef {
340            block: VectorSlice {
341                count: block.rows,
342                pitch: block.pitch,
343            },
344            // SAFETY: `split_at_col` guarantees that `offset` is in-bounds of the
345            // provenance tracked by `self.block`, which is in-sync with the pointer field
346            // (but we not necessary access these without synchronization). By extension
347            // of being in-bounds of the allocation the offset does not overflow `isize`.
348            data: unsafe { self.data.add(offset) },
349            lifetime: self.lifetime,
350        })
351    }
352
353    /// Choose a range of rows and contract the block to that.
354    ///
355    /// The argument type is flexible, allowing ranges (`1..3`), half open ranges (`2..` and `..2`)
356    /// among others. See the [`MatrixIndex`] trait, which is sealed though as its details are not
357    /// yet finalized.
358    ///
359    /// # Examples
360    ///
361    /// ```
362    /// let data = &[
363    ///     [0, 1, 2],
364    ///     [3, 4, 5],
365    ///     [6, 7, 8],
366    /// ];
367    ///
368    /// let block = matrix_slice::from_array_rows(data);
369    ///
370    /// let center = block.select_rows(1..2).unwrap();
371    /// assert_eq!(center.rows(), 1);
372    /// assert_eq!(center.cols(), 3);
373    /// assert_eq!(center[(0, 1)], 4);
374    /// ```
375    pub fn select_rows<R>(self, range: R) -> Option<BlockRef<'data, T>>
376    where
377        R: MatrixIndex,
378    {
379        let (start, len) = range.into_start_and_len(self.block.rows)?;
380        let (_, block, offset) = self.block.split_at_row(start)?;
381        // SAFETY: ensures that the resulting block is more constrained, this property should be
382        // ensured by our sealed `MatrixIndex` implementations.
383        assert!(block.rows >= len);
384
385        Some(BlockRef {
386            block: BlockSlice { rows: len, ..block },
387            // SAFETY: offset is in-bounds as per `split_at_row` contract.
388            data: unsafe { self.data.add(offset) },
389            lifetime: self.lifetime,
390        })
391    }
392
393    /// Choose a range of columns and contract the block to that.
394    ///
395    /// The argument type is flexible, allowing ranges (`1..3`), half open ranges (`2..` and `..2`)
396    /// among others. See the [`MatrixIndex`] trait, which is sealed though as its details are not
397    /// yet finalized.
398    ///
399    /// # Examples
400    ///
401    /// ```
402    /// let data = &[
403    ///     [0, 1],
404    ///     [3, 4],
405    ///     [6, 7],
406    /// ];
407    ///
408    /// let mut block = matrix_slice::from_array_rows(data);
409    ///
410    /// assert!(block.reborrow().select_cols(1..).is_some_and(|b| b.cols() == 1));
411    /// assert!(block.reborrow().select_cols(2..).is_some_and(|b| b.cols() == 0));
412    /// assert!(block.reborrow().select_cols(3..).is_none());
413    /// ```
414    pub fn select_cols<R>(self, range: R) -> Option<BlockRef<'data, T>>
415    where
416        R: MatrixIndex,
417    {
418        let (start, len) = range.into_start_and_len(self.block.cols)?;
419        let (_, block, offset) = self.block.split_at_col(start)?;
420        debug_assert!(block.cols >= len);
421
422        Some(BlockRef {
423            block: BlockSlice { cols: len, ..block },
424            // SAFETY: `split_at_col` guarantees that `offset` is in-bounds of the
425            // provenance tracked by `self.block`, which is in-sync with the pointer field
426            // (but we not necessary access these without synchronization). By extension
427            // of being in-bounds of the allocation the offset does not overflow `isize`.
428            data: unsafe { self.data.add(offset) },
429            lifetime: self.lifetime,
430        })
431    }
432
433    /// Choose a sub-block by its range of rows and columns.
434    pub fn select(
435        self,
436        row_range: impl MatrixIndex,
437        col_range: impl MatrixIndex,
438    ) -> Option<BlockRef<'data, T>> {
439        let block = self.select_rows(row_range)?;
440        block.select_cols(col_range)
441    }
442
443    /// Extract a contiguous underlying slice of elements if the block is contiguous.
444    ///
445    /// # Examples
446    ///
447    /// ```
448    /// let data = &[[0u32; 3]; 3];
449    /// let block = matrix_slice::from_array_rows(data);
450    ///
451    /// let (block, _) = block.split_at_row(2);
452    /// assert!(block.into_contiguous_slice().is_some());
453    ///
454    /// let (pre, post) = block.split_at_col(2);
455    /// assert!(pre.into_contiguous_slice().is_none());
456    /// assert!(post.into_contiguous_slice().is_none());
457    ///
458    /// let (same, _) = block.split_at_col(3);
459    /// assert!(same.into_contiguous_slice().is_some());
460    /// ```
461    pub fn into_contiguous_slice(self) -> Option<&'data [T]> {
462        if let Some(items) = self.block.contiguous_span() {
463            // SAFETY: `contiguous_span` ensures the block covers `items` contiguous elements.
464            // Since pointer provenance is a superset of block's element access that implies the
465            // pointer also has provenance for these elements. Since we have unique access to all
466            // the elements in the block we have non-aliased access to the whole slice.
467            Some(unsafe { core::slice::from_raw_parts(self.data.as_ptr().cast(), items) })
468        } else {
469            None
470        }
471    }
472
473    /// Turn this into a slice of the first row, assuming it is at most one row.
474    fn fake_contiguity(mut self) -> &'data [T] {
475        self.block.fake_contiguity();
476        self.into_contiguous_slice().unwrap()
477    }
478
479    /// Extract access as a slice of arrays if the block is contiguous.
480    ///
481    /// The caller must choose `N` matching the number of columns.
482    pub fn into_array_rows_checked<const N: usize>(self) -> Option<&'data [[T; N]]> {
483        if let Some(rows) = self.block.contiguous_arrays::<N>() {
484            // SAFETY: `` ensures the block covers `items` contiguous N-arrays of
485            // elements. Since pointer provenance is a superset of block's element access that
486            // implies the pointer also has provenance for these elements. Since we have unique
487            // access to all the elements in the block we have non-aliased access to the whole
488            // slice of elements. A slice and a slice of arrays have the same layout so the same
489            // holds for the correctly sized array the length of which `contiguous_arrays` promises
490            // to return.
491            Some(unsafe { core::slice::from_raw_parts(self.data.as_ptr().cast(), rows) })
492        } else {
493            None
494        }
495    }
496
497    /// Iterate over the rows of this block.
498    pub fn iter_rows(self) -> IterRows<'data, T> {
499        IterRows { block: self }
500    }
501
502    /// Create a reference to this block with a shorter lifetime.
503    pub fn reborrow(&self) -> BlockRef<'_, T> {
504        BlockRef {
505            data: self.data,
506            block: self.block,
507            lifetime: PhantomData,
508        }
509    }
510}
511
512impl<T> ops::Index<(usize, usize)> for BlockRef<'_, T> {
513    type Output = T;
514
515    fn index(&self, index: (usize, usize)) -> &Self::Output {
516        let idx = self.block.in_bounds_offset(index.0, index.1);
517        // SAFETY: Index is bounded by `total_span` which itself is a lower estimate of the
518        // provenance of the pointer.
519        unsafe { &*self.data.as_ptr().add(idx) }
520    }
521}
522
523impl<T: fmt::Debug> fmt::Debug for BlockRef<'_, T> {
524    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
525        f.debug_list().entries(self.reborrow().iter_rows()).finish()
526    }
527}
528
529/// Create a mutable block reference from a full matrix represented as an array of rows.
530///
531/// # Examples
532///
533/// ```
534/// let data = &mut [
535///    [0, 1, 2],
536///    [3, 4, 5],
537/// ];
538///
539/// let mut block = matrix_slice::from_array_rows_mut(data);
540///
541/// assert_eq!(block.rows(), 2);
542/// assert_eq!(block.cols(), 3);
543///
544/// block[(1, 1)] = 42;
545///
546/// assert_eq!(data[1][1], 42);
547/// ```
548pub fn from_array_rows_mut<'a, T, const N: usize>(data: &'a mut [[T; N]]) -> BlockMut<'a, T> {
549    BlockMut {
550        block: BlockSlice {
551            rows: data.len(),
552            cols: N,
553            pitch: N,
554        },
555        data: NonNull::from_mut(data).cast(),
556        lifetime: PhantomData,
557    }
558}
559
560/// A reference to a block of a matrix with unique access to elements.
561pub struct BlockMut<'a, T> {
562    // Internal invariant: the size of the block is a subset of the provenance of the pointer. Also
563    // we never have two `BlockMut` with the same accessible elements active at the same time.
564    data: NonNull<T>,
565    block: BlockSlice,
566    lifetime: PhantomData<&'a mut [T]>,
567}
568
569// SAFETY: See `BlockRef` but with `&mut [T]`.
570//
571// We have `&mut T: Sync` iff `T: Sync`
572unsafe impl<T> Sync for BlockMut<'_, T> where T: Sync {}
573// We have `&mut T: Send` iff `T: Send`
574unsafe impl<T> Send for BlockMut<'_, T> where T: Sync {}
575
576/// ```compile_fail
577/// use matrix_slice::BlockMut;
578///
579/// // This coercion must *not* be possible. The field `lifetime` ensures the right variance.
580/// fn _coerce_item_not_covariant<'lt, 'a, 'b: 'a, T>(
581///     v: BlockMut<'lt, &'b T>,
582/// ) -> BlockMut<'lt, &'a T> {
583///     v
584/// //  ^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a`
585/// }
586///
587/// ```compile_fail
588/// use matrix_slice::BlockMut;
589///
590/// fn _copy_block(v: BlockMut<'_, u32>) -> [BlockMut<'_, u32>; 2] {
591///    [v, v]
592/// }
593const _: () = {
594    // We can coerce a block to a shorter lifetime.
595    fn _coerce_block_mut<'a, 'b: 'a, T>(v: BlockMut<'b, T>) -> BlockMut<'a, T> {
596        v
597    }
598
599    // We can coerce a reference to a block to a shorter lifetime.
600    fn _coerce_covariant<'lt, 'a, 'b: 'a, T>(v: &'lt BlockMut<'b, T>) -> &'lt BlockMut<'a, T> {
601        v
602    }
603
604    fn _coerce_covariant_fn<'lt, 'a, 'b: 'a, T>(v: fn(BlockMut<'a, T>)) -> fn(BlockMut<'b, T>) {
605        v
606    }
607};
608
609/// Creates an empty block reference, within a matrix of a dangling slice.
610impl<T> Default for BlockMut<'_, T> {
611    fn default() -> Self {
612        from_array_rows_mut::<T, 0>(&mut [])
613    }
614}
615
616impl<'data, T> BlockMut<'data, T> {
617    /// Create a new block reference from a raw slice and pitch.
618    ///
619    /// The resulting block refers to the whole matrix.
620    ///
621    /// # Panics
622    ///
623    /// Panics if the length of `data` is not a multiple of `pitch`.
624    pub fn new(data: &'data mut [T], pitch: usize) -> Self {
625        assert!(data.len().is_multiple_of(pitch));
626
627        // SAFETY:
628        // - construction implies `count * pitch <= data.len()` covering the provenance.
629        // - this is the only block with mutable access to the whole data.
630        BlockMut {
631            block: BlockSlice {
632                rows: data.len() / pitch,
633                cols: pitch,
634                pitch,
635            },
636            data: NonNull::from_mut(data).cast(),
637            lifetime: PhantomData,
638        }
639    }
640
641    /// Number of rows in this block.
642    pub fn rows(&self) -> usize {
643        self.block.rows
644    }
645
646    /// Number of columns in this block.
647    pub fn cols(&self) -> usize {
648        self.block.cols
649    }
650
651    /// Divide into two blocks at the given column.
652    ///
653    /// # Examples
654    ///
655    /// ```
656    /// let data = &mut [
657    ///     [0, 1, 2],
658    ///     [3, 4, 5],
659    /// ];
660    ///
661    /// let block = matrix_slice::from_array_rows_mut(data);
662    /// let (left, right) = block.split_at_col(2);
663    ///
664    /// assert_eq!(left[(1, 0)], 3);
665    /// assert_eq!(right[(1, 0)], 5);
666    /// ```
667    pub fn split_at_col(self, mid: usize) -> (BlockMut<'data, T>, BlockMut<'data, T>) {
668        self.split_at_col_checked(mid).unwrap()
669    }
670
671    /// Divide into two blocks at the given column.
672    ///
673    /// See [`Self::split_at_col`] but returns `None` if out of bounds.
674    pub fn split_at_col_checked(
675        self,
676        mid: usize,
677    ) -> Option<(BlockMut<'data, T>, BlockMut<'data, T>)> {
678        if let Some((lhs, rhs, offset)) = self.block.split_at_col(mid) {
679            // SAFETY:
680            // - `split_at_col` guarantees that `offset` is in-bounds of the
681            // provenance tracked by `self.block`, which is in-sync with the pointer field
682            // (but we not necessary access these without synchronization). By extension
683            // of being in-bounds of the allocation the offset does not overflow `isize`.
684            // - the two blocks have disjunct access to the same elements as the input that is
685            // consumed by this operation.
686            Some((
687                BlockMut {
688                    data: self.data,
689                    block: lhs,
690                    lifetime: self.lifetime,
691                },
692                BlockMut {
693                    data: unsafe { self.data.add(offset) },
694                    block: rhs,
695                    lifetime: self.lifetime,
696                },
697            ))
698        } else {
699            None
700        }
701    }
702
703    /// Divide into two blocks at the given row.
704    ///
705    /// # Examples
706    ///
707    /// ```
708    /// let data = &mut [
709    ///     [0, 1, 2],
710    ///     [3, 4, 5],
711    /// ];
712    ///
713    /// let block = matrix_slice::from_array_rows_mut(data);
714    /// let (top, bot) = block.split_at_row(1);
715    ///
716    /// assert_eq!(top[(0, 2)], 2);
717    /// assert_eq!(bot[(0, 2)], 5);
718    /// ```
719    pub fn split_at_row(self, mid: usize) -> (BlockMut<'data, T>, BlockMut<'data, T>) {
720        self.split_at_row_checked(mid).unwrap()
721    }
722
723    /// Divide into two blocks at the given row.
724    ///
725    /// See [`Self::split_at_row`] but returns `None` if out of bounds.
726    pub fn split_at_row_checked(
727        self,
728        mid: usize,
729    ) -> Option<(BlockMut<'data, T>, BlockMut<'data, T>)> {
730        if let Some((lhs, rhs, offset)) = self.block.split_at_row(mid) {
731            // SAFETY:
732            // - `split_at_row` guarantees that `offset` is in-bounds of the
733            // provenance tracked by `self.block`, which is in-sync with the pointer field
734            // (but we not necessary access these without synchronization). By extension
735            // of being in-bounds of the allocation the offset does not overflow `isize`.
736            // - the two blocks have disjunct access to the same elements as the input that is
737            // consumed by this operation.
738            Some((
739                BlockMut {
740                    data: self.data,
741                    block: lhs,
742                    lifetime: self.lifetime,
743                },
744                BlockMut {
745                    data: unsafe { self.data.add(offset) },
746                    block: rhs,
747                    lifetime: self.lifetime,
748                },
749            ))
750        } else {
751            None
752        }
753    }
754
755    /// Choose a single row and refer to its data.
756    ///
757    /// # Examples
758    ///
759    /// ```
760    /// let data = &mut [
761    ///     [0, 1, 2],
762    ///     [3, 4, 5],
763    ///     [6, 7, 8],
764    /// ];
765    ///
766    /// let mut block = matrix_slice::from_array_rows_mut(data);
767    /// let mut row = block.reborrow().row(1);
768    /// row[0] = 0x42;
769    /// assert_eq!(block[(1, 0)], 0x42);
770    /// ```
771    pub fn row(self, row: usize) -> VecMut<'data, T> {
772        self.row_checked(row).unwrap()
773    }
774
775    /// Choose a single row and refer to its data.
776    ///
777    /// See [`Self::row`] but returns `None` if out of bounds.
778    pub fn row_checked(self, row: usize) -> Option<VecMut<'data, T>> {
779        let (_, block, offset) = self.block.split_at_row(row)?;
780
781        if block.rows == 0 {
782            return None;
783        }
784
785        // - `split_at_row` guarantees that `offset` is in-bounds of the
786        // provenance tracked by `self.block`, which is in-sync with the pointer field
787        // (but we not necessary access these without synchronization). By extension
788        // of being in-bounds of the allocation the offset does not overflow `isize`.
789        // - the `block` has disjunct access to its column elements and contains
790        // at least one row of data as asserted. Elements within a row have pitch `1`.
791        Some(VecMut {
792            block: VectorSlice {
793                count: block.cols,
794                pitch: 1,
795            },
796            // SAFETY: see above.
797            data: unsafe { self.data.add(offset) },
798            lifetime: self.lifetime,
799        })
800    }
801
802    /// Choose a single column and refer to its data.
803    ///
804    /// # Examples
805    ///
806    /// ```
807    /// let data = &mut [
808    ///     [0, 1, 2],
809    ///     [3, 4, 5],
810    ///     [6, 7, 8],
811    /// ];
812    ///
813    /// let mut block = matrix_slice::from_array_rows_mut(data);
814    /// let mut row = block.reborrow().col(1);
815    /// row[0] = 0x42;
816    /// assert_eq!(block[(0, 1)], 0x42);
817    /// ```
818    pub fn col(self, col: usize) -> VecMut<'data, T> {
819        self.col_checked(col).unwrap()
820    }
821
822    /// Choose a single column and refer to its data.
823    ///
824    /// See [`Self::col`] but returns `None` if out of bounds.
825    pub fn col_checked(self, col: usize) -> Option<VecMut<'data, T>> {
826        let (_, block, offset) = self.block.split_at_col(col)?;
827
828        if block.cols == 0 {
829            return None;
830        }
831
832        // - `split_at_col` guarantees that `offset` is in-bounds of the
833        // provenance tracked by `self.block`, which is in-sync with the pointer field
834        // (but we not necessary access these without synchronization). By extension
835        // of being in-bounds of the allocation the offset does not overflow `isize`.
836        // - the `block` has disjunct access to its row elements and contains
837        // at least one column of data as asserted. Elements within a column have pitch
838        // `block.pitch`.
839        Some(VecMut {
840            block: VectorSlice {
841                count: block.rows,
842                pitch: block.pitch,
843            },
844            // SAFETY: see above.
845            data: unsafe { self.data.add(offset) },
846            lifetime: self.lifetime,
847        })
848    }
849
850    /// Choose a range of rows and contract the block to that.
851    ///
852    /// The argument type is flexible, allowing ranges (`1..3`), half open ranges (`2..` and `..2`)
853    /// among others. See the [`MatrixIndex`] trait, which is sealed though as its details are not
854    /// yet finalized.
855    ///
856    /// # Examples
857    ///
858    /// ```
859    /// let data = &mut [
860    ///     [0, 1, 2],
861    ///     [3, 4, 5],
862    ///     [6, 7, 8],
863    /// ];
864    ///
865    /// let block = matrix_slice::from_array_rows_mut(data);
866    ///
867    /// let center = block.select_rows(1..2).unwrap();
868    /// assert_eq!(center.rows(), 1);
869    /// assert_eq!(center.cols(), 3);
870    /// assert_eq!(center[(0, 1)], 4);
871    /// ```
872    pub fn select_rows<R>(self, range: R) -> Option<BlockMut<'data, T>>
873    where
874        R: MatrixIndex,
875    {
876        let (start, len) = range.into_start_and_len(self.block.rows)?;
877        let (_, block, offset) = self.block.split_at_row(start)?;
878        assert!(block.rows >= len);
879
880        Some(BlockMut {
881            block: BlockSlice { rows: len, ..block },
882            // SAFETY:
883            // - `split_at_row` guarantees that `offset` is in-bounds of the provenance tracked by
884            // `self.block`, which is in-sync with the pointer field (but we not necessary access
885            // these without synchronization). By extension of being in-bounds of the allocation
886            // the offset does not overflow `isize`.
887            // - the block has access to a subset of elements as `self` which is consumed. This
888            // holds because `into_start_and_len` ensures that `start + len <= self.block.rows`.
889            data: unsafe { self.data.add(offset) },
890            lifetime: self.lifetime,
891        })
892    }
893
894    /// Choose a range of columns and contract the block to that.
895    ///
896    /// The argument type is flexible, allowing ranges (`1..3`), half open ranges (`2..` and `..2`)
897    /// among others. See the [`MatrixIndex`] trait, which is sealed though as its details are not
898    /// yet finalized.
899    ///
900    /// ```
901    /// let data = &mut [
902    ///     [0, 1],
903    ///     [3, 4],
904    ///     [6, 7],
905    /// ];
906    ///
907    /// let mut block = matrix_slice::from_array_rows_mut(data);
908    ///
909    /// assert!(block.reborrow().select_cols(1..).is_some_and(|b| b.cols() == 1));
910    /// assert!(block.reborrow().select_cols(2..).is_some_and(|b| b.cols() == 0));
911    /// assert!(block.reborrow().select_cols(3..).is_none());
912    /// ```
913    pub fn select_cols<R>(self, range: R) -> Option<BlockMut<'data, T>>
914    where
915        R: MatrixIndex,
916    {
917        let (start, len) = range.into_start_and_len(self.block.cols)?;
918        let (_, block, offset) = self.block.split_at_col(start)?;
919        debug_assert!(block.cols >= len);
920
921        Some(BlockMut {
922            block: BlockSlice { cols: len, ..block },
923            // SAFETY:
924            // - `split_at_col` guarantees that `offset` is in-bounds of the provenance tracked by
925            // `self.block`, which is in-sync with the pointer field (but we not necessary access
926            // these without synchronization). By extension of being in-bounds of the allocation
927            // the offset does not overflow `isize`.
928            // - the block has access to a subset of elements as `self` which is consumed. This
929            // holds because `into_start_and_len` ensures that `start + len <= self.block.cols`.
930            data: unsafe { self.data.add(offset) },
931            lifetime: self.lifetime,
932        })
933    }
934
935    /// Choose a sub-block by its range of rows and columns.
936    pub fn select(
937        self,
938        row_range: impl MatrixIndex,
939        col_range: impl MatrixIndex,
940    ) -> Option<BlockMut<'data, T>> {
941        let block = self.select_rows(row_range)?;
942        block.select_cols(col_range)
943    }
944
945    /// Extract a contiguous underlying slice of elements if the block is contiguous.
946    ///
947    /// # Examples
948    ///
949    /// ```
950    /// let data = &mut [[0u32; 3]; 3];
951    /// let mut block = matrix_slice::from_array_rows_mut(data);
952    ///
953    /// let (mut part, _) = block.reborrow().split_at_row(2);
954    /// assert!(part.into_contiguous_slice().is_some());
955    ///
956    /// let (pre, post) = block.reborrow().split_at_col(2);
957    /// assert!(pre.into_contiguous_slice().is_none());
958    /// assert!(post.into_contiguous_slice().is_none());
959    ///
960    /// let (same, _) = block.reborrow().split_at_col(3);
961    /// assert!(same.into_contiguous_slice().is_some());
962    /// ```
963    pub fn into_contiguous_slice(self) -> Option<&'data mut [T]> {
964        if let Some(items) = self.block.contiguous_span() {
965            // SAFETY: `contiguous_span` ensures the block covers `items` contiguous elements.
966            // Since pointer provenance is a superset of block's element access that implies the
967            // pointer also has provenance for these elements. Since we have unique access to all
968            // the elements in the block we have non-aliased access to the whole slice.
969            Some(unsafe { core::slice::from_raw_parts_mut(self.data.as_ptr().cast(), items) })
970        } else {
971            None
972        }
973    }
974
975    /// Turn this into a slice of the first row, assuming it is at most one row.
976    fn fake_contiguity(mut self) -> &'data mut [T] {
977        self.block.fake_contiguity();
978        self.into_contiguous_slice().unwrap()
979    }
980
981    /// Extract access as a slice of arrays if the block is contiguous.
982    ///
983    /// The caller must choose `N` matching the number of columns.
984    ///
985    /// # Examples
986    ///
987    /// ```
988    /// let data = &mut [[0u32; 3]; 3];
989    /// let mut block = matrix_slice::from_array_rows_mut(data);
990    ///
991    /// // Turns this back into the same type as `data` had.
992    /// assert!(block.reborrow().into_array_rows_checked::<3>().is_some());
993    ///
994    /// // Using an incorrect number of columns fails.
995    /// assert!(block.reborrow().into_array_rows_checked::<2>().is_none());
996    ///
997    /// // Can still be used after splitting at rows.
998    /// let (_, mut block) = block.split_at_row(2);
999    /// assert!(block.reborrow().into_array_rows_checked::<3>().is_some());
1000    /// ```
1001    pub fn into_array_rows_checked<const N: usize>(self) -> Option<&'data mut [[T; N]]> {
1002        if let Some(rows) = self.block.contiguous_arrays::<N>() {
1003            // SAFETY: `` ensures the block covers `items` contiguous N-arrays of
1004            // elements. Since pointer provenance is a superset of block's element access that
1005            // implies the pointer also has provenance for these elements. Since we have unique
1006            // access to all the elements in the block we have non-aliased access to the whole
1007            // slice of elements. A slice and a slice of arrays have the same layout so the same
1008            // holds for the correctly sized array the length of which `contiguous_arrays` promises
1009            // to return.
1010            Some(unsafe { core::slice::from_raw_parts_mut(self.data.as_ptr().cast(), rows) })
1011        } else {
1012            None
1013        }
1014    }
1015
1016    /// Turn this unique reference into a shared reference.
1017    pub fn cast_const(self) -> BlockRef<'data, T> {
1018        // SAFETY: shared access can always be re-tagged from unique access.
1019        BlockRef {
1020            data: self.data,
1021            block: self.block,
1022            lifetime: PhantomData,
1023        }
1024    }
1025
1026    /// Create a unique reference to this block with a shorter lifetime.
1027    pub fn reborrow(&mut self) -> BlockMut<'_, T> {
1028        // SAFETY: Unique access is created by deriving it from our current pointer so the
1029        // provenance is the same, and temporally it can not overlap access through the current
1030        // value due to the lifetime enforcing a borrow relationship.
1031        BlockMut {
1032            data: self.data,
1033            block: self.block,
1034            lifetime: PhantomData,
1035        }
1036    }
1037
1038    /// Iterate over the rows of this block.
1039    pub fn iter_rows(self) -> IterRows<'data, T> {
1040        self.cast_const().iter_rows()
1041    }
1042
1043    /// Iterate over the rows of this block.
1044    pub fn iter_rows_mut(self) -> IterRowsMut<'data, T> {
1045        IterRowsMut { block: self }
1046    }
1047
1048    /// Modify the item type to a `Cell`, allowing interior mutability.
1049    ///
1050    /// This is the equivalent of [`Cell::from_mut`] over elements in this slice.
1051    pub fn as_cells(self) -> BlockMut<'data, Cell<T>> {
1052        // SAFETY: `Cell<T>` has the same layout as `T`.
1053        BlockMut {
1054            data: self.data.cast(),
1055            block: self.block,
1056            lifetime: PhantomData,
1057        }
1058    }
1059}
1060
1061impl<'data, T> BlockMut<'data, Cell<T>> {
1062    /// Modify the item type from a `Cell` to its interior type.
1063    ///
1064    /// This is the equivalent of [`Cell::get_mut`] over elements in this slice.
1065    pub fn as_cell_items(self) -> BlockMut<'data, T> {
1066        // SAFETY: `Cell<T>` has the same layout as `T`.
1067        BlockMut {
1068            data: self.data.cast(),
1069            block: self.block,
1070            lifetime: PhantomData,
1071        }
1072    }
1073}
1074
1075impl<T> ops::Index<(usize, usize)> for BlockMut<'_, T> {
1076    type Output = T;
1077
1078    fn index(&self, index: (usize, usize)) -> &Self::Output {
1079        let idx = self.block.in_bounds_offset(index.0, index.1);
1080        // SAFETY: Index is bounded by `total_span` which itself is a lower estimate of the
1081        // provenance of the pointer.
1082        unsafe { &*self.data.as_ptr().add(idx) }
1083    }
1084}
1085
1086impl<T> ops::IndexMut<(usize, usize)> for BlockMut<'_, T> {
1087    fn index_mut(&mut self, index: (usize, usize)) -> &mut Self::Output {
1088        let idx = self.block.in_bounds_offset(index.0, index.1);
1089        // SAFETY: Index is bounded by `total_span` which itself is a lower estimate of the
1090        // provenance of the pointer.
1091        unsafe { &mut *self.data.as_ptr().add(idx) }
1092    }
1093}
1094
1095/// Represents the provenance of a pointer to a block of a matrix.
1096///
1097/// FIXME: before exposing this consider `PartialEq, … Ord` implications. These were added to
1098/// satisfy the `Pointee` trait requirements but really what does ordering mean? We have chosen the
1099/// field `pitch` to be last but that is super arbitrary.
1100///
1101/// We assume row major order here for the convention of _naming_ things. That is, when we say row
1102/// we mean a tightly packed slice of items. This implies that the item pitch is assumed to be `1`.
1103/// We have two major possible choices in representation a block-subset of a matrix: store the
1104/// dimensions of the block with a matrix row pitch or store the total size of the matrix and two
1105/// lengths.
1106///
1107/// The former of these allows us to represent both `0×N` and `M×0` blocks naturally, while the
1108/// latter allows one of them but provides a fast capacity that's pre-calculated. We choose the
1109/// former. In either case we need to store three `usize` values. Note that the total span of items
1110/// is *not* `rows * pitch` since the last row might be ragged.
1111#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
1112struct BlockSlice {
1113    rows: usize,
1114    cols: usize,
1115    pitch: usize,
1116}
1117
1118const _: () = {
1119    // As per Rust 1.92's `Pointee` trait. Suspicious: `Ord`. See comment on `BlockSlice`.
1120    use core::{fmt, hash};
1121
1122    fn _can_eventually_be_ptr_metadata<
1123        // Missing: `Freeze` which is unstable
1124        Metadata: fmt::Debug + Copy + Send + Sync + Ord + hash::Hash + Unpin,
1125    >() {
1126    }
1127
1128    let _ = _can_eventually_be_ptr_metadata::<BlockSlice>;
1129};
1130
1131impl BlockSlice {
1132    /// The number of elements if this block is contiguous (cols equals pitch).
1133    fn contiguous_span(&self) -> Option<usize> {
1134        if self.cols == self.pitch {
1135            Some(self.rows * self.cols)
1136        } else {
1137            None
1138        }
1139    }
1140
1141    /// The number of rows if this block is contiguous (cols equals pitch) and matching a static
1142    /// count of column elements.
1143    fn contiguous_arrays<const N: usize>(&self) -> Option<usize> {
1144        if self.cols == self.pitch && self.cols == N {
1145            Some(self.rows)
1146        } else {
1147            None
1148        }
1149    }
1150
1151    /// The number of elements spanned by this block (including those we are not allowed to
1152    /// access).
1153    fn total_span(&self) -> usize {
1154        if let Some(all_but_last) = self.rows.checked_sub(1) {
1155            all_but_last * self.pitch + self.cols
1156        } else {
1157            0
1158        }
1159    }
1160
1161    /// The caller must ensure that this block has at most one row.
1162    fn fake_contiguity(&mut self) {
1163        debug_assert!(self.rows <= 1);
1164        debug_assert!(self.cols <= self.pitch);
1165
1166        self.rows = self.rows.min(1);
1167        // SAFETY: Reducing the pitch when we have at most one row does not change the elements we
1168        // may refer to. The pitch always exceeds the number of columns.
1169        self.pitch = self.cols;
1170    }
1171
1172    /// Split into two block descriptors.
1173    ///
1174    /// Returns `Some` with two valid blocks. The first block is in-bounds. Also returns an offset
1175    /// that is in-bounds of the current block and such that the elements valid for both blocks do
1176    /// not alias. The second block is in-bounds when interpreted as start at the offset.
1177    fn split_at_row(self, mid: usize) -> Option<(BlockSlice, BlockSlice, usize)> {
1178        let n = self.rows.checked_sub(mid)?;
1179
1180        let lhs = BlockSlice {
1181            rows: mid,
1182            cols: self.cols,
1183            pitch: self.pitch,
1184        };
1185
1186        let rhs = BlockSlice {
1187            rows: n,
1188            cols: self.cols,
1189            pitch: self.pitch,
1190        };
1191
1192        // Careful: If we split a block after its last row (i.e. lhs and self are identical),
1193        // the naive offset of rows * pitch may point beyond the total span of elements covered
1194        // by ourselves. In this case the rhs does not cover any row so we assign it any
1195        // in-bounds offset.
1196        let offset = if n > 0 { mid * self.pitch } else { 0 };
1197        debug_assert!(offset <= self.total_span());
1198
1199        Some((lhs, rhs, offset))
1200    }
1201
1202    fn split_at_col(self, mid: usize) -> Option<(BlockSlice, BlockSlice, usize)> {
1203        let n = self.cols.checked_sub(mid)?;
1204
1205        let lhs = BlockSlice {
1206            rows: self.rows,
1207            cols: mid,
1208            pitch: self.pitch,
1209        };
1210
1211        let rhs = BlockSlice {
1212            rows: self.rows,
1213            cols: n,
1214            pitch: self.pitch,
1215        };
1216
1217        // If we have no rows at all then this block does not cover any elements so we must
1218        // pick an offset of 0 to guarantee in-bounds access. The good news is that this case
1219        // also implies that the other side is empty so its offset does not matter.
1220        let offset = if self.rows > 0 { mid } else { 0 };
1221        debug_assert!(offset <= self.total_span());
1222
1223        Some((lhs, rhs, offset))
1224    }
1225
1226    /// Return the absolute position of the element, if in bounds. Otherwise, panic.
1227    fn in_bounds_offset(&self, row: usize, col: usize) -> usize {
1228        assert!(row < self.rows);
1229        assert!(col < self.cols);
1230        let idx = row * self.pitch + col;
1231        debug_assert!(idx < self.total_span());
1232        idx
1233    }
1234}
1235
1236/// Represents the provenance of a pointer to a single column/row of a matrix.
1237///
1238/// FIXME: before exposing this consider `PartialEq, … Ord` implications. These were added to
1239/// satisfy the `Pointee` trait requirements but really what does ordering mean? We have chosen the
1240/// field `pitch` to be last but that is super arbitrary.
1241#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
1242struct VectorSlice {
1243    count: usize,
1244    pitch: usize,
1245}
1246
1247const _: () = {
1248    // As per Rust 1.92's `Pointee` trait. Suspicious: `Ord`. See comment on `VectorSlice`.
1249    use core::{fmt, hash};
1250
1251    fn _can_eventually_be_ptr_metadata<
1252        // Missing: `Freeze` which is unstable
1253        Metadata: fmt::Debug + Copy + Send + Sync + Ord + hash::Hash + Unpin,
1254    >() {
1255    }
1256
1257    let _ = _can_eventually_be_ptr_metadata::<VectorSlice>;
1258};
1259
1260impl VectorSlice {
1261    /// Split into two vector descriptors.
1262    ///
1263    /// Returns `Some` with two valid slice. The first slice is in-bounds. Also returns an offset
1264    /// that is in-bounds of the current slice and such that the elements valid for both blocks do
1265    /// not alias. The second block is in-bounds when interpreted as start at the offset.
1266    fn split_at(self, mid: usize) -> Option<(VectorSlice, VectorSlice, usize)> {
1267        let right_count = self.count.checked_sub(mid)?;
1268
1269        let left = VectorSlice {
1270            count: mid,
1271            pitch: self.pitch,
1272        };
1273
1274        let right = VectorSlice {
1275            count: right_count,
1276            pitch: self.pitch,
1277        };
1278
1279        // We need to make sure that this is in-bounds of the allocation. Note that the provenance
1280        // stretches only past our last element, not an additional pitch past it. So we can use the
1281        // simple formula only if there are elements covered by the right part of the split.
1282        // Fortunately the opposite of this implies that the right does not cover any elements and
1283        // we can thus use any inbounds pointer; like the zero offset.
1284        let offset = if right_count == 0 {
1285            0
1286        } else {
1287            mid * self.pitch
1288        };
1289
1290        Some((left, right, offset))
1291    }
1292
1293    /// Return the absolute position of the element, if in bounds. Otherwise, panic.
1294    fn in_bounds_offset(&self, index: usize) -> usize {
1295        assert!(index < self.count);
1296        index * self.pitch
1297    }
1298}
1299
1300/// Iterate over the rows of a block in a matrix.
1301///
1302/// We assume row-major matrices here, a row is a contiguous slice of items.
1303pub struct IterRows<'a, T> {
1304    block: BlockRef<'a, T>,
1305}
1306
1307impl<'data, T> Iterator for IterRows<'data, T> {
1308    type Item = &'data [T];
1309
1310    fn next(&mut self) -> Option<Self::Item> {
1311        if self.block.rows() == 0 {
1312            None
1313        } else {
1314            // FIXME: add `split_off_rows` instead.
1315            let (row, rest) = core::mem::take(&mut self.block).split_at_row(1);
1316            self.block = rest;
1317            // One row as it was created from `split_at_row(1)`.
1318            Some(row.fake_contiguity())
1319        }
1320    }
1321}
1322
1323/// Iterate over mutable rows of a block in a matrix.
1324///
1325/// We assume row-major matrices here, a row is a contiguous slice of items.
1326pub struct IterRowsMut<'a, T> {
1327    block: BlockMut<'a, T>,
1328}
1329
1330impl<'data, T> Iterator for IterRowsMut<'data, T> {
1331    type Item = &'data mut [T];
1332
1333    fn next(&mut self) -> Option<Self::Item> {
1334        if self.block.rows() == 0 {
1335            None
1336        } else {
1337            // FIXME: add `split_off_rows` instead.
1338            let (row, rest) = core::mem::take(&mut self.block).split_at_row(1);
1339            self.block = rest;
1340            // One row as it was created from `split_at_row(1)`.
1341            Some(row.fake_contiguity())
1342        }
1343    }
1344}
1345
1346pub trait MatrixIndex: sealed::Sealed {}
1347
1348impl MatrixIndex for ops::Range<usize> {}
1349impl MatrixIndex for ops::RangeInclusive<usize> {}
1350impl MatrixIndex for ops::RangeFrom<usize> {}
1351impl MatrixIndex for ops::RangeTo<usize> {}
1352impl MatrixIndex for ops::RangeToInclusive<usize> {}
1353impl MatrixIndex for ops::RangeFull {}
1354
1355pub trait OneSidedMatrixIndex: sealed::SealedOneSided {}
1356
1357impl OneSidedMatrixIndex for ops::RangeFrom<usize> {}
1358impl OneSidedMatrixIndex for ops::RangeTo<usize> {}
1359impl OneSidedMatrixIndex for ops::RangeToInclusive<usize> {}
1360
1361mod sealed {
1362    use core::ops;
1363
1364    pub trait Sealed {
1365        /// SAFETY: It is crucial that `start + len <= dim` holds if `Some` is returned.
1366        fn into_start_and_len(self, dim: usize) -> Option<(usize, usize)>;
1367    }
1368
1369    pub trait SealedOneSided {
1370        /// SAFETY: It is crucial that `split <= dim` holds if `Some` is returned.
1371        fn into_split_point(self, dim: usize) -> Option<(bool, usize)>;
1372    }
1373
1374    impl Sealed for ops::Range<usize> {
1375        fn into_start_and_len(self, dim: usize) -> Option<(usize, usize)> {
1376            if self.start <= self.end && self.end <= dim {
1377                // SAFETY: overflow can not have occurred, so `self.start + len = self.end <= dim`.
1378                Some((self.start, self.end - self.start))
1379            } else {
1380                None
1381            }
1382        }
1383    }
1384
1385    impl Sealed for ops::RangeInclusive<usize> {
1386        fn into_start_and_len(self, dim: usize) -> Option<(usize, usize)> {
1387            let start = *self.start();
1388            let end = *self.end();
1389            if start <= end && end < dim {
1390                // SAFETY: overflow can not have occurred, so `self.start + len = self.end + 1 <= dim`.
1391                Some((start, end - start + 1))
1392            } else {
1393                None
1394            }
1395        }
1396    }
1397
1398    impl Sealed for ops::RangeFrom<usize> {
1399        fn into_start_and_len(self, dim: usize) -> Option<(usize, usize)> {
1400            if self.start <= dim {
1401                // SAFETY: overflow can not have occurred, so `self.start + len = dim <= dim`.
1402                Some((self.start, dim - self.start))
1403            } else {
1404                None
1405            }
1406        }
1407    }
1408
1409    impl Sealed for ops::RangeTo<usize> {
1410        fn into_start_and_len(self, dim: usize) -> Option<(usize, usize)> {
1411            if self.end <= dim {
1412                // SAFETY: `self.end <= dim` by test.
1413                Some((0, self.end))
1414            } else {
1415                None
1416            }
1417        }
1418    }
1419
1420    impl Sealed for ops::RangeToInclusive<usize> {
1421        fn into_start_and_len(self, dim: usize) -> Option<(usize, usize)> {
1422            if self.end < dim {
1423                // SAFETY: `self.end + 1 <= dim` by test.
1424                Some((0, self.end + 1))
1425            } else {
1426                None
1427            }
1428        }
1429    }
1430
1431    impl Sealed for ops::RangeFull {
1432        fn into_start_and_len(self, dim: usize) -> Option<(usize, usize)> {
1433            // SAFETY: `dim <= dim` by tautology.
1434            Some((0, dim))
1435        }
1436    }
1437
1438    impl SealedOneSided for ops::RangeFrom<usize> {
1439        fn into_split_point(self, dim: usize) -> Option<(bool, usize)> {
1440            if self.start <= dim {
1441                // SAFETY: `self.start <= dim` by test.
1442                Some((false, self.start))
1443            } else {
1444                None
1445            }
1446        }
1447    }
1448
1449    impl SealedOneSided for ops::RangeTo<usize> {
1450        fn into_split_point(self, dim: usize) -> Option<(bool, usize)> {
1451            if self.end <= dim {
1452                // SAFETY: `self.end <= dim` by test.
1453                Some((true, self.end))
1454            } else {
1455                None
1456            }
1457        }
1458    }
1459
1460    impl SealedOneSided for ops::RangeToInclusive<usize> {
1461        fn into_split_point(self, dim: usize) -> Option<(bool, usize)> {
1462            if self.end < dim {
1463                // SAFETY: `self.end <= dim` by test.
1464                Some((true, self.end + 1))
1465            } else {
1466                None
1467            }
1468        }
1469    }
1470}
1471
1472/// A reference to a single column/row of a matrix.
1473///
1474/// This is similar to `&[T]` but with a pitch potentially different from `1` between its elements,
1475/// i.e. there is no guarantee of contiguity. As a consequence this does not have a simple
1476/// past-the-end pointer like a slice would have. For an empty slice the only guaranteed-valid
1477/// pointer is the base pointer itself while for larger slices the last guaranteed-valid pointer is
1478/// one-past the last element, _not_ one additional pitch.
1479///
1480/// Created from its constructors or a block reference via the [`BlockRef::col`] and
1481/// [`BlockRef::row`] methods.
1482#[derive(Copy, Clone)]
1483pub struct VecRef<'a, T> {
1484    // Internal invariant: the size of the block is a subset of the provenance of the pointer.
1485    data: NonNull<T>,
1486    block: VectorSlice,
1487    lifetime: PhantomData<&'a [T]>,
1488}
1489
1490// SAFETY: See `&[T]`. The reference can be used to, potentially, get a `&T` for each element in
1491// the block and thus the block itself provides the exact same properties as `T`. The `VecRef` is
1492// then `&[T]` itself and thus has properties of a reference to such a type. Refer to the
1493// reference: <https://doc.rust-lang.org/stable/std/primitive.reference.html>
1494//
1495// We have `&T: Sync` iff `T: Sync`
1496unsafe impl<T> Sync for VecRef<'_, T> where T: Sync {}
1497// We have `&T: Send` iff `T: Sync`
1498unsafe impl<T> Send for VecRef<'_, T> where T: Sync {}
1499
1500impl<'data, T> VecRef<'data, T> {
1501    /// Create a new vector reference from a raw slice and pitch.
1502    ///
1503    /// The resulting block refers to the first column of the matrix.
1504    ///
1505    /// # Panics
1506    ///
1507    /// Panics if the pitch is zero.
1508    pub fn new(data: &'data [T], pitch: usize) -> Self {
1509        assert_ne!(pitch, 0);
1510
1511        VecRef {
1512            // SAFETY: construction implies `count * pitch <= data.len()`.
1513            block: VectorSlice {
1514                count: data.len() / pitch,
1515                pitch,
1516            },
1517            data: NonNull::from(data).cast(),
1518            lifetime: PhantomData,
1519        }
1520    }
1521
1522    /// Create a new vector reference from a raw slice with pitch `1`.
1523    pub fn from_slice(data: &'data [T]) -> Self {
1524        VecRef {
1525            block: VectorSlice {
1526                count: data.len(),
1527                pitch: 1,
1528            },
1529            data: NonNull::from(data).cast(),
1530            lifetime: PhantomData,
1531        }
1532    }
1533
1534    /// Number of elements in this vector.
1535    pub fn len(&self) -> usize {
1536        self.block.count
1537    }
1538
1539    /// Whether this vector is empty.
1540    pub fn is_empty(&self) -> bool {
1541        self.block.count == 0
1542    }
1543
1544    /// Divide into two vectors at the given element.
1545    ///
1546    /// # Examples
1547    ///
1548    /// ```
1549    /// use matrix_slice::VecRef;
1550    ///
1551    /// let data = &[0, 1, 2, 3, 4, 5];
1552    ///
1553    /// let block = VecRef::new(data, 1);
1554    /// let (left, right) = block.split_at(2);
1555    ///
1556    /// assert_eq!(left[1], 1);
1557    /// assert_eq!(right[3], 5);
1558    /// ```
1559    pub fn split_at(self, mid: usize) -> (VecRef<'data, T>, VecRef<'data, T>) {
1560        self.split_at_checked(mid).unwrap()
1561    }
1562
1563    /// Divide into two vectors at the given element.
1564    ///
1565    /// See [`Self::split_at`] but returns `None` if out of bounds.
1566    pub fn split_at_checked(mut self, mid: usize) -> Option<(VecRef<'data, T>, VecRef<'data, T>)> {
1567        // Let's assume this will collapse during const-prop after the type here is inserted.
1568        let tail = self.split_off(mid..)?;
1569        Some((self, tail))
1570    }
1571
1572    /// Take part of the vector.
1573    ///
1574    /// # Examples
1575    ///
1576    /// ```
1577    /// use matrix_slice::VecRef;
1578    ///
1579    /// let data = &[0, 1, 2, 3, 4, 5];
1580    /// let mut vec = VecRef::new(data, 1);
1581    ///
1582    /// // Does nothing.
1583    /// assert!(vec.split_off(6..).is_some_and(|v| v.is_empty()));
1584    /// assert!(vec.split_off(7..).is_none());
1585    /// assert!(vec.split_off(..7).is_none());
1586    ///
1587    /// let right = vec.split_off(2..).unwrap();
1588    /// assert_eq!(vec.len(), 2);
1589    /// assert_eq!(right[3], 5);
1590    /// ```
1591    ///
1592    /// You can also split off the start:
1593    ///
1594    /// ```
1595    /// use matrix_slice::VecRef;
1596    ///
1597    /// let data = &[0, 1, 2, 3, 4, 5];
1598    /// let mut vec = VecRef::new(data, 1);
1599    /// let start = vec.split_off(..=2).unwrap();
1600    ///
1601    /// assert_eq!(vec[0], 3);
1602    /// assert_eq!(start[0], 0);
1603    /// ```
1604    pub fn split_off<R>(&mut self, range: R) -> Option<Self>
1605    where
1606        R: OneSidedMatrixIndex,
1607    {
1608        let (is_front, split_point) = range.into_split_point(self.block.count)?;
1609        let (left, right, offset) = self.block.split_at(split_point)?;
1610
1611        let ptr = self.data;
1612        let (ours, theirs) = if is_front {
1613            ((right, offset), (left, 0))
1614        } else {
1615            ((left, 0), (right, offset))
1616        };
1617
1618        self.block = ours.0;
1619        self.data = unsafe { ptr.add(ours.1) };
1620
1621        Some(VecRef {
1622            block: theirs.0,
1623            data: unsafe { ptr.add(theirs.1) },
1624            lifetime: self.lifetime,
1625        })
1626    }
1627
1628    /// Choose a range of elements and contract the vector to that.
1629    pub fn select<R>(self, range: R) -> Option<VecRef<'data, T>>
1630    where
1631        R: MatrixIndex,
1632    {
1633        let (start, len) = range.into_start_and_len(self.block.count)?;
1634        let (_, block, offset) = self.block.split_at(start)?;
1635        // Safety: ensures that the resulting block is more constrained, this property should be
1636        // ensured by our sealed `MatrixIndex` implementations.
1637        assert!(block.count >= len);
1638
1639        Some(VecRef {
1640            block: VectorSlice {
1641                count: len,
1642                ..block
1643            },
1644            // SAFETY: offset is in-bounds as per `split_at` contract.
1645            data: unsafe { self.data.add(offset) },
1646            lifetime: self.lifetime,
1647        })
1648    }
1649
1650    /// # Examples
1651    ///
1652    /// ```
1653    /// let data = &[
1654    ///     [0, 1, 2],
1655    ///     [3, 4, 5],
1656    ///     [6, 7, 8],
1657    /// ];
1658    ///
1659    /// let block = matrix_slice::from_array_rows(data);
1660    /// let column = block.col(1);
1661    ///
1662    /// assert!(column.iter().eq(&[1, 4, 7]));
1663    /// ```
1664    pub fn iter(self) -> IterVec<'data, T> {
1665        IterVec { vec: self }
1666    }
1667}
1668
1669impl<T> ops::Index<usize> for VecRef<'_, T> {
1670    type Output = T;
1671
1672    fn index(&self, index: usize) -> &Self::Output {
1673        let idx = self.block.in_bounds_offset(index);
1674        // SAFETY: Index is bounded by `total_span` which itself is a lower estimate of the
1675        // provenance of the pointer.
1676        unsafe { &*self.data.as_ptr().add(idx) }
1677    }
1678}
1679
1680/// A reference to a single column/row of a matrix.
1681///
1682/// This is similar to `&[T]` but with a pitch potentially different from `1` between its elements,
1683/// i.e. there is no guarantee of contiguity. As a consequence this does not have a simple
1684/// past-the-end pointer like a slice would have. For an empty slice the only guaranteed-valid
1685/// pointer is the base pointer itself while for larger slices the last guaranteed-valid pointer is
1686/// one-past the last element, _not_ one additional pitch.
1687///
1688/// Created from its constructors or a block reference via the [`BlockMut::col`] and
1689/// [`BlockMut::row`] methods.
1690pub struct VecMut<'a, T> {
1691    // Internal invariant: the size of the block is a subset of the provenance of the pointer. Also
1692    // we never have two `VecMut` with the same accessible elements active at the same time.
1693    data: NonNull<T>,
1694    block: VectorSlice,
1695    lifetime: PhantomData<&'a mut [T]>,
1696}
1697
1698// SAFETY: See `VecRef` but with `&mut [T]`.
1699//
1700// We have `&mut T: Sync` iff `T: Sync`
1701unsafe impl<T> Sync for VecMut<'_, T> where T: Sync {}
1702// We have `&mut T: Send` iff `T: Send`
1703unsafe impl<T> Send for VecMut<'_, T> where T: Sync {}
1704
1705impl<'data, T> VecMut<'data, T> {
1706    /// Create a new vector reference from a raw slice and pitch.
1707    ///
1708    /// The resulting block refers to the first column of the matrix.
1709    pub fn new(data: &'data mut [T], pitch: usize) -> Self {
1710        VecMut {
1711            // SAFETY: construction implies `count * pitch <= data.len()`.
1712            block: VectorSlice {
1713                count: data.len() / pitch,
1714                pitch,
1715            },
1716            data: NonNull::from(data).cast(),
1717            lifetime: PhantomData,
1718        }
1719    }
1720
1721    /// Create a new vector reference from a raw slice with pitch `1`.
1722    pub fn from_slice(data: &'data mut [T]) -> Self {
1723        VecMut {
1724            block: VectorSlice {
1725                count: data.len(),
1726                pitch: 1,
1727            },
1728            data: NonNull::from(data).cast(),
1729            lifetime: PhantomData,
1730        }
1731    }
1732
1733    /// Number of elements in this vector.
1734    pub fn len(&self) -> usize {
1735        self.block.count
1736    }
1737
1738    /// Whether this vector is empty.
1739    pub fn is_empty(&self) -> bool {
1740        self.block.count == 0
1741    }
1742
1743    /// Divide into two vectors at the given element.
1744    ///
1745    /// # Examples
1746    ///
1747    /// ```
1748    /// use matrix_slice::VecMut;
1749    ///
1750    /// let data = &mut [0, 1, 2, 3, 4, 5];
1751    ///
1752    /// let block = VecMut::new(data, 1);
1753    /// let (left, right) = block.split_at(2);
1754    ///
1755    /// assert_eq!(left[1], 1);
1756    /// assert_eq!(right[3], 5);
1757    /// ```
1758    pub fn split_at(self, mid: usize) -> (VecMut<'data, T>, VecMut<'data, T>) {
1759        self.split_at_checked(mid).unwrap()
1760    }
1761
1762    /// Divide into two vectors at the given element.
1763    ///
1764    /// See [`Self::split_at`] but returns `None` if out of bounds.
1765    pub fn split_at_checked(self, mid: usize) -> Option<(VecMut<'data, T>, VecMut<'data, T>)> {
1766        if let Some((lhs, rhs, offset)) = self.block.split_at(mid) {
1767            Some((
1768                VecMut {
1769                    data: self.data,
1770                    block: lhs,
1771                    lifetime: self.lifetime,
1772                },
1773                VecMut {
1774                    data: unsafe { self.data.add(offset) },
1775                    block: rhs,
1776                    lifetime: self.lifetime,
1777                },
1778            ))
1779        } else {
1780            None
1781        }
1782    }
1783
1784    /// Take part of the vector.
1785    ///
1786    /// # Examples
1787    ///
1788    /// ```
1789    /// use matrix_slice::VecMut;
1790    ///
1791    /// let data = &mut [0, 1, 2, 3, 4, 5];
1792    /// let mut vec = VecMut::new(data, 1);
1793    ///
1794    /// // Does nothing.
1795    /// assert!(vec.split_off(6..).is_some_and(|v| v.is_empty()));
1796    /// assert!(vec.split_off(7..).is_none());
1797    /// assert!(vec.split_off(..7).is_none());
1798    ///
1799    /// let mut right = vec.split_off(2..).unwrap();
1800    /// assert_eq!(vec.len(), 2);
1801    /// assert_eq!(right[3], 5);
1802    ///
1803    /// // The two halves are disjoint:
1804    /// right[0] = 0x42;
1805    /// assert_eq!(vec[1], 1);
1806    /// ```
1807    ///
1808    /// You can also split off the start:
1809    ///
1810    /// ```
1811    /// use matrix_slice::VecMut;
1812    ///
1813    /// let data = &mut [0, 1, 2, 3, 4, 5];
1814    /// let mut vec = VecMut::new(data, 1);
1815    /// let start = vec.split_off(..=2).unwrap();
1816    ///
1817    /// assert_eq!(vec[0], 3);
1818    /// assert_eq!(start[0], 0);
1819    /// ```
1820    pub fn split_off<R>(&mut self, range: R) -> Option<Self>
1821    where
1822        R: OneSidedMatrixIndex,
1823    {
1824        let (is_front, split_point) = range.into_split_point(self.block.count)?;
1825        let (left, right, offset) = self.block.split_at(split_point)?;
1826
1827        let ptr = self.data;
1828        let (ours, theirs) = if is_front {
1829            ((right, offset), (left, 0))
1830        } else {
1831            ((left, 0), (right, offset))
1832        };
1833
1834        self.block = ours.0;
1835        self.data = unsafe { ptr.add(ours.1) };
1836
1837        Some(VecMut {
1838            block: theirs.0,
1839            data: unsafe { ptr.add(theirs.1) },
1840            lifetime: self.lifetime,
1841        })
1842    }
1843
1844    /// Choose a range of elements and contract the vector to that.
1845    pub fn select<R>(self, range: R) -> Option<VecMut<'data, T>>
1846    where
1847        R: MatrixIndex,
1848    {
1849        let (start, len) = range.into_start_and_len(self.block.count)?;
1850        let (_, block, offset) = self.block.split_at(start)?;
1851        // Safety: ensures that the resulting block is more constrained, this property should be
1852        // ensured by our sealed `MatrixIndex` implementations.
1853        assert!(block.count >= len);
1854
1855        Some(VecMut {
1856            block: VectorSlice {
1857                count: len,
1858                ..block
1859            },
1860            // SAFETY: offset is in-bounds as per `split_at` contract.
1861            data: unsafe { self.data.add(offset) },
1862            lifetime: self.lifetime,
1863        })
1864    }
1865
1866    /// Turn this unique reference into a shared reference.
1867    pub fn cast_const(self) -> VecRef<'data, T> {
1868        // SAFETY: shared access can always be re-tagged from unique access.
1869        VecRef {
1870            data: self.data,
1871            block: self.block,
1872            lifetime: PhantomData,
1873        }
1874    }
1875
1876    /// Create a unique reference to this block with a shorter lifetime.
1877    pub fn reborrow(&mut self) -> VecMut<'_, T> {
1878        // SAFETY: Unique access is created by deriving it from our current pointer so the
1879        // provenance is the same, and temporally it can not overlap access through the current
1880        // value due to the lifetime enforcing a borrow relationship.
1881        VecMut {
1882            data: self.data,
1883            block: self.block,
1884            lifetime: PhantomData,
1885        }
1886    }
1887
1888    /// Modify the item type to a `Cell`, allowing interior mutability.
1889    ///
1890    /// This is the equivalent of [`Cell::from_mut`] over elements in this slice.
1891    pub fn as_cells(self) -> VecMut<'data, Cell<T>> {
1892        // SAFETY: `Cell<T>` has the same layout as `T`.
1893        VecMut {
1894            data: self.data.cast(),
1895            block: self.block,
1896            lifetime: PhantomData,
1897        }
1898    }
1899
1900    /// # Examples
1901    ///
1902    /// ```
1903    /// let data = &mut [
1904    ///     [0, 1, 2],
1905    ///     [3, 4, 5],
1906    ///     [6, 7, 8],
1907    /// ];
1908    ///
1909    /// let mut block = matrix_slice::from_array_rows_mut(data);
1910    ///
1911    /// for item in block.reborrow().col(1) {
1912    ///     *item *= 2;
1913    /// }
1914    ///
1915    /// assert!(block.col(1).iter().eq(&[2, 8, 14]));
1916    /// ```
1917    pub fn iter(self) -> IterVecMut<'data, T> {
1918        IterVecMut { vec: self }
1919    }
1920}
1921
1922impl<'data, T> VecMut<'data, Cell<T>> {
1923    /// Modify the item type from a `Cell` to its interior type.
1924    ///
1925    /// This is the equivalent of [`Cell::get_mut`] over elements in this slice.
1926    pub fn as_cell_items(self) -> VecMut<'data, T> {
1927        // SAFETY: `Cell<T>` has the same layout as `T`.
1928        VecMut {
1929            data: self.data.cast(),
1930            block: self.block,
1931            lifetime: PhantomData,
1932        }
1933    }
1934}
1935
1936impl<T> ops::Index<usize> for VecMut<'_, T> {
1937    type Output = T;
1938
1939    fn index(&self, index: usize) -> &Self::Output {
1940        let idx = self.block.in_bounds_offset(index);
1941        // SAFETY: Index is bounded by `total_span` which itself is a lower estimate of the
1942        // provenance of the pointer.
1943        unsafe { &*self.data.as_ptr().add(idx) }
1944    }
1945}
1946
1947impl<T> ops::IndexMut<usize> for VecMut<'_, T> {
1948    fn index_mut(&mut self, index: usize) -> &mut Self::Output {
1949        let idx = self.block.in_bounds_offset(index);
1950        // SAFETY: Index is bounded by `total_span` which itself is a lower estimate of the
1951        // provenance of the pointer. By construction the `VecMut` has exclusive access to all
1952        // elements reachable as multiples of its pitch. We access exactly one of them here.
1953        unsafe { &mut *self.data.as_ptr().add(idx) }
1954    }
1955}
1956
1957/// Iterate over the rows of a block in a matrix.
1958///
1959/// We assume row-major matrices here, a row is a contiguous slice of items.
1960pub struct IterVec<'a, T> {
1961    // FIXME: see `std::slice::Iter` which stores the end pointer instead of the full
1962    // representation. That way we do not update two fields each time, i.e. iterating only updates
1963    // a pointer and not a pointer _and_ a `count` field in `block`.
1964    vec: VecRef<'a, T>,
1965}
1966
1967impl<'data, T> IntoIterator for VecRef<'data, T> {
1968    type Item = &'data T;
1969    type IntoIter = IterVec<'data, T>;
1970
1971    fn into_iter(self) -> Self::IntoIter {
1972        self.iter()
1973    }
1974}
1975
1976// FIXME: if budget allows it we should implement common inner-iteration methods such as
1977// `for_each`, `collect`, `all` by doing pointer arithmetic on a range iterator which avoids all
1978// writes to the value's tracking state itself.
1979impl<'data, T> Iterator for IterVec<'data, T> {
1980    type Item = &'data T;
1981
1982    fn next(&mut self) -> Option<Self::Item> {
1983        let base = self.vec.split_off(..1)?;
1984        Some(unsafe { &*base.data.as_ptr() })
1985    }
1986
1987    fn size_hint(&self) -> (usize, Option<usize>) {
1988        let remain = self.vec.len();
1989        (remain, Some(remain))
1990    }
1991
1992    fn count(self) -> usize {
1993        self.vec.len()
1994    }
1995}
1996
1997impl<'data, T> core::iter::FusedIterator for IterVec<'data, T> {}
1998
1999/// Iterate over mutable rows of a block in a matrix.
2000///
2001/// We assume row-major matrices here, a row is a contiguous slice of items.
2002pub struct IterVecMut<'a, T> {
2003    vec: VecMut<'a, T>,
2004}
2005
2006impl<'data, T> IntoIterator for VecMut<'data, T> {
2007    type Item = &'data mut T;
2008    type IntoIter = IterVecMut<'data, T>;
2009
2010    fn into_iter(self) -> Self::IntoIter {
2011        self.iter()
2012    }
2013}
2014
2015// FIXME: if budget allows it we should implement common inner-iteration methods such as
2016// `for_each`, `collect`, `all` by doing pointer arithmetic on a range iterator which avoids all
2017// writes to the value's tracking state itself.
2018impl<'data, T> Iterator for IterVecMut<'data, T> {
2019    type Item = &'data mut T;
2020
2021    fn next(&mut self) -> Option<Self::Item> {
2022        let base = self.vec.split_off(..1)?;
2023        Some(unsafe { &mut *base.data.as_ptr() })
2024    }
2025
2026    fn size_hint(&self) -> (usize, Option<usize>) {
2027        let remain = self.vec.len();
2028        (remain, Some(remain))
2029    }
2030
2031    fn count(self) -> usize {
2032        self.vec.len()
2033    }
2034}
2035
2036impl<'data, T> core::iter::FusedIterator for IterVecMut<'data, T> {}
2037
2038/// Tests should also be ran under MIRI.
2039#[cfg(test)]
2040mod tests {
2041    // Verify that splitting as in the example works.
2042    #[test]
2043    fn well_defined_split() {
2044        let data = &[[0u32; 3]; 3];
2045        let block = super::from_array_rows(data);
2046        let (_, block) = block.split_at_row(1);
2047        let (_, block) = block.split_at_col(1);
2048
2049        block.split_at_row_checked(2).unwrap();
2050    }
2051    #[test]
2052    fn well_defined_split_mut() {
2053        let data = &mut [[0u32; 3]; 3];
2054        let block = super::from_array_rows_mut(data);
2055        let (_, block) = block.split_at_row(1);
2056        let (_, block) = block.split_at_col(1);
2057
2058        block.split_at_row_checked(2).unwrap();
2059    }
2060
2061    /// Check our pointer derivation does not cause retagging that would cause any block to lose
2062    /// provenance over its items. Access individual rows (derived slices) from an overlapping split
2063    /// concurrently.
2064    #[test]
2065    fn soundness_interleaved_block_access() {
2066        let data = &mut [[0u32; 4]; 4];
2067        let block = super::from_array_rows_mut(data);
2068
2069        let (mut lhs, rhs) = block.split_at_col(2);
2070
2071        for (left, right) in lhs.reborrow().iter_rows_mut().zip(rhs.iter_rows_mut()) {
2072            left[0] = right[0];
2073            left[1] = right[1];
2074            right.fill(1);
2075        }
2076
2077        // Check that this pointer is still valid.
2078        for row in lhs.iter_rows_mut() {
2079            row.fill(2);
2080        }
2081
2082        for row in data.iter() {
2083            assert_eq!(row, &[2, 2, 1, 1]);
2084        }
2085    }
2086}