nalgebra_sparse/csc.rs
1//! An implementation of the CSC sparse matrix format.
2//!
3//! This is the module-level documentation. See [`CscMatrix`] for the main documentation of the
4//! CSC implementation.
5
6#[cfg(feature = "serde-serialize")]
7mod csc_serde;
8
9use crate::cs;
10use crate::cs::{CsLane, CsLaneIter, CsLaneIterMut, CsLaneMut, CsMatrix};
11use crate::csr::CsrMatrix;
12use crate::pattern::{SparsityPattern, SparsityPatternFormatError, SparsityPatternIter};
13use crate::{SparseEntry, SparseEntryMut, SparseFormatError, SparseFormatErrorKind};
14
15use nalgebra::Scalar;
16use num_traits::One;
17use std::slice::{Iter, IterMut};
18
19/// A CSC representation of a sparse matrix.
20///
21/// The Compressed Sparse Column (CSC) format is well-suited as a general-purpose storage format
22/// for many sparse matrix applications.
23///
24/// # Usage
25///
26/// ```
27/// use nalgebra_sparse::coo::CooMatrix;
28/// use nalgebra_sparse::csc::CscMatrix;
29/// use nalgebra::{DMatrix, Matrix3x4};
30/// use matrixcompare::assert_matrix_eq;
31///
32/// // The sparsity patterns of CSC matrices are immutable. This means that you cannot dynamically
33/// // change the sparsity pattern of the matrix after it has been constructed. The easiest
34/// // way to construct a CSC matrix is to first incrementally construct a COO matrix,
35/// // and then convert it to CSC.
36///
37/// let mut coo = CooMatrix::<f64>::new(3, 3);
38/// coo.push(2, 0, 1.0);
39/// let csc = CscMatrix::from(&coo);
40///
41/// // Alternatively, a CSC matrix can be constructed directly from raw CSC data.
42/// // Here, we construct a 3x4 matrix
43/// let col_offsets = vec![0, 1, 3, 4, 5];
44/// let row_indices = vec![0, 0, 2, 2, 0];
45/// let values = vec![1.0, 2.0, 3.0, 4.0, 5.0];
46///
47/// // The dense representation of the CSC data, for comparison
48/// let dense = Matrix3x4::new(1.0, 2.0, 0.0, 5.0,
49/// 0.0, 0.0, 0.0, 0.0,
50/// 0.0, 3.0, 4.0, 0.0);
51///
52/// // The constructor validates the raw CSC data and returns an error if it is invalid.
53/// let csc = CscMatrix::try_from_csc_data(3, 4, col_offsets, row_indices, values)
54/// .expect("CSC data must conform to format specifications");
55/// assert_matrix_eq!(csc, dense);
56///
57/// // A third approach is to construct a CSC matrix from a pattern and values. Sometimes this is
58/// // useful if the sparsity pattern is constructed separately from the values of the matrix.
59/// let (pattern, values) = csc.into_pattern_and_values();
60/// let csc = CscMatrix::try_from_pattern_and_values(pattern, values)
61/// .expect("The pattern and values must be compatible");
62///
63/// // Once we have constructed our matrix, we can use it for arithmetic operations together with
64/// // other CSC matrices and dense matrices/vectors.
65/// let x = csc;
66/// # #[allow(non_snake_case)]
67/// let xTx = x.transpose() * &x;
68/// let z = DMatrix::from_fn(4, 8, |i, j| (i as f64) * (j as f64));
69/// let w = 3.0 * xTx * z;
70///
71/// // Although the sparsity pattern of a CSC matrix cannot be changed, its values can.
72/// // Here are two different ways to scale all values by a constant:
73/// let mut x = x;
74/// x *= 5.0;
75/// x.values_mut().iter_mut().for_each(|x_i| *x_i *= 5.0);
76/// ```
77///
78/// # Format
79///
80/// An `m x n` sparse matrix with `nnz` non-zeros in CSC format is represented by the
81/// following three arrays:
82///
83/// - `col_offsets`, an array of integers with length `n + 1`.
84/// - `row_indices`, an array of integers with length `nnz`.
85/// - `values`, an array of values with length `nnz`.
86///
87/// The relationship between the arrays is described below.
88///
89/// - Each consecutive pair of entries `col_offsets[j] .. col_offsets[j + 1]` corresponds to an
90/// offset range in `row_indices` that holds the row indices in column `j`.
91/// - For an entry represented by the index `idx`, `row_indices[idx]` stores its column index and
92/// `values[idx]` stores its value.
93///
94/// The following invariants must be upheld and are enforced by the data structure:
95///
96/// - `col_offsets[0] == 0`
97/// - `col_offsets[m] == nnz`
98/// - `col_offsets` is monotonically increasing.
99/// - `0 <= row_indices[idx] < m` for all `idx < nnz`.
100/// - The row indices associated with each column are monotonically increasing (see below).
101///
102/// The CSC format is a standard sparse matrix format (see [Wikipedia article]). The format
103/// represents the matrix in a column-by-column fashion. The entries associated with column `j` are
104/// determined as follows:
105///
106/// ```
107/// # let col_offsets: Vec<usize> = vec![0, 0];
108/// # let row_indices: Vec<usize> = vec![];
109/// # let values: Vec<i32> = vec![];
110/// # let j = 0;
111/// let range = col_offsets[j] .. col_offsets[j + 1];
112/// let col_j_rows = &row_indices[range.clone()];
113/// let col_j_vals = &values[range];
114///
115/// // For each pair (i, v) in (col_j_rows, col_j_vals), we obtain a corresponding entry
116/// // (i, j, v) in the matrix.
117/// assert_eq!(col_j_rows.len(), col_j_vals.len());
118/// ```
119///
120/// In the above example, for each column `j`, the row indices `col_j_cols` must appear in
121/// monotonically increasing order. In other words, they must be *sorted*. This criterion is not
122/// standard among all sparse matrix libraries, but we enforce this property as it is a crucial
123/// assumption for both correctness and performance for many algorithms.
124///
125/// Note that the CSR and CSC formats are essentially identical, except that CSC stores the matrix
126/// column-by-column instead of row-by-row like CSR.
127///
128/// [Wikipedia article]: https://en.wikipedia.org/wiki/Sparse_matrix#Compressed_sparse_column_(CSC_or_CCS)
129#[derive(Debug, Clone, PartialEq, Eq)]
130pub struct CscMatrix<T> {
131 // Cols are major, rows are minor in the sparsity pattern
132 pub(crate) cs: CsMatrix<T>,
133}
134
135impl<T> CscMatrix<T> {
136 /// Constructs a CSC representation of the (square) `n x n` identity matrix.
137 #[inline]
138 pub fn identity(n: usize) -> Self
139 where
140 T: Scalar + One,
141 {
142 Self {
143 cs: CsMatrix::identity(n),
144 }
145 }
146
147 /// Create a zero CSC matrix with no explicitly stored entries.
148 pub fn zeros(nrows: usize, ncols: usize) -> Self {
149 Self {
150 cs: CsMatrix::new(ncols, nrows),
151 }
152 }
153
154 /// Try to construct a CSC matrix from raw CSC data.
155 ///
156 /// It is assumed that each column contains unique and sorted row indices that are in
157 /// bounds with respect to the number of rows in the matrix. If this is not the case,
158 /// an error is returned to indicate the failure.
159 ///
160 /// An error is returned if the data given does not conform to the CSC storage format.
161 /// See the documentation for [`CscMatrix`] for more information.
162 pub fn try_from_csc_data(
163 num_rows: usize,
164 num_cols: usize,
165 col_offsets: Vec<usize>,
166 row_indices: Vec<usize>,
167 values: Vec<T>,
168 ) -> Result<Self, SparseFormatError> {
169 let pattern = SparsityPattern::try_from_offsets_and_indices(
170 num_cols,
171 num_rows,
172 col_offsets,
173 row_indices,
174 )
175 .map_err(pattern_format_error_to_csc_error)?;
176 Self::try_from_pattern_and_values(pattern, values)
177 }
178
179 /// Try to construct a CSC matrix from raw CSC data with unsorted row indices.
180 ///
181 /// It is assumed that each column contains unique row indices that are in
182 /// bounds with respect to the number of rows in the matrix. If this is not the case,
183 /// an error is returned to indicate the failure.
184 ///
185 /// An error is returned if the data given does not conform to the CSC storage format
186 /// with the exception of having unsorted row indices and values.
187 /// See the documentation for [`CscMatrix`] for more information.
188 pub fn try_from_unsorted_csc_data(
189 num_rows: usize,
190 num_cols: usize,
191 col_offsets: Vec<usize>,
192 mut row_indices: Vec<usize>,
193 mut values: Vec<T>,
194 ) -> Result<Self, SparseFormatError>
195 where
196 T: Scalar,
197 {
198 let result = cs::validate_and_optionally_sort_cs_data(
199 num_cols,
200 num_rows,
201 &col_offsets,
202 &mut row_indices,
203 Some(&mut values),
204 true,
205 );
206
207 match result {
208 Ok(()) => {
209 let pattern = unsafe {
210 SparsityPattern::from_offset_and_indices_unchecked(
211 num_cols,
212 num_rows,
213 col_offsets,
214 row_indices,
215 )
216 };
217 Self::try_from_pattern_and_values(pattern, values)
218 }
219 Err(err) => Err(err),
220 }
221 }
222
223 /// Try to construct a CSC matrix from a sparsity pattern and associated non-zero values.
224 ///
225 /// Returns an error if the number of values does not match the number of minor indices
226 /// in the pattern.
227 pub fn try_from_pattern_and_values(
228 pattern: SparsityPattern,
229 values: Vec<T>,
230 ) -> Result<Self, SparseFormatError> {
231 if pattern.nnz() == values.len() {
232 Ok(Self {
233 cs: CsMatrix::from_pattern_and_values(pattern, values),
234 })
235 } else {
236 Err(SparseFormatError::from_kind_and_msg(
237 SparseFormatErrorKind::InvalidStructure,
238 "Number of values and row indices must be the same",
239 ))
240 }
241 }
242
243 /// The number of rows in the matrix.
244 #[inline]
245 #[must_use]
246 pub fn nrows(&self) -> usize {
247 self.cs.pattern().minor_dim()
248 }
249
250 /// The number of columns in the matrix.
251 #[inline]
252 #[must_use]
253 pub fn ncols(&self) -> usize {
254 self.cs.pattern().major_dim()
255 }
256
257 /// The number of non-zeros in the matrix.
258 ///
259 /// Note that this corresponds to the number of explicitly stored entries, *not* the actual
260 /// number of algebraically zero entries in the matrix. Explicitly stored entries can still
261 /// be zero. Corresponds to the number of entries in the sparsity pattern.
262 #[inline]
263 #[must_use]
264 pub fn nnz(&self) -> usize {
265 self.pattern().nnz()
266 }
267
268 /// The column offsets defining part of the CSC format.
269 #[inline]
270 #[must_use]
271 pub fn col_offsets(&self) -> &[usize] {
272 self.pattern().major_offsets()
273 }
274
275 /// The row indices defining part of the CSC format.
276 #[inline]
277 #[must_use]
278 pub fn row_indices(&self) -> &[usize] {
279 self.pattern().minor_indices()
280 }
281
282 /// The non-zero values defining part of the CSC format.
283 #[inline]
284 #[must_use]
285 pub fn values(&self) -> &[T] {
286 self.cs.values()
287 }
288
289 /// Mutable access to the non-zero values.
290 #[inline]
291 pub fn values_mut(&mut self) -> &mut [T] {
292 self.cs.values_mut()
293 }
294
295 /// An iterator over non-zero triplets (i, j, v).
296 ///
297 /// The iteration happens in column-major fashion, meaning that j increases monotonically,
298 /// and i increases monotonically within each row.
299 ///
300 /// Examples
301 /// --------
302 /// ```
303 /// # use nalgebra_sparse::csc::CscMatrix;
304 /// let col_offsets = vec![0, 2, 3, 4];
305 /// let row_indices = vec![0, 2, 1, 0];
306 /// let values = vec![1, 3, 2, 4];
307 /// let mut csc = CscMatrix::try_from_csc_data(4, 3, col_offsets, row_indices, values)
308 /// .unwrap();
309 ///
310 /// let triplets: Vec<_> = csc.triplet_iter().map(|(i, j, v)| (i, j, *v)).collect();
311 /// assert_eq!(triplets, vec![(0, 0, 1), (2, 0, 3), (1, 1, 2), (0, 2, 4)]);
312 /// ```
313 pub fn triplet_iter(&self) -> CscTripletIter<'_, T> {
314 CscTripletIter {
315 pattern_iter: self.pattern().entries(),
316 values_iter: self.values().iter(),
317 }
318 }
319
320 /// A mutable iterator over non-zero triplets (i, j, v).
321 ///
322 /// Iteration happens in the same order as for [triplet_iter](#method.triplet_iter).
323 ///
324 /// Examples
325 /// --------
326 /// ```
327 /// # use nalgebra_sparse::csc::CscMatrix;
328 /// let col_offsets = vec![0, 2, 3, 4];
329 /// let row_indices = vec![0, 2, 1, 0];
330 /// let values = vec![1, 3, 2, 4];
331 /// // Using the same data as in the `triplet_iter` example
332 /// let mut csc = CscMatrix::try_from_csc_data(4, 3, col_offsets, row_indices, values)
333 /// .unwrap();
334 ///
335 /// // Zero out lower-triangular terms
336 /// csc.triplet_iter_mut()
337 /// .filter(|(i, j, _)| j < i)
338 /// .for_each(|(_, _, v)| *v = 0);
339 ///
340 /// let triplets: Vec<_> = csc.triplet_iter().map(|(i, j, v)| (i, j, *v)).collect();
341 /// assert_eq!(triplets, vec![(0, 0, 1), (2, 0, 0), (1, 1, 2), (0, 2, 4)]);
342 /// ```
343 pub fn triplet_iter_mut(&mut self) -> CscTripletIterMut<'_, T> {
344 let (pattern, values) = self.cs.pattern_and_values_mut();
345 CscTripletIterMut {
346 pattern_iter: pattern.entries(),
347 values_mut_iter: values.iter_mut(),
348 }
349 }
350
351 /// Return the column at the given column index.
352 ///
353 /// Panics
354 /// ------
355 /// Panics if column index is out of bounds.
356 #[inline]
357 #[must_use]
358 pub fn col(&self, index: usize) -> CscCol<'_, T> {
359 self.get_col(index).expect("Row index must be in bounds")
360 }
361
362 /// Mutable column access for the given column index.
363 ///
364 /// Panics
365 /// ------
366 /// Panics if column index is out of bounds.
367 #[inline]
368 pub fn col_mut(&mut self, index: usize) -> CscColMut<'_, T> {
369 self.get_col_mut(index)
370 .expect("Row index must be in bounds")
371 }
372
373 /// Return the column at the given column index, or `None` if out of bounds.
374 #[inline]
375 #[must_use]
376 pub fn get_col(&self, index: usize) -> Option<CscCol<'_, T>> {
377 self.cs.get_lane(index).map(|lane| CscCol { lane })
378 }
379
380 /// Mutable column access for the given column index, or `None` if out of bounds.
381 #[inline]
382 #[must_use]
383 pub fn get_col_mut(&mut self, index: usize) -> Option<CscColMut<'_, T>> {
384 self.cs.get_lane_mut(index).map(|lane| CscColMut { lane })
385 }
386
387 /// An iterator over columns in the matrix.
388 pub fn col_iter(&self) -> CscColIter<'_, T> {
389 CscColIter {
390 lane_iter: CsLaneIter::new(self.pattern(), self.values()),
391 }
392 }
393
394 /// A mutable iterator over columns in the matrix.
395 pub fn col_iter_mut(&mut self) -> CscColIterMut<'_, T> {
396 let (pattern, values) = self.cs.pattern_and_values_mut();
397 CscColIterMut {
398 lane_iter: CsLaneIterMut::new(pattern, values),
399 }
400 }
401
402 /// Disassembles the CSC matrix into its underlying offset, index and value arrays.
403 ///
404 /// If the matrix contains the sole reference to the sparsity pattern,
405 /// then the data is returned as-is. Otherwise, the sparsity pattern is cloned.
406 ///
407 /// Examples
408 /// --------
409 ///
410 /// ```
411 /// # use nalgebra_sparse::csc::CscMatrix;
412 /// let col_offsets = vec![0, 2, 3, 4];
413 /// let row_indices = vec![0, 2, 1, 0];
414 /// let values = vec![1, 3, 2, 4];
415 /// let mut csc = CscMatrix::try_from_csc_data(
416 /// 4,
417 /// 3,
418 /// col_offsets.clone(),
419 /// row_indices.clone(),
420 /// values.clone())
421 /// .unwrap();
422 /// let (col_offsets2, row_indices2, values2) = csc.disassemble();
423 /// assert_eq!(col_offsets2, col_offsets);
424 /// assert_eq!(row_indices2, row_indices);
425 /// assert_eq!(values2, values);
426 /// ```
427 pub fn disassemble(self) -> (Vec<usize>, Vec<usize>, Vec<T>) {
428 self.cs.disassemble()
429 }
430
431 /// Returns the sparsity pattern and values associated with this matrix.
432 pub fn into_pattern_and_values(self) -> (SparsityPattern, Vec<T>) {
433 self.cs.into_pattern_and_values()
434 }
435
436 /// Returns a reference to the sparsity pattern and a mutable reference to the values.
437 #[inline]
438 pub fn pattern_and_values_mut(&mut self) -> (&SparsityPattern, &mut [T]) {
439 self.cs.pattern_and_values_mut()
440 }
441
442 /// Returns a reference to the underlying sparsity pattern.
443 #[must_use]
444 pub fn pattern(&self) -> &SparsityPattern {
445 self.cs.pattern()
446 }
447
448 /// Reinterprets the CSC matrix as its transpose represented by a CSR matrix.
449 ///
450 /// This operation does not touch the CSC data, and is effectively a no-op.
451 pub fn transpose_as_csr(self) -> CsrMatrix<T> {
452 let (pattern, values) = self.cs.take_pattern_and_values();
453 CsrMatrix::try_from_pattern_and_values(pattern, values).unwrap()
454 }
455
456 /// Returns an entry for the given row/col indices, or `None` if the indices are out of bounds.
457 ///
458 /// Each call to this function incurs the cost of a binary search among the explicitly
459 /// stored row entries for the given column.
460 #[must_use]
461 pub fn get_entry(&self, row_index: usize, col_index: usize) -> Option<SparseEntry<'_, T>> {
462 self.cs.get_entry(col_index, row_index)
463 }
464
465 /// Returns a mutable entry for the given row/col indices, or `None` if the indices are out
466 /// of bounds.
467 ///
468 /// Each call to this function incurs the cost of a binary search among the explicitly
469 /// stored row entries for the given column.
470 pub fn get_entry_mut(
471 &mut self,
472 row_index: usize,
473 col_index: usize,
474 ) -> Option<SparseEntryMut<'_, T>> {
475 self.cs.get_entry_mut(col_index, row_index)
476 }
477
478 /// Returns an entry for the given row/col indices.
479 ///
480 /// Same as `get_entry`, except that it directly panics upon encountering row/col indices
481 /// out of bounds.
482 ///
483 /// Panics
484 /// ------
485 /// Panics if `row_index` or `col_index` is out of bounds.
486 #[must_use]
487 pub fn index_entry(&self, row_index: usize, col_index: usize) -> SparseEntry<'_, T> {
488 self.get_entry(row_index, col_index)
489 .expect("Out of bounds matrix indices encountered")
490 }
491
492 /// Returns a mutable entry for the given row/col indices.
493 ///
494 /// Same as `get_entry_mut`, except that it directly panics upon encountering row/col indices
495 /// out of bounds.
496 ///
497 /// Panics
498 /// ------
499 /// Panics if `row_index` or `col_index` is out of bounds.
500 pub fn index_entry_mut(&mut self, row_index: usize, col_index: usize) -> SparseEntryMut<'_, T> {
501 self.get_entry_mut(row_index, col_index)
502 .expect("Out of bounds matrix indices encountered")
503 }
504
505 /// Returns a triplet of slices `(col_offsets, row_indices, values)` that make up the CSC data.
506 #[must_use]
507 pub fn csc_data(&self) -> (&[usize], &[usize], &[T]) {
508 self.cs.cs_data()
509 }
510
511 /// Returns a triplet of slices `(col_offsets, row_indices, values)` that make up the CSC data,
512 /// where the `values` array is mutable.
513 pub fn csc_data_mut(&mut self) -> (&[usize], &[usize], &mut [T]) {
514 self.cs.cs_data_mut()
515 }
516
517 /// Creates a sparse matrix that contains only the explicit entries decided by the
518 /// given predicate.
519 #[must_use]
520 pub fn filter<P>(&self, predicate: P) -> Self
521 where
522 T: Clone,
523 P: Fn(usize, usize, &T) -> bool,
524 {
525 // Note: Predicate uses (row, col, value), so we have to switch around since
526 // cs uses (major, minor, value)
527 Self {
528 cs: self
529 .cs
530 .filter(|col_idx, row_idx, v| predicate(row_idx, col_idx, v)),
531 }
532 }
533
534 /// Returns a new matrix representing the upper triangular part of this matrix.
535 ///
536 /// The result includes the diagonal of the matrix.
537 #[must_use]
538 pub fn upper_triangle(&self) -> Self
539 where
540 T: Clone,
541 {
542 self.filter(|i, j, _| i <= j)
543 }
544
545 /// Returns a new matrix representing the lower triangular part of this matrix.
546 ///
547 /// The result includes the diagonal of the matrix.
548 #[must_use]
549 pub fn lower_triangle(&self) -> Self
550 where
551 T: Clone,
552 {
553 self.filter(|i, j, _| i >= j)
554 }
555
556 /// Returns the diagonal of the matrix as a sparse matrix.
557 #[must_use]
558 pub fn diagonal_as_csc(&self) -> Self
559 where
560 T: Clone,
561 {
562 Self {
563 cs: self.cs.diagonal_as_matrix(),
564 }
565 }
566
567 /// Compute the transpose of the matrix.
568 #[must_use]
569 pub fn transpose(&self) -> CscMatrix<T>
570 where
571 T: Scalar,
572 {
573 CsrMatrix::from(self).transpose_as_csc()
574 }
575}
576
577impl<T> Default for CscMatrix<T> {
578 fn default() -> Self {
579 Self {
580 cs: Default::default(),
581 }
582 }
583}
584
585/// Convert pattern format errors into more meaningful CSC-specific errors.
586///
587/// This ensures that the terminology is consistent: we are talking about rows and columns,
588/// not lanes, major and minor dimensions.
589fn pattern_format_error_to_csc_error(err: SparsityPatternFormatError) -> SparseFormatError {
590 use SparseFormatError as E;
591 use SparseFormatErrorKind as K;
592 use SparsityPatternFormatError::DuplicateEntry as PatternDuplicateEntry;
593 use SparsityPatternFormatError::*;
594
595 match err {
596 InvalidOffsetArrayLength => E::from_kind_and_msg(
597 K::InvalidStructure,
598 "Length of col offset array is not equal to ncols + 1.",
599 ),
600 InvalidOffsetFirstLast => E::from_kind_and_msg(
601 K::InvalidStructure,
602 "First or last col offset is inconsistent with format specification.",
603 ),
604 NonmonotonicOffsets => E::from_kind_and_msg(
605 K::InvalidStructure,
606 "Col offsets are not monotonically increasing.",
607 ),
608 NonmonotonicMinorIndices => E::from_kind_and_msg(
609 K::InvalidStructure,
610 "Row indices are not monotonically increasing (sorted) within each column.",
611 ),
612 MinorIndexOutOfBounds => {
613 E::from_kind_and_msg(K::IndexOutOfBounds, "Row indices are out of bounds.")
614 }
615 PatternDuplicateEntry => {
616 E::from_kind_and_msg(K::DuplicateEntry, "Matrix data contains duplicate entries.")
617 }
618 }
619}
620
621/// Iterator type for iterating over triplets in a CSC matrix.
622#[derive(Debug)]
623pub struct CscTripletIter<'a, T> {
624 pattern_iter: SparsityPatternIter<'a>,
625 values_iter: Iter<'a, T>,
626}
627
628impl<'a, T> Clone for CscTripletIter<'a, T> {
629 fn clone(&self) -> Self {
630 CscTripletIter {
631 pattern_iter: self.pattern_iter.clone(),
632 values_iter: self.values_iter.clone(),
633 }
634 }
635}
636
637impl<'a, T: Clone> CscTripletIter<'a, T> {
638 /// Adapts the triplet iterator to return owned values.
639 ///
640 /// The triplet iterator returns references to the values. This method adapts the iterator
641 /// so that the values are cloned.
642 #[inline]
643 pub fn cloned_values(self) -> impl 'a + Iterator<Item = (usize, usize, T)> {
644 self.map(|(i, j, v)| (i, j, v.clone()))
645 }
646}
647
648impl<'a, T> Iterator for CscTripletIter<'a, T> {
649 type Item = (usize, usize, &'a T);
650
651 fn next(&mut self) -> Option<Self::Item> {
652 let next_entry = self.pattern_iter.next();
653 let next_value = self.values_iter.next();
654
655 match (next_entry, next_value) {
656 (Some((i, j)), Some(v)) => Some((j, i, v)),
657 _ => None,
658 }
659 }
660}
661
662/// Iterator type for mutably iterating over triplets in a CSC matrix.
663#[derive(Debug)]
664pub struct CscTripletIterMut<'a, T> {
665 pattern_iter: SparsityPatternIter<'a>,
666 values_mut_iter: IterMut<'a, T>,
667}
668
669impl<'a, T> Iterator for CscTripletIterMut<'a, T> {
670 type Item = (usize, usize, &'a mut T);
671
672 #[inline]
673 fn next(&mut self) -> Option<Self::Item> {
674 let next_entry = self.pattern_iter.next();
675 let next_value = self.values_mut_iter.next();
676
677 match (next_entry, next_value) {
678 (Some((i, j)), Some(v)) => Some((j, i, v)),
679 _ => None,
680 }
681 }
682}
683
684/// An immutable representation of a column in a CSC matrix.
685#[derive(Debug, Clone, PartialEq, Eq)]
686pub struct CscCol<'a, T> {
687 lane: CsLane<'a, T>,
688}
689
690/// A mutable representation of a column in a CSC matrix.
691///
692/// Note that only explicitly stored entries can be mutated. The sparsity pattern belonging
693/// to the column cannot be modified.
694#[derive(Debug, PartialEq, Eq)]
695pub struct CscColMut<'a, T> {
696 lane: CsLaneMut<'a, T>,
697}
698
699/// Implement the methods common to both CscCol and CscColMut
700macro_rules! impl_csc_col_common_methods {
701 ($name:ty) => {
702 impl<'a, T> $name {
703 /// The number of global rows in the column.
704 #[inline]
705 #[must_use]
706 pub fn nrows(&self) -> usize {
707 self.lane.minor_dim()
708 }
709
710 /// The number of non-zeros in this column.
711 #[inline]
712 #[must_use]
713 pub fn nnz(&self) -> usize {
714 self.lane.nnz()
715 }
716
717 /// The row indices corresponding to explicitly stored entries in this column.
718 #[inline]
719 #[must_use]
720 pub fn row_indices(&self) -> &[usize] {
721 self.lane.minor_indices()
722 }
723
724 /// The values corresponding to explicitly stored entries in this column.
725 #[inline]
726 #[must_use]
727 pub fn values(&self) -> &[T] {
728 self.lane.values()
729 }
730
731 /// Returns an entry for the given global row index.
732 ///
733 /// Each call to this function incurs the cost of a binary search among the explicitly
734 /// stored row entries.
735 #[must_use]
736 pub fn get_entry(&self, global_row_index: usize) -> Option<SparseEntry<'_, T>> {
737 self.lane.get_entry(global_row_index)
738 }
739 }
740 };
741}
742
743impl_csc_col_common_methods!(CscCol<'a, T>);
744impl_csc_col_common_methods!(CscColMut<'a, T>);
745
746impl<'a, T> CscColMut<'a, T> {
747 /// Mutable access to the values corresponding to explicitly stored entries in this column.
748 pub fn values_mut(&mut self) -> &mut [T] {
749 self.lane.values_mut()
750 }
751
752 /// Provides simultaneous access to row indices and mutable values corresponding to the
753 /// explicitly stored entries in this column.
754 ///
755 /// This method primarily facilitates low-level access for methods that process data stored
756 /// in CSC format directly.
757 pub fn rows_and_values_mut(&mut self) -> (&[usize], &mut [T]) {
758 self.lane.indices_and_values_mut()
759 }
760
761 /// Returns a mutable entry for the given global row index.
762 #[must_use]
763 pub fn get_entry_mut(&mut self, global_row_index: usize) -> Option<SparseEntryMut<'_, T>> {
764 self.lane.get_entry_mut(global_row_index)
765 }
766}
767
768/// Column iterator for [`CscMatrix`].
769pub struct CscColIter<'a, T> {
770 lane_iter: CsLaneIter<'a, T>,
771}
772
773impl<'a, T> Iterator for CscColIter<'a, T> {
774 type Item = CscCol<'a, T>;
775
776 fn next(&mut self) -> Option<Self::Item> {
777 self.lane_iter.next().map(|lane| CscCol { lane })
778 }
779}
780
781/// Mutable column iterator for [`CscMatrix`].
782pub struct CscColIterMut<'a, T> {
783 lane_iter: CsLaneIterMut<'a, T>,
784}
785
786impl<'a, T> Iterator for CscColIterMut<'a, T>
787where
788 T: 'a,
789{
790 type Item = CscColMut<'a, T>;
791
792 fn next(&mut self) -> Option<Self::Item> {
793 self.lane_iter.next().map(|lane| CscColMut { lane })
794 }
795}