nalgebra/base/
construction_slice.rs

1use crate::base::dimension::{Const, Dim, DimName, Dynamic};
2use crate::base::matrix_slice::{SliceStorage, SliceStorageMut};
3use crate::base::{MatrixSlice, MatrixSliceMutMN, Scalar};
4
5use num_rational::Ratio;
6
7/// # Creating matrix slices from `&[T]`
8impl<'a, T: Scalar, R: Dim, C: Dim, RStride: Dim, CStride: Dim>
9    MatrixSlice<'a, T, R, C, RStride, CStride>
10{
11    /// Creates, without bound-checking, a matrix slice from an array and with dimensions and strides specified by generic types instances.
12    ///
13    /// # Safety
14    /// This method is unsafe because the input data array is not checked to contain enough elements.
15    /// The generic types `R`, `C`, `RStride`, `CStride` can either be type-level integers or integers wrapped with `Dynamic::new()`.
16    #[inline]
17    pub unsafe fn from_slice_with_strides_generic_unchecked(
18        data: &'a [T],
19        start: usize,
20        nrows: R,
21        ncols: C,
22        rstride: RStride,
23        cstride: CStride,
24    ) -> Self {
25        let data = SliceStorage::from_raw_parts(
26            data.as_ptr().add(start),
27            (nrows, ncols),
28            (rstride, cstride),
29        );
30        Self::from_data(data)
31    }
32
33    /// Creates a matrix slice from an array and with dimensions and strides specified by generic types instances.
34    ///
35    /// Panics if the input data array dose not contain enough elements.
36    /// The generic types `R`, `C`, `RStride`, `CStride` can either be type-level integers or integers wrapped with `Dynamic::new()`.
37    #[inline]
38    pub fn from_slice_with_strides_generic(
39        data: &'a [T],
40        nrows: R,
41        ncols: C,
42        rstride: RStride,
43        cstride: CStride,
44    ) -> Self {
45        // NOTE: The assertion implements the following formula, but without subtractions to avoid
46        // underflow panics:
47        //      len >= (ncols - 1) * cstride + (nrows - 1) * rstride + 1
48        assert!(
49            data.len() + cstride.value() + rstride.value()
50                >= ncols.value() * cstride.value() + nrows.value() * rstride.value() + 1,
51            "Matrix slice: input data buffer to small."
52        );
53
54        unsafe {
55            Self::from_slice_with_strides_generic_unchecked(data, 0, nrows, ncols, rstride, cstride)
56        }
57    }
58}
59
60impl<'a, T: Scalar, R: Dim, C: Dim> MatrixSlice<'a, T, R, C> {
61    /// Creates, without bound-checking, a matrix slice from an array and with dimensions specified by generic types instances.
62    ///
63    /// # Safety
64    /// This method is unsafe because the input data array is not checked to contain enough elements.
65    /// The generic types `R` and `C` can either be type-level integers or integers wrapped with `Dynamic::new()`.
66    #[inline]
67    pub unsafe fn from_slice_generic_unchecked(
68        data: &'a [T],
69        start: usize,
70        nrows: R,
71        ncols: C,
72    ) -> Self {
73        Self::from_slice_with_strides_generic_unchecked(
74            data, start, nrows, ncols, Const::<1>, nrows,
75        )
76    }
77
78    /// Creates a matrix slice from an array and with dimensions and strides specified by generic types instances.
79    ///
80    /// Panics if the input data array dose not contain enough elements.
81    /// The generic types `R` and `C` can either be type-level integers or integers wrapped with `Dynamic::new()`.
82    #[inline]
83    pub fn from_slice_generic(data: &'a [T], nrows: R, ncols: C) -> Self {
84        Self::from_slice_with_strides_generic(data, nrows, ncols, Const::<1>, nrows)
85    }
86}
87
88macro_rules! impl_constructors(
89    ($($Dims: ty),*; $(=> $DimIdent: ident: $DimBound: ident),*; $($gargs: expr),*; $($args: ident),*) => {
90        impl<'a, T: Scalar, $($DimIdent: $DimBound),*> MatrixSlice<'a, T, $($Dims),*> {
91            /// Creates a new matrix slice from the given data array.
92            ///
93            /// Panics if `data` does not contain enough elements.
94            #[inline]
95            pub fn from_slice(data: &'a [T], $($args: usize),*) -> Self {
96                Self::from_slice_generic(data, $($gargs),*)
97            }
98
99            /// Creates, without bound checking, a new matrix slice from the given data array.
100            #[inline]
101            pub unsafe fn from_slice_unchecked(data: &'a [T], start: usize, $($args: usize),*) -> Self {
102                Self::from_slice_generic_unchecked(data, start, $($gargs),*)
103            }
104        }
105
106        impl<'a, T: Scalar, $($DimIdent: $DimBound, )*> MatrixSlice<'a, T, $($Dims,)* Dynamic, Dynamic> {
107            /// Creates a new matrix slice with the specified strides from the given data array.
108            ///
109            /// Panics if `data` does not contain enough elements.
110            #[inline]
111            pub fn from_slice_with_strides(data: &'a [T], $($args: usize,)* rstride: usize, cstride: usize) -> Self {
112                Self::from_slice_with_strides_generic(data, $($gargs,)* Dynamic::new(rstride), Dynamic::new(cstride))
113            }
114
115            /// Creates, without bound checking, a new matrix slice with the specified strides from the given data array.
116            #[inline]
117            pub unsafe fn from_slice_with_strides_unchecked(data: &'a [T], start: usize, $($args: usize,)* rstride: usize, cstride: usize) -> Self {
118                Self::from_slice_with_strides_generic_unchecked(data, start, $($gargs,)* Dynamic::new(rstride), Dynamic::new(cstride))
119            }
120        }
121    }
122);
123
124// TODO: this is not very pretty. We could find a better call syntax.
125impl_constructors!(R, C;                         // Arguments for Matrix<T, ..., S>
126=> R: DimName, => C: DimName; // Type parameters for impl<T, ..., S>
127R::name(), C::name();         // Arguments for `_generic` constructors.
128); // Arguments for non-generic constructors.
129
130impl_constructors!(R, Dynamic;
131                   => R: DimName;
132                   R::name(), Dynamic::new(ncols);
133                   ncols);
134
135impl_constructors!(Dynamic, C;
136                   => C: DimName;
137                   Dynamic::new(nrows), C::name();
138                   nrows);
139
140impl_constructors!(Dynamic, Dynamic;
141                   ;
142                   Dynamic::new(nrows), Dynamic::new(ncols);
143                   nrows, ncols);
144
145/// # Creating mutable matrix slices from `&mut [T]`
146impl<'a, T: Scalar, R: Dim, C: Dim, RStride: Dim, CStride: Dim>
147    MatrixSliceMutMN<'a, T, R, C, RStride, CStride>
148{
149    /// Creates, without bound-checking, a mutable matrix slice from an array and with dimensions and strides specified by generic types instances.
150    ///
151    /// # Safety
152    /// This method is unsafe because the input data array is not checked to contain enough elements.
153    /// The generic types `R`, `C`, `RStride`, `CStride` can either be type-level integers or integers wrapped with `Dynamic::new()`.
154    #[inline]
155    pub unsafe fn from_slice_with_strides_generic_unchecked(
156        data: &'a mut [T],
157        start: usize,
158        nrows: R,
159        ncols: C,
160        rstride: RStride,
161        cstride: CStride,
162    ) -> Self {
163        let data = SliceStorageMut::from_raw_parts(
164            data.as_mut_ptr().add(start),
165            (nrows, ncols),
166            (rstride, cstride),
167        );
168        Self::from_data(data)
169    }
170
171    /// Creates a mutable matrix slice from an array and with dimensions and strides specified by generic types instances.
172    ///
173    /// Panics if the input data array dose not contain enough elements.
174    /// The generic types `R`, `C`, `RStride`, `CStride` can either be type-level integers or integers wrapped with `Dynamic::new()`.
175    #[inline]
176    pub fn from_slice_with_strides_generic(
177        data: &'a mut [T],
178        nrows: R,
179        ncols: C,
180        rstride: RStride,
181        cstride: CStride,
182    ) -> Self {
183        // NOTE: The assertion implements the following formula, but without subtractions to avoid
184        // underflow panics:
185        //      len >= (ncols - 1) * cstride + (nrows - 1) * rstride + 1
186        assert!(
187            data.len() + cstride.value() + rstride.value()
188                >= ncols.value() * cstride.value() + nrows.value() * rstride.value() + 1,
189            "Matrix slice: input data buffer to small."
190        );
191
192        assert!(
193            {
194                let nrows = nrows.value();
195                let ncols = ncols.value();
196                let rstride = rstride.value();
197                let cstride = cstride.value();
198
199                nrows * ncols <= 1
200                    || match (rstride, cstride) {
201                        (0, 0) => false,      // otherwise: matrix[(0, 0)] == index[(nrows - 1, ncols - 1)],
202                        (0, _) => nrows <= 1, // otherwise: matrix[(0, 0)] == index[(nrows - 1, 0)],
203                        (_, 0) => ncols <= 1, // otherwise: matrix[(0, 0)] == index[(0, ncols - 1)],
204                        (_, _) => {
205                            // otherwise: matrix[(0, numer)] == index[(denom, 0)]
206                            let ratio = Ratio::new(rstride, cstride);
207                            nrows <= *ratio.denom() || ncols <= *ratio.numer()
208                        }
209                    }
210            },
211            "Matrix slice: dimensions and strides result in aliased indices."
212        );
213
214        unsafe {
215            Self::from_slice_with_strides_generic_unchecked(data, 0, nrows, ncols, rstride, cstride)
216        }
217    }
218}
219
220impl<'a, T: Scalar, R: Dim, C: Dim> MatrixSliceMutMN<'a, T, R, C> {
221    /// Creates, without bound-checking, a mutable matrix slice from an array and with dimensions specified by generic types instances.
222    ///
223    /// # Safety
224    /// This method is unsafe because the input data array is not checked to contain enough elements.
225    /// The generic types `R` and `C` can either be type-level integers or integers wrapped with `Dynamic::new()`.
226    #[inline]
227    pub unsafe fn from_slice_generic_unchecked(
228        data: &'a mut [T],
229        start: usize,
230        nrows: R,
231        ncols: C,
232    ) -> Self {
233        Self::from_slice_with_strides_generic_unchecked(
234            data, start, nrows, ncols, Const::<1>, nrows,
235        )
236    }
237
238    /// Creates a mutable matrix slice from an array and with dimensions and strides specified by generic types instances.
239    ///
240    /// Panics if the input data array dose not contain enough elements.
241    /// The generic types `R` and `C` can either be type-level integers or integers wrapped with `Dynamic::new()`.
242    #[inline]
243    pub fn from_slice_generic(data: &'a mut [T], nrows: R, ncols: C) -> Self {
244        Self::from_slice_with_strides_generic(data, nrows, ncols, Const::<1>, nrows)
245    }
246}
247
248macro_rules! impl_constructors_mut(
249    ($($Dims: ty),*; $(=> $DimIdent: ident: $DimBound: ident),*; $($gargs: expr),*; $($args: ident),*) => {
250        impl<'a, T: Scalar, $($DimIdent: $DimBound),*> MatrixSliceMutMN<'a, T, $($Dims),*> {
251            /// Creates a new mutable matrix slice from the given data array.
252            ///
253            /// Panics if `data` does not contain enough elements.
254            #[inline]
255            pub fn from_slice(data: &'a mut [T], $($args: usize),*) -> Self {
256                Self::from_slice_generic(data, $($gargs),*)
257            }
258
259            /// Creates, without bound checking, a new mutable matrix slice from the given data array.
260            #[inline]
261            pub unsafe fn from_slice_unchecked(data: &'a mut [T], start: usize, $($args: usize),*) -> Self {
262                Self::from_slice_generic_unchecked(data, start, $($gargs),*)
263            }
264        }
265
266        impl<'a, T: Scalar, $($DimIdent: $DimBound, )*> MatrixSliceMutMN<'a, T, $($Dims,)* Dynamic, Dynamic> {
267            /// Creates a new mutable matrix slice with the specified strides from the given data array.
268            ///
269            /// Panics if `data` does not contain enough elements.
270            #[inline]
271            pub fn from_slice_with_strides_mut(data: &'a mut [T], $($args: usize,)* rstride: usize, cstride: usize) -> Self {
272                Self::from_slice_with_strides_generic(
273                    data, $($gargs,)* Dynamic::new(rstride), Dynamic::new(cstride))
274            }
275
276            /// Creates, without bound checking, a new mutable matrix slice with the specified strides from the given data array.
277            #[inline]
278            pub unsafe fn from_slice_with_strides_unchecked(data: &'a mut [T], start: usize, $($args: usize,)* rstride: usize, cstride: usize) -> Self {
279                Self::from_slice_with_strides_generic_unchecked(
280                    data, start, $($gargs,)* Dynamic::new(rstride), Dynamic::new(cstride))
281            }
282        }
283    }
284);
285
286// TODO: this is not very pretty. We could find a better call syntax.
287impl_constructors_mut!(R, C;                         // Arguments for Matrix<T, ..., S>
288=> R: DimName, => C: DimName; // Type parameters for impl<T, ..., S>
289R::name(), C::name();         // Arguments for `_generic` constructors.
290); // Arguments for non-generic constructors.
291
292impl_constructors_mut!(R, Dynamic;
293                       => R: DimName;
294                       R::name(), Dynamic::new(ncols);
295                       ncols);
296
297impl_constructors_mut!(Dynamic, C;
298                       => C: DimName;
299                       Dynamic::new(nrows), C::name();
300                       nrows);
301
302impl_constructors_mut!(Dynamic, Dynamic;
303                       ;
304                       Dynamic::new(nrows), Dynamic::new(ncols);
305                       nrows, ncols);