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