ndarray/impl_views/
constructors.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 std::ptr::NonNull;
10
11use crate::dimension::offset_from_low_addr_ptr_to_logical_ptr;
12use crate::dimension::{self, CanIndexCheckMode};
13use crate::error::ShapeError;
14use crate::extension::nonnull::nonnull_debug_checked_from_ptr;
15use crate::imp_prelude::*;
16use crate::{is_aligned, StrideShape};
17
18/// Methods for read-only array views.
19impl<'a, A, D> ArrayView<'a, A, D>
20where D: Dimension
21{
22    /// Create a read-only array view borrowing its data from a slice.
23    ///
24    /// Checks whether `shape` are compatible with the slice's
25    /// length, returning an `Err` if not compatible.
26    ///
27    /// ```
28    /// use ndarray::ArrayView;
29    /// use ndarray::arr3;
30    /// use ndarray::ShapeBuilder;
31    ///
32    /// // advanced example where we are even specifying exact strides to use (which is optional).
33    /// let s = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12];
34    /// let a = ArrayView::from_shape((2, 3, 2).strides((1, 4, 2)),
35    ///                               &s).unwrap();
36    ///
37    /// assert!(
38    ///     a == arr3(&[[[0, 2],
39    ///                  [4, 6],
40    ///                  [8, 10]],
41    ///                 [[1, 3],
42    ///                  [5, 7],
43    ///                  [9, 11]]])
44    /// );
45    /// assert!(a.strides() == &[1, 4, 2]);
46    /// ```
47    pub fn from_shape<Sh>(shape: Sh, xs: &'a [A]) -> Result<Self, ShapeError>
48    where Sh: Into<StrideShape<D>>
49    {
50        // eliminate the type parameter Sh as soon as possible
51        Self::from_shape_impl(shape.into(), xs)
52    }
53
54    fn from_shape_impl(shape: StrideShape<D>, xs: &'a [A]) -> Result<Self, ShapeError>
55    {
56        let dim = shape.dim;
57        dimension::can_index_slice_with_strides(xs, &dim, &shape.strides, CanIndexCheckMode::ReadOnly)?;
58        let strides = shape.strides.strides_for_dim(&dim);
59        unsafe {
60            Ok(Self::new_(
61                xs.as_ptr()
62                    .add(offset_from_low_addr_ptr_to_logical_ptr(&dim, &strides)),
63                dim,
64                strides,
65            ))
66        }
67    }
68
69    /// Create an `ArrayView<A, D>` from shape information and a raw pointer to
70    /// the elements.
71    ///
72    /// # Safety
73    ///
74    /// The caller is responsible for ensuring all of the following:
75    ///
76    /// * The elements seen by moving `ptr` according to the shape and strides
77    ///   must live at least as long as `'a` and must not be not mutably
78    ///   aliased for the duration of `'a`.
79    ///
80    /// * `ptr` must be non-null and aligned, and it must be safe to
81    ///   [`.offset()`] `ptr` by zero.
82    ///
83    /// * It must be safe to [`.offset()`] the pointer repeatedly along all
84    ///   axes and calculate the `count`s for the `.offset()` calls without
85    ///   overflow, even if the array is empty or the elements are zero-sized.
86    ///
87    ///   In other words,
88    ///
89    ///   * All possible pointers generated by moving along all axes must be in
90    ///     bounds or one byte past the end of a single allocation with element
91    ///     type `A`. The only exceptions are if the array is empty or the element
92    ///     type is zero-sized. In these cases, `ptr` may be dangling, but it must
93    ///     still be safe to [`.offset()`] the pointer along the axes.
94    ///
95    ///   * The offset in units of bytes between the least address and greatest
96    ///     address by moving along all axes must not exceed `isize::MAX`. This
97    ///     constraint prevents the computed offset, in bytes, from overflowing
98    ///     `isize` regardless of the starting point due to past offsets.
99    ///
100    ///   * The offset in units of `A` between the least address and greatest
101    ///     address by moving along all axes must not exceed `isize::MAX`. This
102    ///     constraint prevents overflow when calculating the `count` parameter to
103    ///     [`.offset()`] regardless of the starting point due to past offsets.
104    ///
105    /// * The product of non-zero axis lengths must not exceed `isize::MAX`.
106    ///
107    /// * Strides must be non-negative.
108    ///
109    /// This function can use debug assertions to check some of these requirements,
110    /// but it's not a complete check.
111    ///
112    /// [`.offset()`]: https://doc.rust-lang.org/stable/std/primitive.pointer.html#method.offset
113    #[inline]
114    pub unsafe fn from_shape_ptr<Sh>(shape: Sh, ptr: *const A) -> Self
115    where Sh: Into<StrideShape<D>>
116    {
117        RawArrayView::from_shape_ptr(shape, ptr).deref_into_view()
118    }
119}
120
121/// Methods for read-write array views.
122impl<'a, A, D> ArrayViewMut<'a, A, D>
123where D: Dimension
124{
125    /// Create a read-write array view borrowing its data from a slice.
126    ///
127    /// Checks whether `dim` and `strides` are compatible with the slice's
128    /// length, returning an `Err` if not compatible.
129    ///
130    /// ```
131    /// use ndarray::ArrayViewMut;
132    /// use ndarray::arr3;
133    /// use ndarray::ShapeBuilder;
134    ///
135    /// let mut s = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12];
136    /// let mut a = ArrayViewMut::from_shape((2, 3, 2).strides((1, 4, 2)),
137    ///                                      &mut s).unwrap();
138    ///
139    /// a[[0, 0, 0]] = 1;
140    /// assert!(
141    ///     a == arr3(&[[[1, 2],
142    ///                  [4, 6],
143    ///                  [8, 10]],
144    ///                 [[1, 3],
145    ///                  [5, 7],
146    ///                  [9, 11]]])
147    /// );
148    /// assert!(a.strides() == &[1, 4, 2]);
149    /// ```
150    pub fn from_shape<Sh>(shape: Sh, xs: &'a mut [A]) -> Result<Self, ShapeError>
151    where Sh: Into<StrideShape<D>>
152    {
153        // eliminate the type parameter Sh as soon as possible
154        Self::from_shape_impl(shape.into(), xs)
155    }
156
157    fn from_shape_impl(shape: StrideShape<D>, xs: &'a mut [A]) -> Result<Self, ShapeError>
158    {
159        let dim = shape.dim;
160        dimension::can_index_slice_with_strides(xs, &dim, &shape.strides, CanIndexCheckMode::OwnedMutable)?;
161        let strides = shape.strides.strides_for_dim(&dim);
162        unsafe {
163            Ok(Self::new_(
164                xs.as_mut_ptr()
165                    .add(offset_from_low_addr_ptr_to_logical_ptr(&dim, &strides)),
166                dim,
167                strides,
168            ))
169        }
170    }
171
172    /// Create an `ArrayViewMut<A, D>` from shape information and a
173    /// raw pointer to the elements.
174    ///
175    /// # Safety
176    ///
177    /// The caller is responsible for ensuring all of the following:
178    ///
179    /// * The elements seen by moving `ptr` according to the shape and strides
180    ///   must live at least as long as `'a` and must not be aliased for the
181    ///   duration of `'a`.
182    ///
183    /// * `ptr` must be non-null and aligned, and it must be safe to
184    ///   [`.offset()`] `ptr` by zero.
185    ///
186    /// * It must be safe to [`.offset()`] the pointer repeatedly along all
187    ///   axes and calculate the `count`s for the `.offset()` calls without
188    ///   overflow, even if the array is empty or the elements are zero-sized.
189    ///
190    ///   In other words,
191    ///
192    ///   * All possible pointers generated by moving along all axes must be in
193    ///     bounds or one byte past the end of a single allocation with element
194    ///     type `A`. The only exceptions are if the array is empty or the element
195    ///     type is zero-sized. In these cases, `ptr` may be dangling, but it must
196    ///     still be safe to [`.offset()`] the pointer along the axes.
197    ///
198    ///   * The offset in units of bytes between the least address and greatest
199    ///     address by moving along all axes must not exceed `isize::MAX`. This
200    ///     constraint prevents the computed offset, in bytes, from overflowing
201    ///     `isize` regardless of the starting point due to past offsets.
202    ///
203    ///   * The offset in units of `A` between the least address and greatest
204    ///     address by moving along all axes must not exceed `isize::MAX`. This
205    ///     constraint prevents overflow when calculating the `count` parameter to
206    ///     [`.offset()`] regardless of the starting point due to past offsets.
207    ///
208    /// * The product of non-zero axis lengths must not exceed `isize::MAX`.
209    ///
210    /// * Strides must be non-negative.
211    ///
212    /// This function can use debug assertions to check some of these requirements,
213    /// but it's not a complete check.
214    ///
215    /// [`.offset()`]: https://doc.rust-lang.org/stable/std/primitive.pointer.html#method.offset
216    #[inline]
217    pub unsafe fn from_shape_ptr<Sh>(shape: Sh, ptr: *mut A) -> Self
218    where Sh: Into<StrideShape<D>>
219    {
220        RawArrayViewMut::from_shape_ptr(shape, ptr).deref_into_view_mut()
221    }
222
223    /// Convert the view into an `ArrayViewMut<'b, A, D>` where `'b` is a lifetime
224    /// outlived by `'a'`.
225    pub fn reborrow<'b>(self) -> ArrayViewMut<'b, A, D>
226    where 'a: 'b
227    {
228        unsafe { ArrayViewMut::new(self.ptr, self.dim, self.strides) }
229    }
230}
231
232/// Private array view methods
233impl<'a, A, D> ArrayView<'a, A, D>
234where D: Dimension
235{
236    /// Create a new `ArrayView`
237    ///
238    /// Unsafe because: `ptr` must be valid for the given dimension and strides.
239    #[inline(always)]
240    pub(crate) unsafe fn new(ptr: NonNull<A>, dim: D, strides: D) -> Self
241    {
242        if cfg!(debug_assertions) {
243            assert!(is_aligned(ptr.as_ptr()), "The pointer must be aligned.");
244            dimension::max_abs_offset_check_overflow::<A, _>(&dim, &strides).unwrap();
245        }
246        ArrayView::from_data_ptr(ViewRepr::new(), ptr).with_strides_dim(strides, dim)
247    }
248
249    /// Unsafe because: `ptr` must be valid for the given dimension and strides.
250    #[inline]
251    pub(crate) unsafe fn new_(ptr: *const A, dim: D, strides: D) -> Self
252    {
253        Self::new(nonnull_debug_checked_from_ptr(ptr as *mut A), dim, strides)
254    }
255}
256
257impl<'a, A, D> ArrayViewMut<'a, A, D>
258where D: Dimension
259{
260    /// Create a new `ArrayView`
261    ///
262    /// Unsafe because: `ptr` must be valid for the given dimension and strides.
263    #[inline(always)]
264    pub(crate) unsafe fn new(ptr: NonNull<A>, dim: D, strides: D) -> Self
265    {
266        if cfg!(debug_assertions) {
267            assert!(is_aligned(ptr.as_ptr()), "The pointer must be aligned.");
268            dimension::max_abs_offset_check_overflow::<A, _>(&dim, &strides).unwrap();
269        }
270        ArrayViewMut::from_data_ptr(ViewRepr::new(), ptr).with_strides_dim(strides, dim)
271    }
272
273    /// Create a new `ArrayView`
274    ///
275    /// Unsafe because: `ptr` must be valid for the given dimension and strides.
276    #[inline(always)]
277    pub(crate) unsafe fn new_(ptr: *mut A, dim: D, strides: D) -> Self
278    {
279        Self::new(nonnull_debug_checked_from_ptr(ptr), dim, strides)
280    }
281}
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy