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}
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