From ff435110b97520702fb24bd94884cd7fc5e85412 Mon Sep 17 00:00:00 2001 From: Andreas Longva Date: Thu, 24 Sep 2020 09:55:09 +0200 Subject: [PATCH] Implement CSR::disassemble and SparsityPattern::disassemble --- nalgebra-sparse/src/csr.rs | 57 +++++++++++++++++++++++++++++++++- nalgebra-sparse/src/lib.rs | 2 ++ nalgebra-sparse/src/pattern.rs | 23 ++++++++++++++ 3 files changed, 81 insertions(+), 1 deletion(-) diff --git a/nalgebra-sparse/src/csr.rs b/nalgebra-sparse/src/csr.rs index e8d7d447..8c4be726 100644 --- a/nalgebra-sparse/src/csr.rs +++ b/nalgebra-sparse/src/csr.rs @@ -240,6 +240,61 @@ impl CsrMatrix { remaining_values: self.values.as_mut_ptr() } } + + /// Returns the underlying vector containing the values for the explicitly stored entries. + pub fn take_values(self) -> Vec { + self.values + } + + /// Disassembles the CSR matrix into its underlying offset, index and value arrays. + /// + /// If the matrix contains the sole reference to the sparsity pattern, + /// then the data is returned as-is. Otherwise, the sparsity pattern is cloned. + /// + /// Examples + /// -------- + /// + /// ``` + /// # use nalgebra_sparse::csr::CsrMatrix; + /// let row_offsets = vec![0, 2, 3, 4]; + /// let col_indices = vec![0, 2, 1, 0]; + /// let values = vec![1, 2, 3, 4]; + /// let mut csr = CsrMatrix::try_from_csr_data( + /// 3, + /// 4, + /// row_offsets.clone(), + /// col_indices.clone(), + /// values.clone()) + /// .unwrap(); + /// let (row_offsets2, col_indices2, values2) = csr.disassemble(); + /// assert_eq!(row_offsets2, row_offsets); + /// assert_eq!(col_indices2, col_indices); + /// assert_eq!(values2, values); + /// ``` + pub fn disassemble(self) -> (Vec, Vec, Vec) { + // Take an Arc to the pattern, which might be the sole reference to the data after + // taking the values. This is important, because it might let us avoid cloning the data + // further below. + let pattern = self.pattern(); + let values = self.take_values(); + + // Try to take the pattern out of the `Arc` if possible, + // otherwise clone the pattern. + let owned_pattern = Arc::try_unwrap(pattern) + .unwrap_or_else(|arc| SparsityPattern::clone(&*arc)); + let (offsets, indices) = owned_pattern.disassemble(); + + (offsets, indices, values) + } + + /// Returns the underlying sparsity pattern. + /// + /// The sparsity pattern is stored internally inside an `Arc`. This allows users to re-use + /// the same sparsity pattern for multiple matrices without storing the same pattern multiple + /// times in memory. + pub fn pattern(&self) -> Arc { + Arc::clone(&self.sparsity_pattern) + } } impl CsrMatrix { @@ -247,7 +302,7 @@ impl CsrMatrix { /// bounds. /// /// If the indices are in bounds, but no explicitly stored entry is associated with it, - /// `T::zero()` is returned. Note that this methods offers no way of distinguishing + /// `T::zero()` is returned. Note that this method offers no way of distinguishing /// explicitly stored zero entries from zero values that are only implicitly represented. /// /// Each call to this function incurs the cost of a binary search among the explicitly diff --git a/nalgebra-sparse/src/lib.rs b/nalgebra-sparse/src/lib.rs index 36b9bc40..872126a8 100644 --- a/nalgebra-sparse/src/lib.rs +++ b/nalgebra-sparse/src/lib.rs @@ -15,6 +15,7 @@ //! - [x] Construct from valid offset + index data //! - [ ] Construct from unsorted (but otherwise valid) offset + index data //! - [x] Iterate over entries (i, j) in the pattern +//! - [x] "Disassemble" the sparsity pattern into the raw index data arrays. //! - CSR matrix type. Functionality: //! - [x] Access to CSR data as slices. //! - [x] Return number of nnz @@ -24,6 +25,7 @@ //! - [ ] Construct from unsorted CSR data //! - [x] Iterate over entries (i, j, v) in the matrix (+mutable). //! - [x] Iterate over rows in the matrix (+ mutable). +//! - [x] "Disassemble" the CSR matrix into the raw CSR data arrays. //! //! - CSC matrix type. Functionality: //! - Same as CSR, but with columns instead of rows. diff --git a/nalgebra-sparse/src/pattern.rs b/nalgebra-sparse/src/pattern.rs index 4f78fbb4..54e0f2e8 100644 --- a/nalgebra-sparse/src/pattern.rs +++ b/nalgebra-sparse/src/pattern.rs @@ -170,6 +170,29 @@ impl SparsityPattern { pub fn entries(&self) -> SparsityPatternIter { SparsityPatternIter::from_pattern(self) } + + /// Returns the raw offset and index data for the sparsity pattern. + /// + /// Examples + /// -------- + /// + /// ``` + /// # use nalgebra_sparse::pattern::SparsityPattern; + /// let offsets = vec![0, 2, 3, 4]; + /// let minor_indices = vec![0, 2, 1, 0]; + /// let pattern = SparsityPattern::try_from_offsets_and_indices( + /// 3, + /// 4, + /// offsets.clone(), + /// minor_indices.clone()) + /// .unwrap(); + /// let (offsets2, minor_indices2) = pattern.disassemble(); + /// assert_eq!(offsets2, offsets); + /// assert_eq!(minor_indices2, minor_indices); + /// ``` + pub fn disassemble(self) -> (Vec, Vec) { + (self.major_offsets, self.minor_indices) + } } /// Error type for `SparsityPattern` format errors.