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}