mop_structs/matrix/dr_matrix/
mod.rs

1mod dr_matrix_row_constructor;
2mod dr_matrix_row_iter_impls;
3#[cfg(feature = "rayon")]
4mod dr_matrix_row_par_iter_impls;
5
6pub use self::{
7  dr_matrix_row_constructor::DrMatrixRowConstructor,
8  dr_matrix_row_iter_impls::{DrMatrixRowIter, DrMatrixRowIterMut},
9};
10use crate::{
11  dim::Dim,
12  prelude::{Array, DynDenseStoMut, DynDenseStoRef, Matrix, StDenseStoMut, StDenseStoRef},
13  vec::VecArray,
14};
15
16#[cfg_attr(
17  feature = "serde1",
18  derive(mop_common_deps::serde::Deserialize, mop_common_deps::serde::Serialize)
19)]
20#[derive(Clone, Copy, Debug, Default, Hash, PartialEq, PartialOrd)]
21pub struct DrMatrix<DS> {
22  data: DS,
23  dim: Dim<[usize; 2]>,
24}
25
26pub type DrMatrixArray<DA> = DrMatrix<DA>;
27pub type DrMatrixMut<'a, T> = DrMatrix<&'a mut [T]>;
28pub type DrMatrixRef<'a, T> = DrMatrix<&'a [T]>;
29#[cfg(feature = "std")]
30pub type DrMatrixVec<T> = DrMatrix<Vec<T>>;
31pub type DrMatrixVecArray<DA> = DrMatrix<VecArray<DA>>;
32
33impl<DS> DrMatrix<DS> {
34  #[inline]
35  fn stride(&self, idx: usize) -> usize {
36    self.cols() * idx
37  }
38}
39
40#[cfg(feature = "std")]
41impl<T> DrMatrixVec<T> {
42  #[cfg(feature = "rand")]
43  pub fn new_rnd<F, R>(shape: [usize; 2], rng: &mut R, mut cb: F) -> Self
44  where
45    F: FnMut(&mut R, [usize; 2]) -> T,
46    R: mop_common_deps::rand::Rng,
47  {
48    let dim: Dim<[usize; 2]> = shape.into();
49    let mut data = Vec::with_capacity(dim.rows() * dim.cols());
50    for x in 0..dim.rows() {
51      for y in 0..dim.cols() {
52        data.push(cb(rng, [x, y]));
53      }
54    }
55    DrMatrix { data, dim }
56  }
57
58  pub fn with_vec_capacity(shape: [usize; 2]) -> Self {
59    DrMatrix {
60      data: Vec::with_capacity(shape[0] * shape[1]),
61      dim: [0, shape[1]].into(),
62    }
63  }
64}
65
66impl<DA> DrMatrixVecArray<DA>
67where
68  DA: Array,
69{
70  #[cfg(feature = "rand")]
71  pub fn new_rnd<F, R>(shape: [usize; 2], rng: &mut R, mut cb: F) -> Self
72  where
73    F: FnMut(&mut R, [usize; 2]) -> DA::Item,
74    R: mop_common_deps::rand::Rng,
75  {
76    let dim: Dim<[usize; 2]> = shape.into();
77    let data = VecArray::new_rnd(dim.rows() * dim.cols(), rng, |rng, idx| {
78      cb(rng, crate::utils::matrix_x_y(dim.cols(), idx))
79    });
80    DrMatrix { data, dim }
81  }
82
83  pub fn with_vec_array(cols: usize) -> Self {
84    DrMatrix {
85      data: VecArray::with_capacity(),
86      dim: [0, cols].into(),
87    }
88  }
89}
90
91impl<DS> DrMatrix<DS>
92where
93  DS: StDenseStoRef,
94{
95  /// Creates a new [`DrMatrix`](DrMatrix) from raw parameters.
96  ///
97  /// # Arguments
98  ///
99  /// * `shape` - An array containing the number of rows and columns.
100  /// * `data` - The matrix data.
101  ///
102  /// # Examples
103  ///
104  /// ```rust
105  /// use mop_structs::matrix::dr_matrix::DrMatrixArray;
106  /// let _ = DrMatrixArray::new([2, 4], [1, 2, 3, 4, 5, 6, 7, 8]);
107  /// ```
108  ///
109  /// # Assertions
110  ///
111  /// * The length of `data` must be equal the number of rows times the number of columns.
112  ///
113  /// ```should_panic
114  /// use mop_structs::matrix::dr_matrix::DrMatrixRef;
115  /// let _ = DrMatrixRef::new([2, 4], &[1, 2, 3]);
116  /// ```
117  pub fn new(shape: [usize; 2], data: DS) -> Self {
118    let dim: Dim<[usize; 2]> = shape.into();
119    assert!(dim.rows() * dim.cols() == data.as_slice().len());
120    Self::new_unchecked(shape, data)
121  }
122
123  /// A faster and unsafe version of [`new`](#method.new).
124  pub fn new_unchecked(shape: [usize; 2], data: DS) -> Self {
125    DrMatrix {
126      data,
127      dim: shape.into(),
128    }
129  }
130
131  /// Converts the inner storage to a generic immutable slice storage.
132  ///
133  /// # Examples
134  ///
135  /// ```rust
136  /// use mop_structs::{
137  ///     doc_tests::dr_matrix_array,
138  ///     matrix::dr_matrix::DrMatrixRef
139  /// };
140  /// assert_eq!(
141  ///     dr_matrix_array().as_ref(),
142  ///     DrMatrixRef::new(
143  ///         [4, 5],
144  ///         &[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20],
145  ///     )
146  /// );
147  /// ```
148  pub fn as_ref(&self) -> DrMatrixRef<'_, DS::Item> {
149    DrMatrix::new([self.dim.rows(), self.dim.cols()], self.data.as_slice())
150  }
151
152  pub fn data(&self) -> &[DS::Item] {
153    &self.data.as_slice()
154  }
155
156  pub fn row(&self, idx: usize) -> &[DS::Item] {
157    let stride = self.stride(idx);
158    &self.data()[stride..stride + self.cols()]
159  }
160
161  pub fn row_iter(&self) -> DrMatrixRowIter<'_, DS::Item> {
162    DrMatrixRowIter::new([self.rows(), self.cols()], self.data().as_ptr())
163  }
164
165  #[cfg(feature = "rayon")]
166  pub fn row_par_iter(
167    &self,
168  ) -> crate::utils::ParallelIteratorWrapper<DrMatrixRowIter<'_, DS::Item>> {
169    crate::utils::ParallelIteratorWrapper(self.row_iter())
170  }
171
172  pub fn value(&self, row_idx: usize, col_idx: usize) -> &DS::Item {
173    &self.data()[self.stride(row_idx) + col_idx]
174  }
175}
176
177impl<DS> DrMatrix<DS>
178where
179  DS: StDenseStoMut,
180{
181  pub fn data_mut(&mut self) -> &mut [DS::Item] {
182    self.data.as_mut_slice()
183  }
184
185  pub fn row_mut(&mut self, idx: usize) -> &mut [DS::Item] {
186    let stride = self.stride(idx);
187    &mut self.data.as_mut_slice()[stride..stride + self.dim.cols()]
188  }
189
190  pub fn row_iter_mut(&mut self) -> DrMatrixRowIterMut<'_, DS::Item> {
191    DrMatrixRowIterMut::new([self.rows(), self.cols()], self.data_mut().as_mut_ptr())
192  }
193
194  #[cfg(feature = "rayon")]
195  pub fn row_par_iter_mut(
196    &mut self,
197  ) -> crate::utils::ParallelIteratorWrapper<DrMatrixRowIterMut<'_, DS::Item>> {
198    crate::utils::ParallelIteratorWrapper(self.row_iter_mut())
199  }
200
201  pub fn swap(&mut self, a: [usize; 2], b: [usize; 2]) {
202    let a_data_idx = self.stride(a[0]) + a[1];
203    let b_data_idx = self.stride(b[0]) + b[1];
204    self.data_mut().swap(a_data_idx, b_data_idx)
205  }
206
207  pub fn two_rows_mut(&mut self, smaller_idx: usize, bigger_idx: usize) -> [&mut [DS::Item]; 2] {
208    let bigger = self.stride(bigger_idx);
209    let smaller = self.stride(smaller_idx);
210    let (first, second) = self.data.as_mut_slice().split_at_mut(bigger);
211    [
212      &mut first[smaller..smaller + self.dim.cols()],
213      &mut second[0..self.dim.cols()],
214    ]
215  }
216
217  pub fn value_mut(&mut self, row_idx: usize, col_idx: usize) -> &mut DS::Item {
218    let stride = self.stride(row_idx);
219    &mut self.data_mut()[stride + col_idx]
220  }
221}
222
223impl<DS> DrMatrix<DS>
224where
225  DS: DynDenseStoRef,
226{
227  #[inline]
228  pub fn rows_capacity(&self) -> usize {
229    self.data.capacity() / self.dim.cols()
230  }
231}
232
233impl<DS> DrMatrix<DS>
234where
235  DS: DynDenseStoMut,
236{
237  pub fn clear(&mut self) {
238    self.data.clear();
239    *self.dim.rows_mut() = 0;
240  }
241
242  pub fn extend<AD>(&mut self, other: &DrMatrix<AD>)
243  where
244    AD: DynDenseStoMut<Item = DS::Item>,
245    DS::Item: Copy,
246  {
247    assert!(self.cols() == other.cols());
248    self.data.extend(other.data());
249    *self.dim.rows_mut() += other.rows();
250  }
251
252  pub fn extend_from_clone<AD>(&mut self, other: &DrMatrix<AD>)
253  where
254    AD: DynDenseStoMut<Item = DS::Item>,
255    DS::Item: Clone,
256  {
257    assert!(self.cols() == other.cols());
258    self.data.extend_from_clone(other.data());
259    *self.dim.rows_mut() += other.rows();
260  }
261
262  pub fn row_constructor(&mut self) -> DrMatrixRowConstructor<'_, DS> {
263    DrMatrixRowConstructor::new(&mut self.data, &mut self.dim)
264  }
265
266  pub fn truncate(&mut self, until_row_idx: usize) {
267    self.data.truncate(self.dim.cols() * until_row_idx);
268    *self.dim.rows_mut() = until_row_idx;
269  }
270}
271
272impl<DS> Matrix for DrMatrix<DS> {
273  #[inline]
274  fn cols(&self) -> usize {
275    self.dim.cols()
276  }
277
278  #[inline]
279  fn rows(&self) -> usize {
280    self.dim.rows()
281  }
282}
283
284#[cfg(all(feature = "quickcheck", feature = "rand"))]
285use mop_common_deps::{
286  quickcheck::{Arbitrary, Gen},
287  rand::{
288    distributions::{Distribution, Standard},
289    Rng,
290  },
291};
292#[cfg(all(feature = "quickcheck", feature = "rand"))]
293impl<T> Arbitrary for DrMatrixVec<T>
294where
295  Standard: Distribution<T>,
296  T: Arbitrary,
297{
298  #[inline]
299  fn arbitrary<G>(g: &mut G) -> Self
300  where
301    G: Gen,
302  {
303    DrMatrixVec::new_rnd(
304      [g.gen_range(0, g.size()), g.gen_range(0, g.size())],
305      g,
306      |g, _| g.gen(),
307    )
308  }
309}
310
311#[cfg(test)]
312mod tests {
313  #[cfg_attr(rustfmt, rustfmt_skip)]
314    const DEFAULT_DATA: [i32; 20] = [
315        1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
316        11, 12, 13, 14, 15, 16, 17, 18, 19, 20
317    ];
318  const DEFAULT_SHAPE: [usize; 2] = [4, 5];
319
320  use crate::{matrix::dr_matrix::DrMatrix, prelude::*, vec::VecArray};
321
322  #[test]
323  pub fn dr_matrix_alloc_clear() {
324    let mut dcca = default_dr_matrix_alloc();
325    dcca.clear();
326    assert_eq!(dcca.cols(), DEFAULT_SHAPE[1]);
327    assert_eq!(dcca.data(), &[]);
328    assert_eq!(dcca.rows(), 0);
329  }
330
331  #[test]
332  pub fn dr_matrix_alloc_cols() {
333    assert_eq!(default_dr_matrix_alloc().cols(), DEFAULT_SHAPE[1]);
334  }
335
336  #[test]
337  pub fn dr_matrix_alloc_data() {
338    assert_eq!(default_dr_matrix_alloc().data(), &DEFAULT_DATA);
339  }
340
341  #[test]
342  pub fn dr_matrix_alloc_data_mut() {
343    assert_eq!(default_dr_matrix_alloc().data_mut(), &mut DEFAULT_DATA);
344  }
345
346  #[test]
347  pub fn dr_matrix_alloc_row() {
348    let ddma = default_dr_matrix_alloc();
349    for row_idx in 0..4 {
350      let starting_row_value = row_idx * 5 + 1;
351      assert_eq!(
352        ddma.row(row_idx as usize),
353        &[
354          starting_row_value,
355          starting_row_value + 1,
356          starting_row_value + 2,
357          starting_row_value + 3,
358          starting_row_value + 4
359        ]
360      );
361    }
362  }
363
364  #[test]
365  pub fn dr_matrix_alloc_rows() {
366    assert_eq!(default_dr_matrix_alloc().rows(), DEFAULT_SHAPE[0]);
367  }
368
369  #[test]
370  pub fn dr_matrix_alloc_truncate() {
371    let mut ddma = default_dr_matrix_alloc();
372    ddma.truncate(2);
373    assert_eq!(ddma.cols(), DEFAULT_SHAPE[1]);
374    assert_eq!(ddma.data(), &DEFAULT_DATA[0..10]);
375    assert_eq!(ddma.rows(), 2);
376  }
377
378  #[test]
379  pub fn dr_matrix_alloc_value() {
380    let ddma = default_dr_matrix_alloc();
381    for row_idx in 0..4 {
382      let starting_row_value = row_idx * 5 + 1;
383      for col_idx in 0..5 {
384        assert_eq!(
385          *ddma.value(row_idx as usize, col_idx as usize),
386          starting_row_value + col_idx
387        );
388      }
389    }
390  }
391
392  fn default_dr_matrix_alloc() -> DrMatrix<VecArray<[i32; 20]>> {
393    DrMatrix::new([4, 5], VecArray::with_array(DEFAULT_DATA))
394  }
395}