ndarray/
arraytraits.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::hash;
10use std::iter::FromIterator;
11use std::iter::IntoIterator;
12use std::mem;
13use std::ops::{Index, IndexMut};
14use alloc::boxed::Box;
15use alloc::vec::Vec;
16
17use crate::imp_prelude::*;
18use crate::iter::{Iter, IterMut};
19use crate::NdIndex;
20
21use crate::numeric_util;
22use crate::{FoldWhile, Zip};
23
24#[cold]
25#[inline(never)]
26pub(crate) fn array_out_of_bounds() -> ! {
27    panic!("ndarray: index out of bounds");
28}
29
30#[inline(always)]
31pub fn debug_bounds_check<S, D, I>(_a: &ArrayBase<S, D>, _index: &I)
32where
33    D: Dimension,
34    I: NdIndex<D>,
35    S: Data,
36{
37    debug_bounds_check!(_a, *_index);
38}
39
40/// Access the element at **index**.
41///
42/// **Panics** if index is out of bounds.
43impl<S, D, I> Index<I> for ArrayBase<S, D>
44where
45    D: Dimension,
46    I: NdIndex<D>,
47    S: Data,
48{
49    type Output = S::Elem;
50    #[inline]
51    fn index(&self, index: I) -> &S::Elem {
52        debug_bounds_check!(self, index);
53        unsafe {
54            &*self.ptr.as_ptr().offset(
55                index
56                    .index_checked(&self.dim, &self.strides)
57                    .unwrap_or_else(|| array_out_of_bounds()),
58            )
59        }
60    }
61}
62
63/// Access the element at **index** mutably.
64///
65/// **Panics** if index is out of bounds.
66impl<S, D, I> IndexMut<I> for ArrayBase<S, D>
67where
68    D: Dimension,
69    I: NdIndex<D>,
70    S: DataMut,
71{
72    #[inline]
73    fn index_mut(&mut self, index: I) -> &mut S::Elem {
74        debug_bounds_check!(self, index);
75        unsafe {
76            &mut *self.as_mut_ptr().offset(
77                index
78                    .index_checked(&self.dim, &self.strides)
79                    .unwrap_or_else(|| array_out_of_bounds()),
80            )
81        }
82    }
83}
84
85/// Return `true` if the array shapes and all elements of `self` and
86/// `rhs` are equal. Return `false` otherwise.
87impl<A, B, S, S2, D> PartialEq<ArrayBase<S2, D>> for ArrayBase<S, D>
88where
89    A: PartialEq<B>,
90    S: Data<Elem = A>,
91    S2: Data<Elem = B>,
92    D: Dimension,
93{
94    fn eq(&self, rhs: &ArrayBase<S2, D>) -> bool {
95        if self.shape() != rhs.shape() {
96            return false;
97        }
98        if let Some(self_s) = self.as_slice() {
99            if let Some(rhs_s) = rhs.as_slice() {
100                return numeric_util::unrolled_eq(self_s, rhs_s);
101            }
102        }
103        Zip::from(self)
104            .and(rhs)
105            .fold_while(true, |_, a, b| {
106                if a != b {
107                    FoldWhile::Done(false)
108                } else {
109                    FoldWhile::Continue(true)
110                }
111            })
112            .into_inner()
113    }
114}
115
116/// Return `true` if the array shapes and all elements of `self` and
117/// `rhs` are equal. Return `false` otherwise.
118impl<'a, A, B, S, S2, D> PartialEq<&'a ArrayBase<S2, D>> for ArrayBase<S, D>
119where
120    A: PartialEq<B>,
121    S: Data<Elem = A>,
122    S2: Data<Elem = B>,
123    D: Dimension,
124{
125    fn eq(&self, rhs: &&ArrayBase<S2, D>) -> bool {
126        *self == **rhs
127    }
128}
129
130/// Return `true` if the array shapes and all elements of `self` and
131/// `rhs` are equal. Return `false` otherwise.
132impl<'a, A, B, S, S2, D> PartialEq<ArrayBase<S2, D>> for &'a ArrayBase<S, D>
133where
134    A: PartialEq<B>,
135    S: Data<Elem = A>,
136    S2: Data<Elem = B>,
137    D: Dimension,
138{
139    fn eq(&self, rhs: &ArrayBase<S2, D>) -> bool {
140        **self == *rhs
141    }
142}
143
144impl<S, D> Eq for ArrayBase<S, D>
145where
146    D: Dimension,
147    S: Data,
148    S::Elem: Eq,
149{
150}
151
152impl<A, S> From<Box<[A]>> for ArrayBase<S, Ix1>
153where
154    S: DataOwned<Elem = A>,
155{
156    /// Create a one-dimensional array from a boxed slice (no copying needed).
157    ///
158    /// **Panics** if the length is greater than `isize::MAX`.
159    fn from(b: Box<[A]>) -> Self {
160        Self::from_vec(b.into_vec())
161    }
162}
163
164impl<A, S> From<Vec<A>> for ArrayBase<S, Ix1>
165where
166    S: DataOwned<Elem = A>,
167{
168    /// Create a one-dimensional array from a vector (no copying needed).
169    ///
170    /// **Panics** if the length is greater than `isize::MAX`.
171    ///
172    /// ```rust
173    /// use ndarray::Array;
174    ///
175    /// let array = Array::from(vec![1., 2., 3., 4.]);
176    /// ```
177    fn from(v: Vec<A>) -> Self {
178        Self::from_vec(v)
179    }
180}
181
182impl<A, S> FromIterator<A> for ArrayBase<S, Ix1>
183where
184    S: DataOwned<Elem = A>,
185{
186    /// Create a one-dimensional array from an iterable.
187    ///
188    /// **Panics** if the length is greater than `isize::MAX`.
189    ///
190    /// ```rust
191    /// use ndarray::{Array, arr1};
192    ///
193    /// // Either use `from_iter` directly or use `Iterator::collect`.
194    /// let array = Array::from_iter((0..5).map(|x| x * x));
195    /// assert!(array == arr1(&[0, 1, 4, 9, 16]))
196    /// ```
197    fn from_iter<I>(iterable: I) -> ArrayBase<S, Ix1>
198    where
199        I: IntoIterator<Item = A>,
200    {
201        Self::from_iter(iterable)
202    }
203}
204
205impl<'a, S, D> IntoIterator for &'a ArrayBase<S, D>
206where
207    D: Dimension,
208    S: Data,
209{
210    type Item = &'a S::Elem;
211    type IntoIter = Iter<'a, S::Elem, D>;
212
213    fn into_iter(self) -> Self::IntoIter {
214        self.iter()
215    }
216}
217
218impl<'a, S, D> IntoIterator for &'a mut ArrayBase<S, D>
219where
220    D: Dimension,
221    S: DataMut,
222{
223    type Item = &'a mut S::Elem;
224    type IntoIter = IterMut<'a, S::Elem, D>;
225
226    fn into_iter(self) -> Self::IntoIter {
227        self.iter_mut()
228    }
229}
230
231impl<'a, A, D> IntoIterator for ArrayView<'a, A, D>
232where
233    D: Dimension,
234{
235    type Item = &'a A;
236    type IntoIter = Iter<'a, A, D>;
237
238    fn into_iter(self) -> Self::IntoIter {
239        self.into_iter_()
240    }
241}
242
243impl<'a, A, D> IntoIterator for ArrayViewMut<'a, A, D>
244where
245    D: Dimension,
246{
247    type Item = &'a mut A;
248    type IntoIter = IterMut<'a, A, D>;
249
250    fn into_iter(self) -> Self::IntoIter {
251        self.into_iter_()
252    }
253}
254
255impl<S, D> hash::Hash for ArrayBase<S, D>
256where
257    D: Dimension,
258    S: Data,
259    S::Elem: hash::Hash,
260{
261    // Note: elements are hashed in the logical order
262    fn hash<H: hash::Hasher>(&self, state: &mut H) {
263        self.shape().hash(state);
264        if let Some(self_s) = self.as_slice() {
265            hash::Hash::hash_slice(self_s, state);
266        } else {
267            for row in self.rows() {
268                if let Some(row_s) = row.as_slice() {
269                    hash::Hash::hash_slice(row_s, state);
270                } else {
271                    for elt in row {
272                        elt.hash(state)
273                    }
274                }
275            }
276        }
277    }
278}
279
280// NOTE: ArrayBase keeps an internal raw pointer that always
281// points into the storage. This is Sync & Send as long as we
282// follow the usual inherited mutability rules, as we do with
283// Vec, &[] and &mut []
284
285/// `ArrayBase` is `Sync` when the storage type is.
286unsafe impl<S, D> Sync for ArrayBase<S, D>
287where
288    S: Sync + Data,
289    D: Sync,
290{
291}
292
293/// `ArrayBase` is `Send` when the storage type is.
294unsafe impl<S, D> Send for ArrayBase<S, D>
295where
296    S: Send + Data,
297    D: Send,
298{
299}
300
301#[cfg(any(feature = "serde"))]
302// Use version number so we can add a packed format later.
303pub const ARRAY_FORMAT_VERSION: u8 = 1u8;
304
305// use "raw" form instead of type aliases here so that they show up in docs
306/// Implementation of `ArrayView::from(&S)` where `S` is a slice or sliceable.
307impl<'a, A, Slice: ?Sized> From<&'a Slice> for ArrayView<'a, A, Ix1>
308where
309    Slice: AsRef<[A]>,
310{
311    /// Create a one-dimensional read-only array view of the data in `slice`.
312    ///
313    /// **Panics** if the slice length is greater than `isize::MAX`.
314    fn from(slice: &'a Slice) -> Self {
315        let xs = slice.as_ref();
316        if mem::size_of::<A>() == 0 {
317            assert!(
318                xs.len() <= ::std::isize::MAX as usize,
319                "Slice length must fit in `isize`.",
320            );
321        }
322        unsafe { Self::from_shape_ptr(xs.len(), xs.as_ptr()) }
323    }
324}
325
326/// Implementation of `ArrayView::from(&A)` where `A` is an array.
327impl<'a, A, S, D> From<&'a ArrayBase<S, D>> for ArrayView<'a, A, D>
328where
329    S: Data<Elem = A>,
330    D: Dimension,
331{
332    /// Create a read-only array view of the array.
333    fn from(array: &'a ArrayBase<S, D>) -> Self {
334        array.view()
335    }
336}
337
338/// Implementation of `ArrayViewMut::from(&mut S)` where `S` is a slice or sliceable.
339impl<'a, A, Slice: ?Sized> From<&'a mut Slice> for ArrayViewMut<'a, A, Ix1>
340where
341    Slice: AsMut<[A]>,
342{
343    /// Create a one-dimensional read-write array view of the data in `slice`.
344    ///
345    /// **Panics** if the slice length is greater than `isize::MAX`.
346    fn from(slice: &'a mut Slice) -> Self {
347        let xs = slice.as_mut();
348        if mem::size_of::<A>() == 0 {
349            assert!(
350                xs.len() <= ::std::isize::MAX as usize,
351                "Slice length must fit in `isize`.",
352            );
353        }
354        unsafe { Self::from_shape_ptr(xs.len(), xs.as_mut_ptr()) }
355    }
356}
357
358/// Implementation of `ArrayViewMut::from(&mut A)` where `A` is an array.
359impl<'a, A, S, D> From<&'a mut ArrayBase<S, D>> for ArrayViewMut<'a, A, D>
360where
361    S: DataMut<Elem = A>,
362    D: Dimension,
363{
364    /// Create a read-write array view of the array.
365    fn from(array: &'a mut ArrayBase<S, D>) -> Self {
366        array.view_mut()
367    }
368}
369
370impl<A, D> From<Array<A, D>> for ArcArray<A, D>
371where
372    D: Dimension,
373{
374    fn from(arr: Array<A, D>) -> ArcArray<A, D> {
375        arr.into_shared()
376    }
377}
378
379/// Argument conversion into an array view
380///
381/// The trait is parameterized over `A`, the element type, and `D`, the
382/// dimensionality of the array. `D` defaults to one-dimensional.
383///
384/// Use `.into()` to do the conversion.
385///
386/// ```
387/// use ndarray::AsArray;
388///
389/// fn sum<'a, V: AsArray<'a, f64>>(data: V) -> f64 {
390///     let array_view = data.into();
391///     array_view.sum()
392/// }
393///
394/// assert_eq!(
395///     sum(&[1., 2., 3.]),
396///     6.
397/// );
398///
399/// ```
400pub trait AsArray<'a, A: 'a, D = Ix1>: Into<ArrayView<'a, A, D>>
401where
402    D: Dimension,
403{
404}
405impl<'a, A: 'a, D, T> AsArray<'a, A, D> for T
406where
407    T: Into<ArrayView<'a, A, D>>,
408    D: Dimension,
409{
410}
411
412/// Create an owned array with a default state.
413///
414/// The array is created with dimension `D::default()`, which results
415/// in for example dimensions `0` and `(0, 0)` with zero elements for the
416/// one-dimensional and two-dimensional cases respectively.
417///
418/// The default dimension for `IxDyn` is `IxDyn(&[0])` (array has zero
419/// elements). And the default for the dimension `()` is `()` (array has
420/// one element).
421///
422/// Since arrays cannot grow, the intention is to use the default value as
423/// placeholder.
424impl<A, S, D> Default for ArrayBase<S, D>
425where
426    S: DataOwned<Elem = A>,
427    D: Dimension,
428    A: Default,
429{
430    // NOTE: We can implement Default for non-zero dimensional array views by
431    // using an empty slice, however we need a trait for nonzero Dimension.
432    fn default() -> Self {
433        ArrayBase::default(D::default())
434    }
435}