Thanks to visit codestin.com
Credit goes to docs.rs

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