numas/array/
array.rs

1use std::fmt;
2use std::cell::RefCell;
3use std::rc::Rc;
4
5use shape::Shape;
6
7
8/// Array structure
9pub struct Array<T: Copy> {
10    pub data: Rc<RefCell<Vec<T>>>,
11    pub shape: Shape,
12}
13
14impl<T: Copy> Array<T> {
15    /// Creates new bounded array
16    ///
17    /// # Arguments
18    ///
19    /// * `data` - array elements
20    /// * `shape` - vector representing array shape
21    /// * `start` - start offset of array data
22    /// * `end` - end offset of array data
23    #[inline]
24    pub fn new_bounded(data: Vec<T>, shape: Vec<i32>, start: usize, end: usize) -> Array<T> {
25        return Array {
26            data: Rc::new(RefCell::new(data)),
27            shape: Shape::new(shape, start, end)
28        };
29    }
30
31    /// Creates new array
32    ///
33    /// # Arguments
34    ///
35    /// * `data` - array elements
36    /// * `shape` - vector representing array shape
37    pub fn new(data: Vec<T>, shape: Vec<i32>) -> Array<T> {
38        let length = data.len();
39
40        return Array::new_bounded(data, shape, 0, length);
41    }
42
43    /// Returns Shape instance
44    #[inline]
45    pub fn shape(&self) -> &Shape {
46        &self.shape
47    }
48
49    /// Returns vector representing array shape
50    #[inline]
51    pub fn get_shape(&self) -> &Vec<i32> {
52        self.shape.get_shape()
53    }
54
55    /// Sets array shape
56    ///
57    /// # Arguments
58    ///
59    /// * `shape` - vector representing new array shape
60    #[inline]
61    pub fn reshape(&mut self, shape: Vec<i32>) -> &Array<T> {
62        self.shape.set_shape(shape);
63        return self;
64    }
65
66    /// Sets array shape
67    ///
68    /// # Arguments
69    ///
70    /// * `shape` - vector representing new array shape
71    #[inline]
72    pub fn set_shape(&mut self, shape: Vec<i32>) -> () {
73        self.shape.set_shape(shape);
74    }
75
76    /// Validates indices have right dimension
77    ///
78    /// # Arguments
79    ///
80    /// * `indices` - Indices
81    fn check_indices_size(&self, indices: &Vec<usize>) -> () {
82        let shape_len = self.shape.get_shape().len();
83
84        if indices.len() / 2 > shape_len {
85            panic!(
86                "Invalid indices given: shape dimensions {}, indices dimensions {}",
87                shape_len,
88                indices.len() / 2
89            );
90        }
91    }
92
93    /// Set values on given indices to given value
94    ///
95    /// # Arguments
96    ///
97    /// * `indices` - vector of indices
98    /// * `value` - value to fill it with
99    ///
100    /// # Examples
101    ///
102    /// ```
103    /// #[macro_use] extern crate numas;
104    /// use numas::array::Array;
105    ///
106    /// let f_array = Array::new(vec![1,2,3,4,5,6,7,8,9], vec![3,3]);
107    /// 
108    /// // first row
109    /// f_array.set(s![0], -1);
110    /// assert_eq!(f_array.collect(), vec![-1,-1,-1,4,5,6,7,8,9]);
111    ///
112    /// let s_array = Array::new(vec![1,2,3,4,5,6,7,8,9], vec![3,3]);
113    ///
114    /// // fist two rows
115    /// s_array.set(s![0 => 2], -1);
116    /// assert_eq!(s_array.collect(), vec![-1,-1,-1,-1,-1,-1,7,8,9]);
117    ///
118    /// let t_array = Array::new(vec![1,2,3,4,5,6,7,8,9], vec![3,3]);
119    ///
120    /// // second row, second column
121    /// t_array.set(s![1; 1], -1);
122    /// assert_eq!(t_array.collect(), vec![1,2,3,4,-1,6,7,8,9]);
123    ///
124    /// let x_array = Array::new(vec![1,2,3,4,5,6,7,8,9], vec![3,3]);
125    ///
126    /// // last row, two last columns
127    /// x_array.set(s![2; 1 => 3], -1);
128    /// assert_eq!(x_array.collect(), vec![1,2,3,4,5,6,7,-1,-1]);
129    /// ```
130    pub fn set(&self, indices: Vec<usize>, value: T) -> () {
131        self.check_indices_size(&indices);
132
133        let shape = self.shape.indices_to_shape(indices);
134        let mut data = self.data.borrow_mut();
135
136        for i in shape.get_bounds() {
137            data[i] = value;
138        }
139    }
140
141    /// Fills array with given value
142    ///
143    /// # Arguments
144    ///
145    /// * `value` - fill value
146    pub fn fill(&self, value: T) -> &Array<T> {
147        let mut data = self.data.borrow_mut();
148
149        for i in self.shape.get_bounds() {
150            data[i] = value;
151        }
152
153        return self;
154    }
155
156    /// Return new Array from given indices
157    ///
158    /// # Arguments
159    ///
160    /// * `indices` - vector of indices
161    ///
162    /// # Examples
163    ///
164    /// ```
165    /// #[macro_use] extern crate numas;
166    /// use numas::array::Array;
167    ///
168    /// let array = Array::new(vec![1,2,3,4,5,6,7,8,9], vec![3,3]);
169    ///
170    /// // first row
171    /// assert_eq!(array.get(s![0]).collect(), vec![1,2,3]);
172    ///
173    /// // fist two rows
174    /// assert_eq!(array.get(s![0 => 2]).collect(), vec![1,2,3,4,5,6]);
175    ///
176    /// // second row, second column
177    /// assert_eq!(array.get(s![1; 1]).collect(), vec![5]);
178    ///
179    /// // last row, two last columns
180    /// assert_eq!(array.get(s![2; 1 => 3]).collect(), vec![8,9]);
181    /// ```
182    pub fn get(&self, indices: Vec<usize>) -> Array<T> {
183        // Handle invalid indices length
184        self.check_indices_size(&indices);
185
186        let new_shape = self.shape.indices_to_shape(indices);
187
188        return Array {
189            shape: new_shape,
190            data: self.data.clone(),
191        };
192    }
193
194    /// Returns length of array
195    pub fn len(&self) -> usize {
196        return Shape::total_len(&self.shape) as usize;
197    }
198
199    /// Returns base length of array
200    #[inline]
201    pub fn base_len(&self) -> usize {
202        return self.data.borrow().len();
203    }
204
205    /// Creates view into array
206    #[inline]
207    pub fn view(&self) -> Array<T> {
208        return Array {
209            data: self.data.clone(),
210            shape: self.shape.clone(),
211        }
212    }
213
214    /// Creates bounded view into array
215    ///
216    /// # Arguments
217    ///
218    /// * `shape` - vector representing array shape
219    /// * `start` - start offset of array data
220    /// * `end` - end offset of array data
221    #[inline]
222    pub fn bounded_view(&self, shape: &Vec<i32>, start: usize, end: usize) -> Array<T> {
223        return Array {
224            data: self.data.clone(),
225            shape: Shape::new(shape.clone(), start, end),
226        }
227    }
228
229    /// Collects elements of array into vector
230    pub fn collect(&self) -> Vec<T> {
231        let data = self.data.borrow();
232        return data[self.shape.get_bounds()].to_vec();
233    }
234}
235
236impl<T: Copy> Clone for Array<T> {
237    /// Clones array object
238    fn clone(&self) -> Array<T> {
239        let data = self.data.borrow().to_vec().clone();
240
241        return Array {
242            data: Rc::new(RefCell::new(data)),
243            shape: self.shape.clone(),
244        };
245    }
246}
247
248impl <T: fmt::Debug + Copy> fmt::Debug for Array<T> {
249    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
250        let data = self.data.borrow();
251        return write!(f, "data: \t{:?}\nshape: \t{:?}", &data[self.shape.get_bounds()], self.get_shape());
252    }
253}