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
use crate::{ dim::Dim, prelude::DynDenseStoMut, utils::{are_in_upper_bound, does_not_have_duplicates}, vec::css::CssSlice, }; /// Constructs a new valid row in a easy and interactive manner, abstracting away the complexity /// of the CSR format. /// /// This struct may panic when out of scope. Please see the `Drop` documentation in /// the [`Trait Implementations`](#implementations) section for more information. #[derive(Debug, PartialEq)] pub struct CsrMatrixRowConstructor<'a, DS, US> { row_nnz: usize, data: &'a mut DS, dim: &'a mut Dim<[usize; 2]>, indcs: &'a mut US, ptrs: &'a mut US, } impl<'a, DS, US> CsrMatrixRowConstructor<'a, DS, US> where DS: DynDenseStoMut, US: DynDenseStoMut<Item = usize>, { pub(crate) fn new( dim: &'a mut Dim<[usize; 2]>, data: &'a mut DS, indcs: &'a mut US, ptrs: &'a mut US, ) -> Self { CsrMatrixRowConstructor { row_nnz: 0, data, dim, indcs, ptrs, } } /// Commits the row construction, modifying the internal structure. /// /// # Examples /// /// ```rust /// use mop_structs::{ /// doc_tests::csr_matrix_empty_vec_array, /// matrix::csr_matrix::CsrMatrixRef /// }; /// let mut a = csr_matrix_empty_vec_array(); /// a.row_constructor().commit(); /// assert_eq!(a.as_ref(), CsrMatrixRef::new([1, 5], &[], &[], &[0, 0])); /// ``` /// /// # Assertions /// /// * Inserted indices must be less than the number of columns of `Self`. /// /// ```should_panic /// use mop_structs::doc_tests::csr_matrix_empty_vec_array; /// let mut a = csr_matrix_empty_vec_array(); /// a.row_constructor().set_value(10, 1).commit(); /// ``` /// /// * Inserted indices must be unique. /// /// ```should_panic /// use mop_structs::doc_tests::csr_matrix_empty_vec_array; /// let mut a = csr_matrix_empty_vec_array(); /// a.row_constructor().set_value(1, 1).set_value(1, 10).commit(); /// ``` pub fn commit(self) { let last_ptr = *self.ptrs.as_slice().last().unwrap(); let inserted_indcs = &self.indcs.as_slice()[last_ptr..]; assert!( are_in_upper_bound(inserted_indcs, &self.dim.cols()), "Inserted indices must be less than the number of columns of `Self`" ); assert!( does_not_have_duplicates(inserted_indcs), "Inserted indices must be unique." ); unsafe { self.commit_unchecked() }; } /// A faster and unsafe version of [`commit`](#method.commit). pub unsafe fn commit_unchecked(mut self) { let last_ptr = *self.ptrs.as_slice().last().unwrap(); self.ptrs.push(last_ptr + self.row_nnz); *self.dim.rows_mut() += 1; self.row_nnz = 0; } /// Copies all values of `row` into the current row. /// /// # Examples /// /// ```rust /// use mop_structs::{ /// doc_tests::csr_matrix_empty_vec_array, /// matrix::csr_matrix::CsrMatrixRef, /// vec::css::CssSlice /// }; /// let mut a = csr_matrix_empty_vec_array(); /// let b = CssSlice::new(5, &[1, 2], &[0, 1]); /// a.row_constructor().copy_values_from_row(&b).commit(); /// assert_eq!(a.as_ref(), CsrMatrixRef::new( /// [1, 5], /// &[1, 2], /// &[0, 1], /// &[0, 2] /// )); /// ``` pub fn copy_values_from_row(mut self, row: &CssSlice<'_, DS::Item>) -> Self where DS::Item: Copy, { self.row_nnz += row.nnz(); self.data.extend(row.data()); self.indcs.extend(row.indcs()); self } /// Sets a new value in the current row and column index `column_idx`. /// /// # Examples /// /// ```rust /// use mop_structs::{ /// doc_tests::csr_matrix_empty_vec_array, /// matrix::csr_matrix::CsrMatrixRef /// }; /// let mut a = csr_matrix_empty_vec_array(); /// a.row_constructor().set_value(1, 1).commit(); /// assert_eq!(a.as_ref(), CsrMatrixRef::new([1, 5], &[1], &[1], &[0, 1])); /// ``` pub fn set_value(mut self, column_idx: usize, value: DS::Item) -> Self { self.row_nnz += 1; self.data.push(value); self.indcs.push(column_idx); self } } impl<'a, DS, US> Drop for CsrMatrixRowConstructor<'a, DS, US> { /// Some measures are taken to ensure the CSR format and avoid unexpected runtime behavior. /// /// # Assertions /// /// * Every single nonempty instance of `CsrRowLayerConstructor` must end with a call to /// the `commit` method. /// /// ```should_panic /// use mop_structs::doc_tests::csr_matrix_empty_vec_array; /// let mut a = csr_matrix_empty_vec_array(); /// a.row_constructor().set_value(1, 1); /// ``` fn drop(&mut self) { if self.row_nnz > 0 { panic!( "Every single nonempty instance of `CsrMatrixRowConstructor` must end with a call to the `commit` method." ); } } }