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