mop_structs/matrix/csr_matrix/mod.rs
1//! CSR (Compressed Sparse Row) matrix.
2//!
3//! See [Wikipedia](https://en.wikipedia.org/wiki/Sparse_matrix).
4
5#[cfg(feature = "rand")]
6mod csr_matrix_rnd;
7mod csr_matrix_row_constructor;
8mod csr_matrix_row_iter_impls;
9#[cfg(feature = "rayon")]
10mod csr_matrix_row_par_iter_impls;
11
12pub use self::{
13 csr_matrix_row_constructor::CsrMatrixRowConstructor,
14 csr_matrix_row_iter_impls::{CsrMatrixRowIter, CsrMatrixRowIterMut},
15};
16use crate::{
17 dim::Dim,
18 prelude::{Array, DynDenseStoMut, DynDenseStoRef, Matrix, StDenseStoMut, StDenseStoRef},
19 utils::{are_in_upper_bound, does_not_have_duplicates},
20 vec::{
21 css::{CssSlice, CssSliceMut},
22 VecArray,
23 },
24};
25use core::ops::Range;
26
27/// This structure can hold differents mixed types of indexed storages.
28#[cfg_attr(
29 feature = "serde1",
30 derive(mop_common_deps::serde::Deserialize, mop_common_deps::serde::Serialize)
31)]
32#[derive(Clone, Copy, Debug, Default, Hash, PartialEq, PartialOrd)]
33pub struct CsrMatrix<DS, US> {
34 data: DS,
35 dim: Dim<[usize; 2]>,
36 indcs: US,
37 ptrs: US,
38}
39
40pub type CsrMatrixArray<DA, UA> = CsrMatrix<DA, UA>;
41#[cfg(feature = "std")]
42pub type CsrMatrixVec<T> = CsrMatrix<Vec<T>, Vec<usize>>;
43pub type CsrMatrixVecArray<DA, UA> = CsrMatrix<VecArray<DA>, VecArray<UA>>;
44pub type CsrMatrixRef<'a, T> = CsrMatrix<&'a [T], &'a [usize]>;
45
46#[cfg(feature = "std")]
47impl<T> CsrMatrixVec<T> {
48 #[cfg(feature = "rand")]
49 pub fn new_rnd<F, R>(shape: [usize; 2], nnz: usize, rng: &mut R, cb: F) -> Self
50 where
51 F: FnMut(&mut R, [usize; 2]) -> T,
52 R: mop_common_deps::rand::Rng,
53 {
54 let dim: Dim<[usize; 2]> = shape.into();
55 let capacity = dim.rows() * dim.cols();
56 assert!(nnz <= capacity);
57 let mut cmr = self::csr_matrix_rnd::CsrMatrixRnd {
58 data: Vec::with_capacity(nnz),
59 dim: &dim,
60 indcs: Vec::with_capacity(nnz),
61 nnz,
62 ptrs: Vec::with_capacity(dim.rows() + 1),
63 rng,
64 };
65 cmr.fill_ptrs();
66 cmr.fill_indcs();
67 cmr.fill_data(cb);
68 CsrMatrixVec::new([dim.rows(), dim.cols()], cmr.data, cmr.indcs, cmr.ptrs)
69 }
70
71 pub fn with_vec_capacity(shape: [usize; 2], nnz: usize) -> Self {
72 let mut ptrs = Vec::with_capacity(shape[0] + 1);
73 ptrs.push(0);
74 CsrMatrix {
75 data: Vec::with_capacity(nnz),
76 dim: [0, shape[1]].into(),
77 indcs: Vec::with_capacity(nnz),
78 ptrs,
79 }
80 }
81}
82
83impl<DA, UA> CsrMatrixVecArray<DA, UA>
84where
85 DA: Array,
86 UA: Array<Item = usize>,
87{
88 #[cfg(feature = "rand")]
89 pub fn new_rnd<F, R>(shape: [usize; 2], nnz: usize, rng: &mut R, cb: F) -> Self
90 where
91 F: FnMut(&mut R, [usize; 2]) -> DA::Item,
92 R: mop_common_deps::rand::Rng,
93 {
94 let dim: Dim<[usize; 2]> = shape.into();
95 let capacity = dim.rows() * dim.cols();
96 assert!(nnz <= capacity);
97 let mut cmr = self::csr_matrix_rnd::CsrMatrixRnd {
98 data: VecArray::<DA>::with_capacity(),
99 dim: &dim,
100 indcs: VecArray::<UA>::with_capacity(),
101 nnz,
102 ptrs: VecArray::<UA>::with_capacity(),
103 rng,
104 };
105 cmr.fill_ptrs();
106 cmr.fill_indcs();
107 cmr.fill_data(cb);
108 CsrMatrixVecArray::new([dim.rows(), dim.cols()], cmr.data, cmr.indcs, cmr.ptrs)
109 }
110
111 pub fn with_vec_array(cols: usize) -> Self {
112 let mut ptrs_vec_array = VecArray::with_capacity();
113 ptrs_vec_array.push(0);
114 CsrMatrixVecArray {
115 data: VecArray::with_capacity(),
116 dim: [0, cols].into(),
117 indcs: VecArray::with_capacity(),
118 ptrs: ptrs_vec_array,
119 }
120 }
121}
122
123impl<DS, US> CsrMatrix<DS, US>
124where
125 DS: StDenseStoRef,
126 US: StDenseStoRef<Item = usize>,
127{
128 /// Creates a new [`CsrMatrix`](CsrMatrix) from raw parameters.
129 ///
130 /// # Arguments
131 ///
132 /// * `shape` - An array containing the number of rows and columns.
133 /// * `data` - The matrix data.
134 /// * `indcs` - Each column index of its corresponding data.
135 /// * `ptrs` - The length of each row.
136 ///
137 /// # Examples
138 ///
139 /// ```rust
140 /// use mop_structs::matrix::csr_matrix::CsrMatrixArray;
141 /// let _ = CsrMatrixArray::new([2, 4], [1, 2, 3], [0, 1, 2], [0, 3, 3]);
142 /// ```
143 ///
144 /// # Assertions
145 ///
146 /// * The length of `data` must be equal the length of `indcs`.
147 ///
148 /// ```should_panic
149 /// use mop_structs::matrix::csr_matrix::CsrMatrixRef;
150 /// let _ = CsrMatrixRef::new([2, 4], &[1, 2, 3], &[], &[0, 3, 3]);
151 /// ```
152 ///
153 /// * The length of `data` is greater than the number of rows times the number of columns.
154 ///
155 /// ```should_panic
156 /// use mop_structs::matrix::csr_matrix::CsrMatrixRef;
157 /// let _ = CsrMatrixRef::new(
158 /// [2, 4], &[1, 2, 3, 4, 5, 6, 7, 8, 9], &[0, 1, 2, 3, 0, 1, 2, 3, 0], &[0, 4, 8]
159 /// );
160 /// ```
161 ///
162 /// * The length of `ptrs` must be equal the number of rows plus 1.
163 ///
164 /// ```should_panic
165 /// use mop_structs::matrix::csr_matrix::CsrMatrixRef;
166 /// let _ = CsrMatrixRef::new([2, 4], &[1, 2, 3], &[0, 1, 2], &[0, 3, 3, 3, 3]);
167 /// ```
168 ///
169 /// * Column indices must be less than the number of columns.
170 ///
171 /// ```should_panic
172 /// use mop_structs::matrix::csr_matrix::CsrMatrixRef;
173 /// let _ = CsrMatrixRef::new([2, 4], &[1, 2, 3], &[0, 1, 9], &[0, 3, 3]);
174 /// ```
175 ///
176 /// * Column indices of a row must be unique.
177 ///
178 /// ```should_panic
179 /// use mop_structs::matrix::csr_matrix::CsrMatrixRef;
180 /// let _ = CsrMatrixRef::new([2, 4], &[1, 2, 3], &[0, 0, 0], &[0, 3, 3]);
181 /// ```
182 ///
183 /// * Rows length must end with the nnz.
184 ///
185 /// ```should_panic
186 /// use mop_structs::matrix::csr_matrix::CsrMatrixRef;
187 /// let _ = CsrMatrixRef::new([2, 4], &[1, 2, 3], &[0, 1, 2], &[0, 3, 9]);
188 /// ```
189 ///
190 /// * Rows length must be in ascending order.
191 ///
192 /// ```should_panic
193 /// use mop_structs::matrix::csr_matrix::CsrMatrixRef;
194 /// let _ = CsrMatrixRef::new([3, 4], &[1, 2, 3, 4], &[0, 0, 0, 1], &[0, 1, 0, 4]);
195 /// ```
196 pub fn new(shape: [usize; 2], data: DS, indcs: US, ptrs: US) -> Self {
197 let dim: Dim<[usize; 2]> = shape.into();
198 assert!(
199 data.as_slice().len() == indcs.as_slice().len(),
200 "The length of `data` must be equal the length of `indcs`."
201 );
202 assert!(
203 data.as_slice().len() <= dim.rows() * dim.cols(),
204 "The length of `data` must be less than the number of rows times the \
205 number of columns."
206 );
207 assert!(
208 ptrs.as_slice().len() == dim.rows() + 1,
209 "The length of `ptrs` must be equal the number of rows plus 1."
210 );
211 assert!(
212 are_in_upper_bound(indcs.as_slice(), &dim.cols()),
213 "Column indices must be less than the number of columns."
214 );
215 assert!(
216 ptrs
217 .as_slice()
218 .windows(2)
219 .all(|x| does_not_have_duplicates(&indcs.as_slice()[x[0]..x[1]])),
220 "Column indices of a row must be unique."
221 );
222 assert!(
223 *ptrs.as_slice().last().unwrap() == data.as_slice().len(),
224 "Rows length must end with the nnz."
225 );
226 assert!(
227 ptrs.as_slice().windows(2).all(|x| x[0] <= x[1]),
228 "Rows length must be in ascending order."
229 );
230 unsafe { Self::new_unchecked(shape, data, indcs, ptrs) }
231 }
232
233 /// A faster and unsafe version of [`new`](#method.new).
234 pub unsafe fn new_unchecked(shape: [usize; 2], data: DS, indcs: US, ptrs: US) -> Self {
235 CsrMatrix {
236 data,
237 dim: shape.into(),
238 indcs,
239 ptrs,
240 }
241 }
242
243 /// Converts the inner storage to a generic immutable slice storage.
244 ///
245 /// # Examples
246 ///
247 /// ```rust
248 /// use mop_structs::{
249 /// doc_tests::csr_matrix_array,
250 /// matrix::csr_matrix::CsrMatrixRef
251 /// };
252 /// assert_eq!(
253 /// csr_matrix_array().as_ref(),
254 /// CsrMatrixRef::new(
255 /// [4, 5],
256 /// &[1, 2, 3, 4, 5],
257 /// &[0, 2, 1, 3, 4],
258 /// &[0, 2, 4, 4, 5]
259 /// )
260 /// );
261 /// ```
262 pub fn as_ref(&self) -> CsrMatrixRef<'_, DS::Item> {
263 CsrMatrix::new(
264 [self.dim.rows(), self.dim.cols()],
265 self.data.as_slice(),
266 self.indcs.as_slice(),
267 self.ptrs.as_slice(),
268 )
269 }
270
271 /// Returns an immutable reference to the data elements.
272 ///
273 /// # Examples
274 ///
275 /// ```rust
276 /// use mop_structs::doc_tests::csr_matrix_array;
277 /// let a = csr_matrix_array();
278 /// assert_eq!(a.data(), &[1, 2, 3, 4, 5]);
279 /// ```
280 pub fn data(&self) -> &[DS::Item] {
281 self.data.as_slice()
282 }
283
284 /// Returns an immutable reference to the column indices of the data elements.
285 ///
286 /// # Examples
287 ///
288 /// ```rust
289 /// use mop_structs::doc_tests::csr_matrix_array;
290 /// let a = csr_matrix_array();
291 /// assert_eq!(a.indcs(), &[0, 2, 1, 3, 4]);
292 /// ```
293 pub fn indcs(&self) -> &[usize] {
294 &self.indcs.as_slice()
295 }
296
297 /// Returns the Number of NonZero elements.
298 ///
299 /// # Examples
300 ///
301 /// ```rust
302 /// use mop_structs::doc_tests::csr_matrix_array;
303 /// assert_eq!(csr_matrix_array().nnz(), 5);
304 /// ```
305 #[inline]
306 pub fn nnz(&self) -> usize {
307 self.data().len()
308 }
309
310 /// Returns an immutable reference to the rows length.
311 ///
312 /// # Examples
313 ///
314 /// ```rust
315 /// use mop_structs::doc_tests::csr_matrix_array;
316 /// let a = csr_matrix_array();
317 /// assert_eq!(a.ptrs(), &[0, 2, 4, 4, 5]);
318 /// ```
319 pub fn ptrs(&self) -> &[usize] {
320 &self.ptrs.as_slice()
321 }
322
323 /// Returns an immutable reference to the row at the `row_idx` row.
324 ///
325 /// # Examples
326 ///
327 /// ```rust
328 /// use mop_structs::{
329 /// doc_tests::csr_matrix_array,
330 /// vec::css::CssSlice
331 /// };
332 /// assert_eq!(
333 /// csr_matrix_array().row(0),
334 /// CssSlice::new(5, &[1, 2], &[0, 2])
335 /// );
336 /// ```
337 ///
338 /// # Assertions
339 ///
340 /// * `row_idx` must be less than the number of rows.
341 ///
342 /// ```should_panic
343 /// use mop_structs::doc_tests::csr_matrix_array;
344 /// let _ = csr_matrix_array().row(10);
345 /// ```
346 pub fn row(&self, row_idx: usize) -> CssSlice<'_, DS::Item> {
347 let range = self.ptr_range_of_row(row_idx);
348 CssSlice::new(
349 self.dim.cols(),
350 &self.data.as_slice()[range.clone()],
351 &self.indcs.as_slice()[range],
352 )
353 }
354
355 /// An iterator that returns immutable references of all rows.
356 ///
357 /// # Examples
358 ///
359 /// ```rust
360 /// use mop_structs::{
361 /// doc_tests::csr_matrix_array,
362 /// vec::css::CssSlice
363 /// };
364 /// let mut a = csr_matrix_array();
365 /// let mut li = a.row_iter();
366 /// li.next();
367 /// assert_eq!(li.next(), Some(CssSlice::new(5, &[3, 4], &[1, 3])));
368 /// li.next();
369 /// li.next();
370 /// assert_eq!(li.next(), None);
371 /// ```
372 pub fn row_iter(&self) -> CsrMatrixRowIter<'_, DS::Item> {
373 CsrMatrixRowIter::new(
374 [self.rows(), self.cols()],
375 self.data().as_ptr(),
376 self.indcs(),
377 self.ptrs(),
378 )
379 }
380
381 /// An parallel iterator that returns immutable references of all rows.
382 ///
383 /// # Examples
384 ///
385 /// ```rust
386 /// use mop_structs::{
387 /// doc_tests::csr_matrix_array,
388 /// prelude::*
389 /// };
390 /// let a = csr_matrix_array();
391 /// a.row_par_iter().enumerate().for_each(|(idx, x)| assert_eq!(x, a.row(idx)));
392 /// ```
393 #[cfg(feature = "rayon")]
394 pub fn row_par_iter(
395 &self,
396 ) -> crate::utils::ParallelIteratorWrapper<CsrMatrixRowIter<'_, DS::Item>> {
397 crate::utils::ParallelIteratorWrapper(self.row_iter())
398 }
399
400 /// If any, returns an immutable reference to the element at the `row_idx` row and
401 /// `col_idx` column.
402 ///
403 /// # Examples
404 ///
405 /// ```rust
406 /// use mop_structs::doc_tests::csr_matrix_array;
407 /// let a = csr_matrix_array();
408 /// assert_eq!(a.value(0, 0), Some(&1));
409 /// assert_eq!(a.value(1, 0), None);
410 /// ```
411 ///
412 /// # Assertions
413 ///
414 /// * `row_idx` must be less than the number of rows and `col_idx` must be less
415 /// than the number of columns.
416 ///
417 /// ```should_panic
418 /// use mop_structs::doc_tests::csr_matrix_array;
419 /// let _ = csr_matrix_array().value(10, 10);
420 /// ```
421 pub fn value(&self, row_idx: usize, col_idx: usize) -> Option<&DS::Item> {
422 self
423 .data_idx_of_coords(row_idx, col_idx)
424 .map(|x| &self.data()[x])
425 }
426
427 #[inline]
428 fn data_idx_of_coords(&self, row_idx: usize, col_idx: usize) -> Option<usize> {
429 assert!(row_idx < self.rows() && col_idx < self.cols());
430 let row_start_ptr = self.ptrs()[row_idx];
431 let row_end_ptr = self.ptrs()[row_idx + 1];
432 if let Ok(x) = self.indcs()[row_start_ptr..row_end_ptr].binary_search(&col_idx) {
433 Some(row_start_ptr + x)
434 } else {
435 None
436 }
437 }
438
439 #[inline]
440 fn ptr_range_of_row(&self, row_idx: usize) -> Range<usize> {
441 assert!(
442 row_idx < self.dim.rows(),
443 "`row_idx` must be less than the number of rows."
444 );
445 let lower_bound = self.ptrs()[row_idx] - self.ptrs()[0];
446 let upper_bound = self.ptrs()[row_idx + 1] - self.ptrs()[0];
447 lower_bound..upper_bound
448 }
449}
450
451#[cfg(feature = "rand")]
452impl<DS, US> CsrMatrix<DS, US>
453where
454 DS: StDenseStoRef,
455 US: StDenseStoRef<Item = usize>,
456{
457}
458
459impl<DS, US> CsrMatrix<DS, US>
460where
461 DS: StDenseStoMut,
462 US: StDenseStoRef<Item = usize>,
463{
464 /// Returns an mutable reference to the data elements.
465 ///
466 /// # Examples
467 ///
468 /// ```rust
469 /// use mop_structs::doc_tests::csr_matrix_array;
470 /// let mut a = csr_matrix_array();
471 /// assert_eq!(a.data_mut(), &mut [1, 2, 3, 4, 5]);
472 /// ```
473 pub fn data_mut(&mut self) -> &mut [DS::Item] {
474 self.data.as_mut_slice()
475 }
476
477 /// In a single borrow of `Self`, returns borrows for the most imporant inner
478 /// parts (&mut data, &indices and &pointers).
479 pub fn parts_with_data_mut(&mut self) -> (&mut [DS::Item], &[usize], &[usize]) {
480 (
481 self.data.as_mut_slice(),
482 self.indcs.as_slice(),
483 self.ptrs.as_slice(),
484 )
485 }
486
487 /// Returns an mutable reference to the row at the `row_idx` position.
488 ///
489 /// # Examples
490 ///
491 /// ```rust
492 /// use mop_structs::{
493 /// doc_tests::csr_matrix_array,
494 /// vec::css::CssSliceMut
495 /// };
496 /// assert_eq!(
497 /// csr_matrix_array().row_mut(1),
498 /// CssSliceMut::new(5, &mut [3, 4], &[1, 3])
499 /// );
500 /// ```
501 ///
502 /// # Assertions
503 ///
504 /// * `row_idx` must be less than the number of rows.
505 ///
506 /// ```should_panic
507 /// use mop_structs::doc_tests::csr_matrix_array;
508 /// let _ = csr_matrix_array().row_mut(10);
509 /// ```
510 pub fn row_mut(&mut self, row_idx: usize) -> CssSliceMut<'_, DS::Item> {
511 let range = self.ptr_range_of_row(row_idx);
512 CssSliceMut::new(
513 self.dim.cols(),
514 &mut self.data.as_mut_slice()[range.clone()],
515 &self.indcs.as_slice()[range],
516 )
517 }
518
519 /// An iterator that returns mutable references of all rows.
520 ///
521 /// # Examples
522 ///
523 /// ```rust
524 /// use mop_structs::{
525 /// doc_tests::csr_matrix_array,
526 /// vec::css::CssSliceMut
527 /// };
528 /// let mut a = csr_matrix_array();
529 /// let mut li = a.row_iter_mut();
530 /// li.next();
531 /// assert_eq!(li.next(), Some(CssSliceMut::new(5, &mut [3, 4], &[1, 3])));
532 /// li.next();
533 /// li.next();
534 /// assert_eq!(li.next(), None);
535 /// ```
536 pub fn row_iter_mut(&mut self) -> CsrMatrixRowIterMut<'_, DS::Item> {
537 CsrMatrixRowIterMut::new(
538 [self.rows(), self.cols()],
539 self.data_mut().as_mut_ptr(),
540 self.indcs(),
541 self.ptrs(),
542 )
543 }
544
545 /// An parallel iterator that returns mutable references of all rows.
546 ///
547 /// # Examples
548 ///
549 /// ```rust
550 /// use mop_structs::{
551 /// doc_tests::csr_matrix_array,
552 /// prelude::*
553 /// };
554 /// let mut a = csr_matrix_array();
555 /// a.row_par_iter_mut().for_each(|mut a| a.data_mut().iter_mut().for_each(|b| *b += 2));
556 /// assert_eq!(a.data(), &[3, 4, 5, 6, 7]);
557 /// ```
558 #[cfg(feature = "rayon")]
559 pub fn row_par_iter_mut(
560 &mut self,
561 ) -> crate::utils::ParallelIteratorWrapper<CsrMatrixRowIterMut<'_, DS::Item>> {
562 crate::utils::ParallelIteratorWrapper(self.row_iter_mut())
563 }
564
565 pub fn split_at_mut(
566 &mut self,
567 row_idx: usize,
568 ) -> (CssSliceMut<'_, DS::Item>, CssSliceMut<'_, DS::Item>) {
569 assert!(row_idx <= self.rows());
570 let split_at = self.ptrs()[row_idx];
571 let (first_data, second_data) = self.data.as_mut_slice().split_at_mut(split_at);
572 let first = CssSliceMut::new(
573 self.dim.cols(),
574 first_data,
575 &self.indcs.as_slice()[0..split_at],
576 );
577 let second = CssSliceMut::new(
578 self.dim.cols(),
579 second_data,
580 &self.indcs.as_slice()[split_at..],
581 );
582 (first, second)
583 }
584
585 /// If any, returns an mutable reference to the element at the `row_idx` row and
586 /// `col_idx` column.
587 ///
588 /// # Examples
589 ///
590 /// ```rust
591 /// use mop_structs::doc_tests::csr_matrix_array;
592 /// let mut a = csr_matrix_array();
593 /// assert_eq!(a.value_mut(0, 0), Some(&mut 1));
594 /// assert_eq!(a.value_mut(1, 0), None);
595 /// ```
596 ///
597 /// # Assertions
598 ///
599 /// * `row_idx` must be less than the number of rows and `col_idx` must be less
600 /// than the number of columns.
601 ///
602 /// ```should_panic
603 /// use mop_structs::doc_tests::csr_matrix_array;
604 /// let _ = csr_matrix_array().value_mut(10, 10);
605 /// ```
606 pub fn value_mut(&mut self, row_idx: usize, col_idx: usize) -> Option<&mut DS::Item> {
607 if let Some(x) = self.data_idx_of_coords(row_idx, col_idx) {
608 Some(&mut self.data_mut()[x])
609 } else {
610 None
611 }
612 }
613
614 /// Swaps two elements of two distinct coordinates.
615 ///
616 /// # Examples
617 ///
618 /// ```rust
619 /// use mop_structs::doc_tests::csr_matrix_array;
620 /// let mut a = csr_matrix_array();
621 /// a.swap([0, 0], [3, 4]);
622 /// assert_eq!(a.data(), &[5, 2, 3, 4, 1]);
623 /// ```
624 ///
625 /// # Assertions
626 ///
627 /// * `a` row must be less than the number of rows and `a` column must be
628 /// less than the number of columns.
629 ///
630 /// ```should_panic
631 /// use mop_structs::doc_tests::csr_matrix_array;
632 /// let _ = csr_matrix_array().swap([10, 10], [0, 0]);
633 /// ```
634 ///
635 /// * `b` row must be less than the number of rows and `b` column must be
636 /// less than the number of columns.
637 ///
638 /// ```should_panic
639 /// use mop_structs::doc_tests::csr_matrix_array;
640 /// let _ = csr_matrix_array().swap([0, 0], [10, 10]);
641 /// ```
642 ///
643 /// * `a` or `b` coordinates must point to existing elements.
644 ///
645 /// ```should_panic
646 /// use mop_structs::doc_tests::csr_matrix_array;
647 /// let _ = csr_matrix_array().swap([1, 1], [2, 2]);
648 /// ```
649 pub fn swap(&mut self, a: [usize; 2], b: [usize; 2]) {
650 let a_data_idx = self.data_idx_of_coords(a[0], a[1]).unwrap();
651 let b_data_idx = self.data_idx_of_coords(b[0], b[1]).unwrap();
652 self.data_mut().swap(a_data_idx, b_data_idx);
653 }
654}
655
656impl<DS, US> CsrMatrix<DS, US>
657where
658 DS: DynDenseStoRef,
659 US: DynDenseStoRef<Item = usize>,
660{
661 /// Returns the current rows capacity.
662 ///
663 /// # Examples
664 ///
665 /// ```rust
666 /// use mop_structs::doc_tests::csr_matrix_vec_array;
667 /// assert_eq!(csr_matrix_vec_array().rows_capacity(), 4);
668 /// ```
669 #[inline]
670 pub fn rows_capacity(&self) -> usize {
671 self.ptrs.capacity() - 1
672 }
673}
674
675impl<DS, US> CsrMatrix<DS, US>
676where
677 DS: DynDenseStoMut,
678 US: DynDenseStoMut<Item = usize>,
679{
680 /// Removes all values and sets the number of rows to zero but doesn't modify the
681 /// number of columns.
682 ///
683 /// Note that this method has no effect on the allocated capacity.
684 ///
685 /// # Examples
686 ///
687 /// ```rust
688 /// use mop_structs::{
689 /// doc_tests::csr_matrix_vec_array,
690 /// matrix::csr_matrix::CsrMatrixRef,
691 /// prelude::*
692 /// };
693 /// let mut a = csr_matrix_vec_array();
694 /// a.clear();
695 /// assert_eq!(a.as_ref(), CsrMatrixRef::new(
696 /// [0, a.cols()],
697 /// &[],
698 /// &[],
699 /// &[0]
700 /// ));
701 /// ```
702 pub fn clear(&mut self) {
703 self.data.clear();
704 self.indcs.clear();
705 self.ptrs.clear();
706 self.ptrs.push(0);
707 *self.dim.rows_mut() = 0;
708 }
709
710 pub fn extend(&mut self, other: &Self)
711 where
712 DS::Item: Copy,
713 US::Item: Copy,
714 {
715 assert!(
716 self.cols() == other.cols(),
717 "The number of columns of `Self` must be equal the number of columns of `other`."
718 );
719 let mut current_ptr = *self.ptrs.as_slice().last().unwrap();
720 let mut last_other_ptr = *other.ptrs().first().unwrap();
721 other.ptrs().iter().skip(1).for_each(|&x| {
722 current_ptr += x - last_other_ptr;
723 last_other_ptr = x;
724 self.ptrs.push(current_ptr);
725 });
726 self.data.extend(other.data());
727 self.indcs.extend(other.indcs());
728 *self.dim.rows_mut() += other.rows();
729 }
730
731 /// See [`CsrMatrixRowConstructor`](CsrMatrixRowConstructor) for more information.
732 pub fn row_constructor(&mut self) -> CsrMatrixRowConstructor<'_, DS, US> {
733 CsrMatrixRowConstructor::new(
734 &mut self.dim,
735 &mut self.data,
736 &mut self.indcs,
737 &mut self.ptrs,
738 )
739 }
740
741 pub fn truncate(&mut self, until_row_idx: usize) {
742 self.data.truncate(until_row_idx);
743 self.indcs.truncate(until_row_idx);
744 self.ptrs.truncate(until_row_idx + 1);
745 *self.dim.rows_mut() = until_row_idx;
746 }
747}
748
749impl<DS, US> Matrix for CsrMatrix<DS, US> {
750 /// The number of columns.
751 ///
752 /// # Examples
753 ///
754 /// ```rust
755 /// use mop_structs::{doc_tests::csr_matrix_array, prelude::*};
756 /// assert_eq!(csr_matrix_array().cols(), 5);
757 /// ```
758 #[inline]
759 fn cols(&self) -> usize {
760 self.dim.cols()
761 }
762
763 /// The number of rows.
764 ///
765 /// # Examples
766 ///
767 /// ```rust
768 /// use mop_structs::{doc_tests::csr_matrix_array, prelude::*};
769 /// assert_eq!(csr_matrix_array().rows(), 4);
770 /// ```
771 #[inline]
772 fn rows(&self) -> usize {
773 self.dim.rows()
774 }
775}
776
777#[cfg(all(feature = "quickcheck", feature = "rand"))]
778use mop_common_deps::{
779 quickcheck::{Arbitrary, Gen},
780 rand::{
781 distributions::{Distribution, Standard},
782 Rng,
783 },
784};
785#[cfg(all(feature = "quickcheck", feature = "rand"))]
786impl<T> Arbitrary for CsrMatrixVec<T>
787where
788 Standard: Distribution<T>,
789 T: Arbitrary,
790{
791 #[inline]
792 fn arbitrary<G>(g: &mut G) -> Self
793 where
794 G: Gen,
795 {
796 let rows = g.gen_range(0, g.size());
797 let cols = g.gen_range(0, g.size());
798 let nnz = g.gen_range(0, rows * cols + 1);
799 CsrMatrixVec::new_rnd([rows, cols], nnz, g, |g, _| g.gen())
800 }
801}