ndarray/impl_views/conversions.rs
1// Copyright 2014-2016 bluss and ndarray developers.
2//
3// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
6// option. This file may not be copied, modified, or distributed
7// except according to those terms.
8
9use alloc::slice;
10#[allow(unused_imports)]
11use rawpointer::PointerExt;
12use std::mem::MaybeUninit;
13
14use crate::imp_prelude::*;
15
16use crate::{Baseiter, ElementsBase, ElementsBaseMut};
17
18use crate::dimension::offset_from_low_addr_ptr_to_logical_ptr;
19use crate::iter::{self, AxisIter, AxisIterMut};
20use crate::math_cell::MathCell;
21use crate::IndexLonger;
22
23/// Methods for read-only array views.
24impl<'a, A, D> ArrayView<'a, A, D>
25where D: Dimension
26{
27 /// Convert the view into an `ArrayView<'b, A, D>` where `'b` is a lifetime
28 /// outlived by `'a'`.
29 pub fn reborrow<'b>(self) -> ArrayView<'b, A, D>
30 where 'a: 'b
31 {
32 unsafe { ArrayView::new(self.parts.ptr, self.parts.dim, self.parts.strides) }
33 }
34
35 /// Return the array’s data as a slice, if it is contiguous and in standard order.
36 /// Return `None` otherwise.
37 ///
38 /// Note that while the method is similar to [`ArrayRef::as_slice()`], this method transfers
39 /// the view's lifetime to the slice, so it is a bit more powerful.
40 pub fn to_slice(&self) -> Option<&'a [A]>
41 {
42 if self.is_standard_layout() {
43 unsafe { Some(slice::from_raw_parts(self.parts.ptr.as_ptr(), self.len())) }
44 } else {
45 None
46 }
47 }
48
49 /// Return the array’s data as a slice, if it is contiguous.
50 /// Return `None` otherwise.
51 ///
52 /// Note that while the method is similar to
53 /// [`ArrayRef::as_slice_memory_order()`], this method transfers the view's
54 /// lifetime to the slice, so it is a bit more powerful.
55 pub fn to_slice_memory_order(&self) -> Option<&'a [A]>
56 {
57 if self.is_contiguous() {
58 let offset = offset_from_low_addr_ptr_to_logical_ptr(&self.parts.dim, &self.parts.strides);
59 unsafe { Some(slice::from_raw_parts(self.parts.ptr.sub(offset).as_ptr(), self.len())) }
60 } else {
61 None
62 }
63 }
64
65 /// Converts to a raw array view.
66 #[inline]
67 pub(crate) fn into_raw_view(self) -> RawArrayView<A, D>
68 {
69 unsafe { RawArrayView::new(self.parts.ptr, self.parts.dim, self.parts.strides) }
70 }
71}
72
73/// Methods specific to `ArrayView0`.
74///
75/// ***See also all methods for [`ArrayView`] and [`ArrayBase`]***
76impl<'a, A> ArrayView<'a, A, Ix0>
77{
78 /// Consume the view and return a reference to the single element in the array.
79 ///
80 /// The lifetime of the returned reference matches the lifetime of the data
81 /// the array view was pointing to.
82 ///
83 /// ```
84 /// use ndarray::{arr0, Array0};
85 ///
86 /// // `Foo` doesn't implement `Clone`.
87 /// #[derive(Debug, Eq, PartialEq)]
88 /// struct Foo;
89 ///
90 /// let array: Array0<Foo> = arr0(Foo);
91 /// let view = array.view();
92 /// let scalar: &Foo = view.into_scalar();
93 /// assert_eq!(scalar, &Foo);
94 /// ```
95 pub fn into_scalar(self) -> &'a A
96 {
97 self.index(Ix0())
98 }
99}
100
101/// Methods specific to `ArrayViewMut0`.
102///
103/// ***See also all methods for [`ArrayViewMut`] and [`ArrayBase`]***
104impl<'a, A> ArrayViewMut<'a, A, Ix0>
105{
106 /// Consume the mutable view and return a mutable reference to the single element in the array.
107 ///
108 /// The lifetime of the returned reference matches the lifetime of the data
109 /// the array view was pointing to.
110 ///
111 /// ```
112 /// use ndarray::{arr0, Array0};
113 ///
114 /// let mut array: Array0<f64> = arr0(5.);
115 /// let view = array.view_mut();
116 /// let scalar = view.into_scalar();
117 /// *scalar = 7.;
118 /// assert_eq!(scalar, &7.);
119 /// assert_eq!(array[()], 7.);
120 /// ```
121 pub fn into_scalar(self) -> &'a mut A
122 {
123 self.index(Ix0())
124 }
125}
126
127/// Methods for read-write array views.
128impl<'a, A, D> ArrayViewMut<'a, A, D>
129where D: Dimension
130{
131 /// Return the array’s data as a slice, if it is contiguous and in standard order.
132 /// Return `None` otherwise.
133 ///
134 /// Note that while this is similar to [`ArrayBase::as_slice_mut()`], this method transfers the
135 /// view's lifetime to the slice.
136 pub fn into_slice(self) -> Option<&'a mut [A]>
137 {
138 self.try_into_slice().ok()
139 }
140
141 /// Return the array’s data as a slice, if it is contiguous.
142 /// Return `None` otherwise.
143 ///
144 /// Note that while this is similar to
145 /// [`ArrayBase::as_slice_memory_order_mut()`], this method transfers the
146 /// view's lifetime to the slice.
147 pub fn into_slice_memory_order(self) -> Option<&'a mut [A]>
148 {
149 self.try_into_slice_memory_order().ok()
150 }
151
152 /// Return a shared view of the array with elements as if they were embedded in cells.
153 ///
154 /// The cell view itself can be copied and accessed without exclusivity.
155 ///
156 /// The view acts "as if" the elements are temporarily in cells, and elements
157 /// can be changed through shared references using the regular cell methods.
158 pub fn into_cell_view(self) -> ArrayView<'a, MathCell<A>, D>
159 {
160 // safety: valid because
161 // A and MathCell<A> have the same representation
162 // &'a mut T is interchangeable with &'a Cell<T> -- see method Cell::from_mut in std
163 unsafe {
164 self.into_raw_view_mut()
165 .cast::<MathCell<A>>()
166 .deref_into_view()
167 }
168 }
169
170 /// Return the array view as a view of `MaybeUninit<A>` elements
171 ///
172 /// This conversion leaves the elements as they were (presumably initialized), but
173 /// they are represented with the `MaybeUninit<A>` type. Effectively this means that
174 /// the elements can be overwritten without dropping the old element in its place.
175 /// (In some situations this is not what you want, while for `Copy` elements it makes
176 /// no difference at all.)
177 ///
178 /// # Safety
179 ///
180 /// This method allows writing uninitialized data into the view, which could leave any
181 /// original array that we borrow from in an inconsistent state. This is not allowed
182 /// when using the resulting array view.
183 pub(crate) unsafe fn into_maybe_uninit(self) -> ArrayViewMut<'a, MaybeUninit<A>, D>
184 {
185 // Safe because: A and MaybeUninit<A> have the same representation;
186 // and we can go from initialized to (maybe) not unconditionally in terms of
187 // representation. However, the user must be careful to not write uninit elements
188 // through the view.
189 self.into_raw_view_mut()
190 .cast::<MaybeUninit<A>>()
191 .deref_into_view_mut()
192 }
193}
194
195/// Private raw array view methods
196impl<A, D> RawArrayView<A, D>
197where D: Dimension
198{
199 #[inline]
200 pub(crate) fn into_base_iter(self) -> Baseiter<A, D>
201 {
202 unsafe { Baseiter::new(self.parts.ptr, self.parts.dim, self.parts.strides) }
203 }
204}
205
206impl<A, D> RawArrayViewMut<A, D>
207where D: Dimension
208{
209 #[inline]
210 pub(crate) fn into_base_iter(self) -> Baseiter<A, D>
211 {
212 unsafe { Baseiter::new(self.parts.ptr, self.parts.dim, self.parts.strides) }
213 }
214}
215
216/// Methods for iterating over array views.
217impl<'a, A, D> ArrayView<'a, A, D>
218where D: Dimension
219{
220 #[inline]
221 pub(crate) fn into_base_iter(self) -> Baseiter<A, D>
222 {
223 unsafe { Baseiter::new(self.parts.ptr, self.parts.dim, self.parts.strides) }
224 }
225
226 #[inline]
227 pub(crate) fn into_elements_base(self) -> ElementsBase<'a, A, D>
228 {
229 ElementsBase::new(self)
230 }
231
232 /// Convert into an outer iterator for this view.
233 ///
234 /// Unlike [ArrayRef::outer_iter], this methods preserves the lifetime of the data,
235 /// not the view itself.
236 pub fn into_outer_iter(self) -> iter::AxisIter<'a, A, D::Smaller>
237 where D: RemoveAxis
238 {
239 AxisIter::new(self, Axis(0))
240 }
241
242 /// Convert into an indexed iterator.
243 ///
244 /// Unlike [ArrayRef::indexed_iter], this methods preserves the lifetime of the data,
245 /// not the view itself.
246 pub fn into_indexed_iter(self) -> iter::IndexedIter<'a, A, D>
247 {
248 iter::IndexedIter::new(self.into_elements_base())
249 }
250
251 /// Convert into an iterator over an `axis`.
252 ///
253 /// Unlike [ArrayRef::axis_iter], this methods preserves the lifetime of the data,
254 /// not the view itself.
255 pub fn into_axis_iter(self, axis: Axis) -> iter::AxisIter<'a, A, D::Smaller>
256 where D: RemoveAxis
257 {
258 AxisIter::new(self, axis)
259 }
260
261 /// Convert into an iterator over an `axis` by chunks.
262 ///
263 /// Unlike [`ArrayRef::axis_chunks_iter`], this methods preserves the lifetime of the data,
264 /// not the view itself.
265 pub fn into_axis_chunks_iter(self, axis: Axis, chunk_size: usize) -> iter::AxisChunksIter<'a, A, D>
266 where D: RemoveAxis
267 {
268 iter::AxisChunksIter::new(self, axis, chunk_size)
269 }
270}
271
272/// Methods for iterating over mutable array views.
273impl<'a, A, D> ArrayViewMut<'a, A, D>
274where D: Dimension
275{
276 // Convert into a read-only view
277 pub(crate) fn into_view(self) -> ArrayView<'a, A, D>
278 {
279 unsafe { ArrayView::new(self.parts.ptr, self.parts.dim, self.parts.strides) }
280 }
281
282 /// Converts to a mutable raw array view.
283 pub(crate) fn into_raw_view_mut(self) -> RawArrayViewMut<A, D>
284 {
285 unsafe { RawArrayViewMut::new(self.parts.ptr, self.parts.dim, self.parts.strides) }
286 }
287
288 #[inline]
289 pub(crate) fn into_base_iter(self) -> Baseiter<A, D>
290 {
291 unsafe { Baseiter::new(self.parts.ptr, self.parts.dim, self.parts.strides) }
292 }
293
294 #[inline]
295 pub(crate) fn into_elements_base(self) -> ElementsBaseMut<'a, A, D>
296 {
297 ElementsBaseMut::new(self)
298 }
299
300 /// Return the array’s data as a slice, if it is contiguous and in standard order.
301 /// Otherwise return self in the Err branch of the result.
302 pub(crate) fn try_into_slice(self) -> Result<&'a mut [A], Self>
303 {
304 if self.is_standard_layout() {
305 unsafe { Ok(slice::from_raw_parts_mut(self.parts.ptr.as_ptr(), self.len())) }
306 } else {
307 Err(self)
308 }
309 }
310
311 /// Return the array’s data as a slice, if it is contiguous.
312 /// Otherwise return self in the Err branch of the result.
313 fn try_into_slice_memory_order(self) -> Result<&'a mut [A], Self>
314 {
315 if self.is_contiguous() {
316 let offset = offset_from_low_addr_ptr_to_logical_ptr(&self.parts.dim, &self.parts.strides);
317 unsafe { Ok(slice::from_raw_parts_mut(self.parts.ptr.sub(offset).as_ptr(), self.len())) }
318 } else {
319 Err(self)
320 }
321 }
322
323 /// Convert into an outer iterator for this view.
324 ///
325 /// Unlike [ArrayRef::outer_iter], this methods preserves the lifetime of the data,
326 /// not the view itself.
327 pub fn into_outer_iter(self) -> iter::AxisIter<'a, A, D::Smaller>
328 where D: RemoveAxis
329 {
330 AxisIter::new(self.into_view(), Axis(0))
331 }
332
333 /// Convert into an indexed iterator.
334 ///
335 /// Unlike [ArrayRef::indexed_iter], this methods preserves the lifetime of the data,
336 /// not the view itself.
337 pub fn into_indexed_iter(self) -> iter::IndexedIter<'a, A, D>
338 {
339 iter::IndexedIter::new(self.into_view().into_elements_base())
340 }
341
342 /// Convert into an iterator over an `axis`.
343 ///
344 /// Unlike [ArrayRef::axis_iter], this methods preserves the lifetime of the data,
345 /// not the view itself.
346 pub fn into_axis_iter(self, axis: Axis) -> iter::AxisIter<'a, A, D::Smaller>
347 where D: RemoveAxis
348 {
349 AxisIter::new(self.into_view(), axis)
350 }
351
352 /// Convert into an iterator over an `axis` by chunks.
353 ///
354 /// Unlike [`ArrayRef::axis_chunks_iter`], this methods preserves the lifetime of the data,
355 /// not the view itself.
356 pub fn into_axis_chunks_iter(self, axis: Axis, chunk_size: usize) -> iter::AxisChunksIter<'a, A, D>
357 where D: RemoveAxis
358 {
359 iter::AxisChunksIter::new(self.into_view(), axis, chunk_size)
360 }
361
362 /// Convert into an outer iterator for this view.
363 ///
364 /// Unlike [ArrayRef::outer_iter_mut], this methods preserves the lifetime of the data,
365 /// not the view itself.
366 pub fn into_outer_iter_mut(self) -> iter::AxisIterMut<'a, A, D::Smaller>
367 where D: RemoveAxis
368 {
369 AxisIterMut::new(self, Axis(0))
370 }
371
372 /// Convert into an indexed iterator.
373 ///
374 /// Unlike [ArrayRef::indexed_iter_mut], this methods preserves the lifetime of the data,
375 /// not the view itself.
376 pub fn into_indexed_iter_mut(self) -> iter::IndexedIterMut<'a, A, D>
377 {
378 iter::IndexedIterMut::new(self.into_elements_base())
379 }
380
381 /// Convert into an iterator over an `axis`.
382 ///
383 /// Unlike [ArrayRef::axis_iter_mut], this methods preserves the lifetime of the data,
384 /// not the view itself.
385 pub fn into_axis_iter_mut(self, axis: Axis) -> iter::AxisIterMut<'a, A, D::Smaller>
386 where D: RemoveAxis
387 {
388 AxisIterMut::new(self, axis)
389 }
390
391 /// Convert into an iterator over an `axis` by chunks.
392 ///
393 /// Unlike [`ArrayRef::axis_chunks_iter_mut`], this methods preserves the lifetime of the data,
394 /// not the view itself.
395 pub fn into_axis_chunks_iter_mut(self, axis: Axis, chunk_size: usize) -> iter::AxisChunksIterMut<'a, A, D>
396 where D: RemoveAxis
397 {
398 iter::AxisChunksIterMut::new(self, axis, chunk_size)
399 }
400}