ndarray/impl_views/
indexing.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 crate::arraytraits::array_out_of_bounds;
10use crate::imp_prelude::*;
11use crate::NdIndex;
12
13/// Extra indexing methods for array views
14///
15/// These methods are very similar to regular indexing or calling of the
16/// `get`/`get_mut` methods that we can use on any array or array view. The
17/// difference here is in the length of lifetime in the resulting reference.
18///
19/// **Note** that the `ArrayView` (read-only) and `ArrayViewMut` (read-write) differ
20/// in how they are allowed implement this trait -- `ArrayView`'s implementation
21/// is usual. If you put in a `ArrayView<'a, T, D>` here, you get references
22/// `&'a T` out.
23///
24/// For `ArrayViewMut` to obey the borrowing rules we have to consume the
25/// view if we call any of these methods. (The equivalent of reborrow is
26/// `.view_mut()` for read-write array views, but if you can use that,
27/// then the regular indexing / `get_mut` should suffice, too.)
28///
29/// ```
30/// use ndarray::IndexLonger;
31/// use ndarray::ArrayView;
32///
33/// let data = [0.; 256];
34/// let long_life_ref = {
35///     // make a 16 × 16 array view
36///     let view = ArrayView::from(&data[..]).into_shape_with_order((16, 16)).unwrap();
37///
38///     // index the view and with `IndexLonger`.
39///     // Note here that we get a reference with a life that is derived from
40///     // `data`, the base data, instead of being derived from the view
41///     IndexLonger::index(&view, [0, 1])
42/// };
43///
44/// // view goes out of scope
45///
46/// assert_eq!(long_life_ref, &0.);
47///
48/// ```
49pub trait IndexLonger<I>
50{
51    /// The type of the reference to the element that is produced, including
52    /// its lifetime.
53    type Output;
54    /// Get a reference of a element through the view.
55    ///
56    /// This method is like `Index::index` but with a longer lifetime (matching
57    /// the array view); which we can only do for the array view and not in the
58    /// `Index` trait.
59    ///
60    /// See also [the `get` method][1] which works for all arrays and array
61    /// views.
62    ///
63    /// [1]: ArrayBase::get
64    ///
65    /// **Panics** if index is out of bounds.
66    #[track_caller]
67    fn index(self, index: I) -> Self::Output;
68
69    /// Get a reference of a element through the view.
70    ///
71    /// This method is like `ArrayBase::get` but with a longer lifetime (matching
72    /// the array view); which we can only do for the array view and not in the
73    /// `Index` trait.
74    ///
75    /// See also [the `get` method][1] (and [`get_mut`][2]) which works for all arrays and array
76    /// views.
77    ///
78    /// [1]: ArrayBase::get
79    /// [2]: ArrayBase::get_mut
80    ///
81    /// **Panics** if index is out of bounds.
82    #[track_caller]
83    fn get(self, index: I) -> Option<Self::Output>;
84
85    /// Get a reference of a element through the view without boundary check
86    ///
87    /// This method is like `elem` with a longer lifetime (matching the array
88    /// view); which we can't do for general arrays.
89    ///
90    /// See also [the `uget` method][1] which works for all arrays and array
91    /// views.
92    ///
93    /// [1]: ArrayBase::uget
94    ///
95    /// **Note:** only unchecked for non-debug builds of ndarray.
96    ///
97    /// # Safety
98    ///
99    /// The caller must ensure that the index is in-bounds.
100    unsafe fn uget(self, index: I) -> Self::Output;
101}
102
103impl<'a, 'b, I, A, D> IndexLonger<I> for &'b ArrayView<'a, A, D>
104where
105    I: NdIndex<D>,
106    D: Dimension,
107{
108    type Output = &'a A;
109
110    /// Get a reference of a element through the view.
111    ///
112    /// This method is like `Index::index` but with a longer lifetime (matching
113    /// the array view); which we can only do for the array view and not in the
114    /// `Index` trait.
115    ///
116    /// See also [the `get` method][1] which works for all arrays and array
117    /// views.
118    ///
119    /// [1]: ArrayBase::get
120    ///
121    /// **Panics** if index is out of bounds.
122    #[track_caller]
123    fn index(self, index: I) -> &'a A
124    {
125        debug_bounds_check!(self, index);
126        unsafe { &*self.get_ptr(index).unwrap_or_else(|| array_out_of_bounds()) }
127    }
128
129    fn get(self, index: I) -> Option<&'a A>
130    {
131        unsafe { self.get_ptr(index).map(|ptr| &*ptr) }
132    }
133
134    /// Get a reference of a element through the view without boundary check
135    ///
136    /// This method is like `elem` with a longer lifetime (matching the array
137    /// view); which we can't do for general arrays.
138    ///
139    /// See also [the `uget` method][1] which works for all arrays and array
140    /// views.
141    ///
142    /// [1]: ArrayBase::uget
143    ///
144    /// **Note:** only unchecked for non-debug builds of ndarray.
145    unsafe fn uget(self, index: I) -> &'a A
146    {
147        debug_bounds_check!(self, index);
148        &*self.as_ptr().offset(index.index_unchecked(&self.strides))
149    }
150}
151
152impl<'a, I, A, D> IndexLonger<I> for ArrayViewMut<'a, A, D>
153where
154    I: NdIndex<D>,
155    D: Dimension,
156{
157    type Output = &'a mut A;
158
159    /// Convert a mutable array view to a mutable reference of a element.
160    ///
161    /// This method is like `IndexMut::index_mut` but with a longer lifetime
162    /// (matching the array view); which we can only do for the array view and
163    /// not in the `Index` trait.
164    ///
165    /// See also [the `get_mut` method][1] which works for all arrays and array
166    /// views.
167    ///
168    /// [1]: ArrayBase::get_mut
169    ///
170    /// **Panics** if index is out of bounds.
171    #[track_caller]
172    fn index(mut self, index: I) -> &'a mut A
173    {
174        debug_bounds_check!(self, index);
175        unsafe {
176            match self.get_mut_ptr(index) {
177                Some(ptr) => &mut *ptr,
178                None => array_out_of_bounds(),
179            }
180        }
181    }
182
183    /// Convert a mutable array view to a mutable reference of a element, with
184    /// checked access.
185    ///
186    /// See also [the `get_mut` method][1] which works for all arrays and array
187    /// views.
188    ///
189    /// [1]: ArrayBase::get_mut
190    ///
191    fn get(mut self, index: I) -> Option<&'a mut A>
192    {
193        debug_bounds_check!(self, index);
194        unsafe {
195            match self.get_mut_ptr(index) {
196                Some(ptr) => Some(&mut *ptr),
197                None => None,
198            }
199        }
200    }
201
202    /// Convert a mutable array view to a mutable reference of a element without
203    /// boundary check.
204    ///
205    /// See also [the `uget_mut` method][1] which works for all arrays and array
206    /// views.
207    ///
208    /// [1]: ArrayBase::uget_mut
209    ///
210    /// **Note:** only unchecked for non-debug builds of ndarray.
211    unsafe fn uget(mut self, index: I) -> &'a mut A
212    {
213        debug_bounds_check!(self, index);
214        &mut *self
215            .as_mut_ptr()
216            .offset(index.index_unchecked(&self.strides))
217    }
218}
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