1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211
pub mod types; /// Module containing N-dimensional array storage, manipulation and file format support. /// /// # Introduction /// /// N-dimensional arrays are stored in `NDArray` structs. Slice of those arrays can be borrowed /// using the `NDSliceable` and `NDSliceableMut` trait which returns `NDSlice` and `NDSliceMut` /// respectively. Those slice can also be sliced into sub slice. /// /// Those N-dimensional structures implement two basic traits, `NDData` and `NDDataMut`, which give /// access to their data. /// /// The `NDIndex` trait provides helper functions to manipulate N-dimensional indexes. /// /// The CSV and Numpy sub module allow to load and store N-dimensional arrays. /// /// # Examples /// /// ## NDData /// /// `NDArray`, `NDSlice` and `NDSliceMut` all implement `NDData`: /// /// ``` /// use rds::array::{NDData, NDSliceable, NDArray, NDSlice}; /// /// let array = NDArray::<f32>::new(&[4, 3], 1.0); /// /// assert!(array.dim() == 2); /// assert!(array.shape() == &[4, 3]); /// assert!(array.strides() == &[3, 1]); /// assert!(array.size() == 12); /// /// for i in 0..array.shape()[0] { /// for j in 0..array.shape()[1] { /// // Indexing can use the idx method or the [] operator /// assert!(*array.idx(&[i,j]) == 1.0); /// assert!(array[&[i,j]] == 1.0); /// } /// } /// /// // We borrow the second row as a NDSlice which also implements NDData /// let row = array.slice(&[1]); /// /// assert!(row.dim() == 1); /// assert!(row.shape() == &[3]); /// assert!(row.strides() == &[1]); /// assert!(row.size() == 3); /// /// for i in 0..row.shape()[0] { /// assert!(*row.idx(&[i]) == 1.0); /// assert!(row[&[i]] == 1.0); /// } /// /// // NDData also overload the equality operator /// assert!(row == NDArray::<f32>::new(&[3], 1.0)); /// assert!(row != NDArray::<f32>::new(&[3], 0.0)); /// assert!(row != NDArray::<f32>::new(&[4], 1.0)); /// ``` /// ## NDDataMut /// /// `NDArray` and `NDSliceMut` implement NDDataMut: /// /// ``` /// use rds::array::{NDData, NDDataMut, NDSliceableMut, NDArray, NDSliceMut}; /// /// let mut array = NDArray::<f32>::new(&[3, 3], 1.0); /// /// for i in 0..array.shape()[0] { /// for j in 0..array.shape()[1] { /// // Assignation using idx_mut /// *array.idx_mut(&[i,j]) = (i * 10 + j) as f32; /// } /// } /// /// // mutable slicing and assign allow to set the first row to 0 /// array.slice_mut(&[0]).assign(&NDArray::<f32>::new(&[3], 0.0)); /// /// { /// // Mutable borrow of the second row of array /// let mut row = array.slice_mut(&[1]); /// for i in 0..row.shape()[0] { /// // Assignation using the [] operator /// row[&[i]] = (row.shape()[0] - i) as f32; /// } /// } /// /// // Transposition of the array, rows become columns /// array.transpose(); /// /// // If you've followed everything until here /// for i in 0..array.shape()[0] { /// assert!(array[&[i, 0]] == 0.0); /// assert!(array[&[i, 1]] == (array.shape()[0] - i) as f32); /// assert!(array[&[i, 2]] == (20 + i) as f32); /// } /// ``` /// /// ## CSV /// /// Here is how to load an array from a csv file, modify it then save it. /// /// ```no_run /// use rds::array::{NDData, NDDataMut, NDArray}; /// use rds::array::csv::CSVFile; /// /// let mut csv_file = CSVFile::new("data.csv"); /// let mut array : NDArray<f32> = csv_file.read_array().unwrap(); /// for i in 0..array.shape()[0] { /// for j in 0..array.shape()[1] { /// array[&[i,j]] += 1.0; /// } /// } /// csv_file.write_data(&array); /// ``` /// /// ## Numpy /// /// We can do the same with a numpy array for any number of dimensions using the `NDIndex` trait. /// /// ```no_run /// use std::iter::repeat; /// use rds::array::{NDData, NDDataMut, NDArray}; /// use rds::array::ndindex::NDIndex; /// use rds::array::numpy::NumpyFile; /// /// let mut numpy_file = NumpyFile::new("data.npy"); /// let mut array : NDArray<f32> = numpy_file.read_array().unwrap(); /// // Allocate an index with the right number of dimensions /// let mut idx : Vec<usize> = repeat(0usize).take(array.dim()).collect(); /// loop { /// array[&idx[..]] += 1.0; /// // Increment the index in row-major order /// idx.inc_ro(array.shape()); /// // If the index overflow to zero, we looped through every elements /// if idx.is_zero() { /// break; /// } /// } /// numpy_file.write_data(&array); /// ``` pub mod array; /// Module containing Blas bindings and overloaded operation for `NDData`. /// /// # Introduction /// /// Blas functionalities are implemented for any struct implementing `NDDataMut<T>` where `T` is /// either f32 or f64. /// /// The convention is that the calling array is always the output array. This means for example /// that a matrix vector multiplication should be called on the vector. Whether a matrix need a /// translation or not is infered by the framework. If there are more than one solution, the one /// requiring the less translations is taken. /// /// The operators are overloaded to use those Blas functions, however they only operate on /// references making the syntax a bit weird. /// /// # Examples /// /// ## Blas level 1 /// /// ``` /// use rds::array::{NDDataMut, NDArray}; /// use rds::blas::Blas; /// /// let mut array1 = NDArray::<f32>::new(&[5], 1.0); /// assert!(array1.asum() == 5.0); /// assert!(array1.asum() == 5.0); /// array1.scal(2.0); /// let mut array2 = NDArray::<f32>::copy(&array1); /// assert!(array1.dot(&array2) == 20.0); /// array2 += &array1; /// assert!(array2.asum() == 20.0); /// ``` /// /// ## Blas level 2 /// /// ``` /// use rds::array::{NDDataMut, NDArray}; /// use rds::blas::Blas; /// /// let vec1 = NDArray::<f32>::from_slice(&[2], &[2.0, 0.0]); /// let mut vec2 = NDArray::<f32>::copy(&vec1); /// let rot90 = NDArray::<f32>::from_slice(&[2,2], &[0.0, -1.0, 1.0, 0.0]); /// vec2 *= &rot90; /// assert!(vec1.dot(&vec2) == 0.0); /// assert!(vec2 == NDArray::<f32>::from_slice(&[2], &[0.0, 2.0])); /// ``` /// ## Blas level 3 /// /// /// ``` /// use rds::array::{NDDataMut, NDArray}; /// use rds::blas::Blas; /// /// let rot90 = NDArray::<f32>::from_slice(&[2,2], &[0.0, -1.0, 1.0, 0.0]); /// let rot180 = &rot90 * &rot90; /// let identity = NDArray::<f32>::from_slice(&[2,2], &[1.0, 0.0, 0.0, 1.0]); /// let mut transformed = NDArray::<f32>::copy(&identity); /// transformed *= &rot90; /// transformed *= &rot180; /// transformed *= &rot90; /// assert!(transformed == identity); /// ``` pub mod blas; pub mod backend; #[cfg(test)] mod tests;