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}
OSZAR »