multidimension/
array.rs

1use super::{Isomorphic, Size, Index, impl_ops_for_view, View, ViewRef, ViewMut, impl_ops_for_memoryview};
2
3/// A dense array of `T`s indexed by `I`.
4#[derive(Debug, Clone)]
5pub struct Array<I: Index, T> {
6    size: I::Size,
7    items: Box<[T]>,
8}
9
10impl<I: Index, T> Array<I, T> {
11    fn new_inner(size: I::Size, items: Box<[T]>) -> Self {
12        assert_eq!(I::length(size), items.len());
13        Self {size, items}
14    }
15
16    /// Constructs an `Array` of size `size` given its elements.
17    ///
18    /// ```
19    /// use multidimension::{Index, Array};
20    /// let a: Array<(usize, bool), f32> = Array::new(3, [0.0, 1.0, -1.0, 2.0, 3.0, -2.0]);
21    /// assert_eq!(a[(0, false)], 0.0);
22    /// assert_eq!(a[(0, true)], 1.0);
23    /// assert_eq!(a[(1, false)], -1.0);
24    /// assert_eq!(a[(1, true)], 2.0);
25    /// assert_eq!(a[(2, false)], 3.0);
26    /// assert_eq!(a[(2, true)], -2.0);
27    /// ```
28    pub fn new(size: impl Isomorphic<I::Size>, items: impl Into<Box<[T]>>) -> Self {
29        Self::new_inner(size.to_iso(), items.into())
30    }
31
32    /// Construct an `Array` of size `size` from a function.
33    ///
34    /// Consider also [`fn_view()`].
35    ///
36    /// [`fn_view()`]: super::fn_view
37    ///
38    /// ```
39    /// use multidimension::{Index, Array};
40    /// let a: Array<usize, _> = Array::from_fn(10, |x| x % 3 == 0);
41    /// assert_eq!(a.as_ref(), [true, false, false, true, false, false, true, false, false, true]);
42    /// ```
43    pub fn from_fn(
44        size: impl Isomorphic<I::Size>,
45        mut f: impl FnMut(I) -> T,
46    ) -> Self {
47        let size = size.to_iso();
48        let mut items = Vec::with_capacity(I::length(size));
49        size.each(|i| items.push(f(i)));
50        Self::new_inner(size, items.into())
51    }
52
53    /// Returns the raw array elements.
54    pub fn to_raw(self) -> Box<[T]> { self.items }
55
56    /// Change the index type of this array without moving any of the items.
57    pub fn iso<J: Index>(self) -> Array<J, T> where
58        J: Isomorphic<I>,
59        J::Size: Isomorphic<<I as Index>::Size>,
60    {
61        Array {size: J::Size::from_iso(self.size), items: self.items}
62    }
63}
64
65impl<I: Index, T> std::convert::AsRef<[T]> for Array<I, T> {
66    fn as_ref(&self) -> &[T] { &self.items }
67}
68
69impl<I: Index, T> std::convert::AsMut<[T]> for Array<I, T> {
70    fn as_mut(&mut self) -> &mut [T] { &mut self.items }
71}
72
73impl<I: Index, T: Clone> View for Array<I, T> {
74    type I = I;
75    type T = T;
76    #[inline(always)]
77    fn size(&self) -> I::Size { self.size }
78    #[inline(always)]
79    fn len(&self) -> usize { self.as_ref().len() }
80    #[inline(always)]
81    fn at(&self, index: I) -> T { self[index].clone() }
82}
83
84impl<I: Index, T: Clone> ViewRef for Array<I, T> {
85    #[inline(always)]
86    fn at_ref(&self, index: Self::I) -> &Self::T { &self.items[index.to_usize(self.size)] }
87}
88
89impl<I: Index, T: Clone> ViewMut for Array<I, T> {
90    #[inline(always)]
91    fn at_mut(&mut self, index: Self::I) -> &mut Self::T { &mut self.items[index.to_usize(self.size)] }
92}
93
94impl_ops_for_view!(Array<I: Index, T>);
95impl_ops_for_memoryview!(Array<I: Index, T>);
96
97// ----------------------------------------------------------------------------
98
99impl<T> super::Push<T> for Vec<T> {
100    fn push(&mut self, t: T) { Vec::push(self, t); }
101}
102
103impl<I: Index, T: Clone> super::NewView for Array<I, T> {
104    type Buffer = Vec<T>;
105
106    fn new_view(
107        size: I::Size,
108        callback: impl FnOnce(&mut Self::Buffer),
109    ) -> Self {
110        let mut buffer = Vec::with_capacity(I::length(size));
111        callback(&mut buffer);
112        Self::new_inner(size, buffer.into())
113    }
114}