ndarray/alias_asref.rs
1use crate::{
2 iter::Axes,
3 ArrayBase,
4 Axis,
5 AxisDescription,
6 Dimension,
7 NdIndex,
8 RawArrayView,
9 RawData,
10 RawDataMut,
11 Slice,
12 SliceArg,
13};
14
15/// Functions coming from RawRef
16impl<A, S: RawData<Elem = A>, D: Dimension> ArrayBase<S, D>
17{
18 /// Return a raw pointer to the element at `index`, or return `None`
19 /// if the index is out of bounds.
20 ///
21 /// ```
22 /// use ndarray::arr2;
23 ///
24 /// let a = arr2(&[[1., 2.], [3., 4.]]);
25 ///
26 /// let v = a.raw_view();
27 /// let p = a.get_ptr((0, 1)).unwrap();
28 ///
29 /// assert_eq!(unsafe { *p }, 2.);
30 /// ```
31 pub fn get_ptr<I>(&self, index: I) -> Option<*const A>
32 where I: NdIndex<D>
33 {
34 self.as_raw_ref().get_ptr(index)
35 }
36
37 /// Return a raw pointer to the element at `index`, or return `None`
38 /// if the index is out of bounds.
39 ///
40 /// ```
41 /// use ndarray::arr2;
42 ///
43 /// let mut a = arr2(&[[1., 2.], [3., 4.]]);
44 ///
45 /// let v = a.raw_view_mut();
46 /// let p = a.get_mut_ptr((0, 1)).unwrap();
47 ///
48 /// unsafe {
49 /// *p = 5.;
50 /// }
51 ///
52 /// assert_eq!(a.get((0, 1)), Some(&5.));
53 /// ```
54 pub fn get_mut_ptr<I>(&mut self, index: I) -> Option<*mut A>
55 where
56 S: RawDataMut<Elem = A>,
57 I: NdIndex<D>,
58 {
59 self.as_raw_ref_mut().get_mut_ptr(index)
60 }
61
62 /// Return a pointer to the first element in the array.
63 ///
64 /// Raw access to array elements needs to follow the strided indexing
65 /// scheme: an element at multi-index *I* in an array with strides *S* is
66 /// located at offset
67 ///
68 /// *Σ<sub>0 ≤ k < d</sub> I<sub>k</sub> × S<sub>k</sub>*
69 ///
70 /// where *d* is `self.ndim()`.
71 #[inline(always)]
72 pub fn as_ptr(&self) -> *const A
73 {
74 self.as_raw_ref().as_ptr()
75 }
76
77 /// Return a raw view of the array.
78 #[inline]
79 pub fn raw_view(&self) -> RawArrayView<S::Elem, D>
80 {
81 self.as_raw_ref().raw_view()
82 }
83}
84
85/// Functions coming from LayoutRef
86impl<S: RawData, D: Dimension> ArrayBase<S, D>
87{
88 /// Slice the array in place without changing the number of dimensions.
89 ///
90 /// In particular, if an axis is sliced with an index, the axis is
91 /// collapsed, as in [`.collapse_axis()`], rather than removed, as in
92 /// [`.slice_move()`] or [`.index_axis_move()`].
93 ///
94 /// [`.collapse_axis()`]: Self::collapse_axis
95 /// [`.slice_move()`]: Self::slice_move
96 /// [`.index_axis_move()`]: Self::index_axis_move
97 ///
98 /// See [*Slicing*](#slicing) for full documentation.
99 /// See also [`s!`], [`SliceArg`], and [`SliceInfo`](crate::SliceInfo).
100 ///
101 /// **Panics** in the following cases:
102 ///
103 /// - if an index is out of bounds
104 /// - if a step size is zero
105 /// - if [`NewAxis`](`crate::SliceInfoElem::NewAxis`) is in `info`, e.g. if `NewAxis` was
106 /// used in the [`s!`] macro
107 /// - if `D` is `IxDyn` and `info` does not match the number of array axes
108 #[track_caller]
109 pub fn slice_collapse<I>(&mut self, info: I)
110 where I: SliceArg<D>
111 {
112 self.as_layout_ref_mut().slice_collapse(info);
113 }
114
115 /// Slice the array in place along the specified axis.
116 ///
117 /// **Panics** if an index is out of bounds or step size is zero.<br>
118 /// **Panics** if `axis` is out of bounds.
119 #[track_caller]
120 pub fn slice_axis_inplace(&mut self, axis: Axis, indices: Slice)
121 {
122 self.as_layout_ref_mut().slice_axis_inplace(axis, indices);
123 }
124
125 /// Slice the array in place, with a closure specifying the slice for each
126 /// axis.
127 ///
128 /// This is especially useful for code which is generic over the
129 /// dimensionality of the array.
130 ///
131 /// **Panics** if an index is out of bounds or step size is zero.
132 #[track_caller]
133 pub fn slice_each_axis_inplace<F>(&mut self, f: F)
134 where F: FnMut(AxisDescription) -> Slice
135 {
136 self.as_layout_ref_mut().slice_each_axis_inplace(f);
137 }
138
139 /// Selects `index` along the axis, collapsing the axis into length one.
140 ///
141 /// **Panics** if `axis` or `index` is out of bounds.
142 #[track_caller]
143 pub fn collapse_axis(&mut self, axis: Axis, index: usize)
144 {
145 self.as_layout_ref_mut().collapse_axis(axis, index);
146 }
147
148 /// Return `true` if the array data is laid out in contiguous “C order” in
149 /// memory (where the last index is the most rapidly varying).
150 ///
151 /// Return `false` otherwise, i.e. the array is possibly not
152 /// contiguous in memory, it has custom strides, etc.
153 pub fn is_standard_layout(&self) -> bool
154 {
155 self.as_layout_ref().is_standard_layout()
156 }
157
158 /// Return true if the array is known to be contiguous.
159 pub(crate) fn is_contiguous(&self) -> bool
160 {
161 self.as_layout_ref().is_contiguous()
162 }
163
164 /// Return an iterator over the length and stride of each axis.
165 pub fn axes(&self) -> Axes<'_, D>
166 {
167 self.as_layout_ref().axes()
168 }
169
170 /*
171 /// Return the axis with the least stride (by absolute value)
172 pub fn min_stride_axis(&self) -> Axis {
173 self.dim.min_stride_axis(&self.strides)
174 }
175 */
176
177 /// Return the axis with the greatest stride (by absolute value),
178 /// preferring axes with len > 1.
179 pub fn max_stride_axis(&self) -> Axis
180 {
181 self.as_layout_ref().max_stride_axis()
182 }
183
184 /// Reverse the stride of `axis`.
185 ///
186 /// ***Panics*** if the axis is out of bounds.
187 #[track_caller]
188 pub fn invert_axis(&mut self, axis: Axis)
189 {
190 self.as_layout_ref_mut().invert_axis(axis);
191 }
192
193 /// Swap axes `ax` and `bx`.
194 ///
195 /// This does not move any data, it just adjusts the array’s dimensions
196 /// and strides.
197 ///
198 /// **Panics** if the axes are out of bounds.
199 ///
200 /// ```
201 /// use ndarray::arr2;
202 ///
203 /// let mut a = arr2(&[[1., 2., 3.]]);
204 /// a.swap_axes(0, 1);
205 /// assert!(
206 /// a == arr2(&[[1.], [2.], [3.]])
207 /// );
208 /// ```
209 #[track_caller]
210 pub fn swap_axes(&mut self, ax: usize, bx: usize)
211 {
212 self.as_layout_ref_mut().swap_axes(ax, bx);
213 }
214
215 /// If possible, merge in the axis `take` to `into`.
216 ///
217 /// Returns `true` iff the axes are now merged.
218 ///
219 /// This method merges the axes if movement along the two original axes
220 /// (moving fastest along the `into` axis) can be equivalently represented
221 /// as movement along one (merged) axis. Merging the axes preserves this
222 /// order in the merged axis. If `take` and `into` are the same axis, then
223 /// the axis is "merged" if its length is ≤ 1.
224 ///
225 /// If the return value is `true`, then the following hold:
226 ///
227 /// * The new length of the `into` axis is the product of the original
228 /// lengths of the two axes.
229 ///
230 /// * The new length of the `take` axis is 0 if the product of the original
231 /// lengths of the two axes is 0, and 1 otherwise.
232 ///
233 /// If the return value is `false`, then merging is not possible, and the
234 /// original shape and strides have been preserved.
235 ///
236 /// Note that the ordering constraint means that if it's possible to merge
237 /// `take` into `into`, it's usually not possible to merge `into` into
238 /// `take`, and vice versa.
239 ///
240 /// ```
241 /// use ndarray::Array3;
242 /// use ndarray::Axis;
243 ///
244 /// let mut a = Array3::<f64>::zeros((2, 3, 4));
245 /// assert!(a.merge_axes(Axis(1), Axis(2)));
246 /// assert_eq!(a.shape(), &[2, 1, 12]);
247 /// ```
248 ///
249 /// ***Panics*** if an axis is out of bounds.
250 #[track_caller]
251 pub fn merge_axes(&mut self, take: Axis, into: Axis) -> bool
252 {
253 self.as_layout_ref_mut().merge_axes(take, into)
254 }
255
256 /// Return the total number of elements in the array.
257 pub fn len(&self) -> usize
258 {
259 self.as_layout_ref().len()
260 }
261
262 /// Return the length of `axis`.
263 ///
264 /// The axis should be in the range `Axis(` 0 .. *n* `)` where *n* is the
265 /// number of dimensions (axes) of the array.
266 ///
267 /// ***Panics*** if the axis is out of bounds.
268 #[track_caller]
269 pub fn len_of(&self, axis: Axis) -> usize
270 {
271 self.as_layout_ref().len_of(axis)
272 }
273
274 /// Return whether the array has any elements
275 pub fn is_empty(&self) -> bool
276 {
277 self.as_layout_ref().is_empty()
278 }
279
280 /// Return the number of dimensions (axes) in the array
281 pub fn ndim(&self) -> usize
282 {
283 self.as_layout_ref().ndim()
284 }
285
286 /// Return the shape of the array in its “pattern” form,
287 /// an integer in the one-dimensional case, tuple in the n-dimensional cases
288 /// and so on.
289 pub fn dim(&self) -> D::Pattern
290 {
291 self.as_layout_ref().dim()
292 }
293
294 /// Return the shape of the array as it's stored in the array.
295 ///
296 /// This is primarily useful for passing to other `ArrayBase`
297 /// functions, such as when creating another array of the same
298 /// shape and dimensionality.
299 ///
300 /// ```
301 /// use ndarray::Array;
302 ///
303 /// let a = Array::from_elem((2, 3), 5.);
304 ///
305 /// // Create an array of zeros that's the same shape and dimensionality as `a`.
306 /// let b = Array::<f64, _>::zeros(a.raw_dim());
307 /// ```
308 pub fn raw_dim(&self) -> D
309 {
310 self.as_layout_ref().raw_dim()
311 }
312
313 /// Return the shape of the array as a slice.
314 ///
315 /// Note that you probably don't want to use this to create an array of the
316 /// same shape as another array because creating an array with e.g.
317 /// [`Array::zeros()`](ArrayBase::zeros) using a shape of type `&[usize]`
318 /// results in a dynamic-dimensional array. If you want to create an array
319 /// that has the same shape and dimensionality as another array, use
320 /// [`.raw_dim()`](ArrayBase::raw_dim) instead:
321 ///
322 /// ```rust
323 /// use ndarray::{Array, Array2};
324 ///
325 /// let a = Array2::<i32>::zeros((3, 4));
326 /// let shape = a.shape();
327 /// assert_eq!(shape, &[3, 4]);
328 ///
329 /// // Since `a.shape()` returned `&[usize]`, we get an `ArrayD` instance:
330 /// let b = Array::zeros(shape);
331 /// assert_eq!(a.clone().into_dyn(), b);
332 ///
333 /// // To get the same dimension type, use `.raw_dim()` instead:
334 /// let c = Array::zeros(a.raw_dim());
335 /// assert_eq!(a, c);
336 /// ```
337 pub fn shape(&self) -> &[usize]
338 {
339 self.as_layout_ref().shape()
340 }
341
342 /// Return the strides of the array as a slice.
343 pub fn strides(&self) -> &[isize]
344 {
345 self.as_layout_ref().strides()
346 }
347
348 /// Return the stride of `axis`.
349 ///
350 /// The axis should be in the range `Axis(` 0 .. *n* `)` where *n* is the
351 /// number of dimensions (axes) of the array.
352 ///
353 /// ***Panics*** if the axis is out of bounds.
354 #[track_caller]
355 pub fn stride_of(&self, axis: Axis) -> isize
356 {
357 self.as_layout_ref().stride_of(axis)
358 }
359}