2019-02-03 21:18:55 +08:00
use num ::Zero ;
2020-03-21 19:16:46 +08:00
use simba ::scalar ::ClosedAdd ;
2018-10-21 13:42:32 +08:00
use std ::iter ;
2018-10-21 04:26:44 +08:00
use std ::marker ::PhantomData ;
2019-02-03 21:18:55 +08:00
use std ::ops ::Range ;
2018-10-21 13:42:32 +08:00
use std ::slice ;
2018-10-21 04:26:44 +08:00
2019-03-23 21:29:07 +08:00
use crate ::allocator ::Allocator ;
use crate ::sparse ::cs_utils ;
2021-08-03 00:41:46 +08:00
use crate ::{ Const , DefaultAllocator , Dim , Dynamic , Matrix , OVector , Scalar , Vector , U1 } ;
2018-11-07 01:31:04 +08:00
2021-04-11 17:00:38 +08:00
pub struct ColumnEntries < ' a , T > {
2018-11-07 01:31:04 +08:00
curr : usize ,
i : & ' a [ usize ] ,
2021-04-11 17:00:38 +08:00
v : & ' a [ T ] ,
2018-11-07 01:31:04 +08:00
}
2021-04-11 17:00:38 +08:00
impl < ' a , T > ColumnEntries < ' a , T > {
2018-11-07 01:31:04 +08:00
#[ inline ]
2021-04-11 17:00:38 +08:00
pub fn new ( i : & ' a [ usize ] , v : & ' a [ T ] ) -> Self {
2018-11-07 01:31:04 +08:00
assert_eq! ( i . len ( ) , v . len ( ) ) ;
2019-02-17 05:29:41 +08:00
Self { curr : 0 , i , v }
2018-11-07 01:31:04 +08:00
}
}
2021-04-11 17:00:38 +08:00
impl < ' a , T : Clone > Iterator for ColumnEntries < ' a , T > {
type Item = ( usize , T ) ;
2018-11-07 01:31:04 +08:00
#[ inline ]
2019-02-17 05:29:41 +08:00
fn next ( & mut self ) -> Option < Self ::Item > {
2018-11-07 01:31:04 +08:00
if self . curr > = self . i . len ( ) {
None
} else {
2021-07-06 05:51:27 +08:00
let res = Some ( ( unsafe { * self . i . get_unchecked ( self . curr ) } , unsafe {
self . v . get_unchecked ( self . curr ) . clone ( )
} ) ) ;
2018-11-07 01:31:04 +08:00
self . curr + = 1 ;
res
}
}
}
2018-10-21 04:26:44 +08:00
2020-11-15 23:57:49 +08:00
// TODO: this structure exists for now only because impl trait
2018-10-21 13:42:32 +08:00
// cannot be used for trait method return types.
2019-02-03 21:18:55 +08:00
/// Trait for iterable compressed-column matrix storage.
2021-04-11 17:00:38 +08:00
pub trait CsStorageIter < ' a , T , R , C = U1 > {
2019-02-03 21:18:55 +08:00
/// Iterator through all the rows of a specific columns.
///
2021-07-28 07:18:29 +08:00
/// The elements are given as a tuple (`row_index`, value).
2021-04-11 17:00:38 +08:00
type ColumnEntries : Iterator < Item = ( usize , T ) > ;
2019-02-03 21:18:55 +08:00
/// Iterator through the row indices of a specific column.
2018-10-30 14:46:34 +08:00
type ColumnRowIndices : Iterator < Item = usize > ;
2018-10-21 13:42:32 +08:00
2019-02-03 21:18:55 +08:00
/// Iterates through all the row indices of the j-th column.
2018-10-30 14:46:34 +08:00
fn column_row_indices ( & ' a self , j : usize ) -> Self ::ColumnRowIndices ;
2019-02-03 21:18:55 +08:00
/// Iterates through all the entries of the j-th column.
2018-10-21 13:42:32 +08:00
fn column_entries ( & ' a self , j : usize ) -> Self ::ColumnEntries ;
}
2019-02-03 21:18:55 +08:00
/// Trait for mutably iterable compressed-column sparse matrix storage.
2021-04-11 17:00:38 +08:00
pub trait CsStorageIterMut < ' a , T : ' a , R , C = U1 > {
2019-02-03 21:18:55 +08:00
/// Mutable iterator through all the values of the sparse matrix.
2021-04-11 17:00:38 +08:00
type ValuesMut : Iterator < Item = & ' a mut T > ;
2019-02-03 21:18:55 +08:00
/// Mutable iterator through all the rows of a specific columns.
///
2021-07-28 07:18:29 +08:00
/// The elements are given as a tuple (`row_index`, value).
2021-04-11 17:00:38 +08:00
type ColumnEntriesMut : Iterator < Item = ( usize , & ' a mut T ) > ;
2018-11-04 14:10:43 +08:00
2019-02-03 21:18:55 +08:00
/// A mutable iterator through the values buffer of the sparse matrix.
2018-11-07 01:31:04 +08:00
fn values_mut ( & ' a mut self ) -> Self ::ValuesMut ;
2019-02-03 21:18:55 +08:00
/// Iterates mutably through all the entries of the j-th column.
2018-11-04 14:10:43 +08:00
fn column_entries_mut ( & ' a mut self , j : usize ) -> Self ::ColumnEntriesMut ;
}
2019-02-03 21:18:55 +08:00
/// Trait for compressed column sparse matrix storage.
2021-04-11 17:00:38 +08:00
pub trait CsStorage < T , R , C = U1 > : for < ' a > CsStorageIter < ' a , T , R , C > {
2019-02-03 21:18:55 +08:00
/// The shape of the stored matrix.
2018-10-21 04:26:44 +08:00
fn shape ( & self ) -> ( R , C ) ;
2019-02-03 21:18:55 +08:00
/// Retrieve the i-th row index of the underlying row index buffer.
///
2021-07-04 11:19:07 +08:00
/// # Safety
2019-02-03 21:18:55 +08:00
/// No bound-checking is performed.
2018-10-21 04:26:44 +08:00
unsafe fn row_index_unchecked ( & self , i : usize ) -> usize ;
2019-02-03 21:18:55 +08:00
/// The i-th value on the contiguous value buffer of this storage.
///
2021-07-04 11:19:07 +08:00
/// # Safety
2019-02-03 21:18:55 +08:00
/// No bound-checking is performed.
2021-04-11 17:00:38 +08:00
unsafe fn get_value_unchecked ( & self , i : usize ) -> & T ;
2019-02-03 21:18:55 +08:00
/// The i-th value on the contiguous value buffer of this storage.
2021-04-11 17:00:38 +08:00
fn get_value ( & self , i : usize ) -> & T ;
2019-02-03 21:18:55 +08:00
/// Retrieve the i-th row index of the underlying row index buffer.
2018-10-21 04:26:44 +08:00
fn row_index ( & self , i : usize ) -> usize ;
2019-02-03 21:18:55 +08:00
/// The value indices for the `i`-th column.
2018-10-24 00:18:05 +08:00
fn column_range ( & self , i : usize ) -> Range < usize > ;
2019-02-03 21:18:55 +08:00
/// The size of the value buffer (i.e. the entries known as possibly being non-zero).
2018-10-24 00:18:05 +08:00
fn len ( & self ) -> usize ;
2018-10-21 04:26:44 +08:00
}
2019-02-03 21:18:55 +08:00
/// Trait for compressed column sparse matrix mutable storage.
2021-04-11 17:00:38 +08:00
pub trait CsStorageMut < T , R , C = U1 > :
CsStorage < T , R , C > + for < ' a > CsStorageIterMut < ' a , T , R , C >
2018-11-04 14:10:43 +08:00
{
2018-10-21 04:26:44 +08:00
}
2019-02-03 21:18:55 +08:00
/// A storage of column-compressed sparse matrix based on a Vec.
2018-11-07 01:31:04 +08:00
#[ derive(Clone, Debug, PartialEq) ]
2021-04-11 17:00:38 +08:00
pub struct CsVecStorage < T : Scalar , R : Dim , C : Dim >
2020-04-05 23:53:27 +08:00
where
DefaultAllocator : Allocator < usize , C > ,
2018-10-21 04:26:44 +08:00
{
2018-10-30 14:46:34 +08:00
pub ( crate ) shape : ( R , C ) ,
2021-04-11 17:00:38 +08:00
pub ( crate ) p : OVector < usize , C > ,
2018-10-30 14:46:34 +08:00
pub ( crate ) i : Vec < usize > ,
2021-04-11 17:00:38 +08:00
pub ( crate ) vals : Vec < T > ,
2018-10-21 04:26:44 +08:00
}
2021-04-11 17:00:38 +08:00
impl < T : Scalar , R : Dim , C : Dim > CsVecStorage < T , R , C >
2020-04-05 23:53:27 +08:00
where
DefaultAllocator : Allocator < usize , C > ,
2018-10-31 00:29:32 +08:00
{
2019-02-03 21:18:55 +08:00
/// The value buffer of this storage.
2021-06-07 22:34:03 +08:00
#[ must_use ]
2021-04-11 17:00:38 +08:00
pub fn values ( & self ) -> & [ T ] {
2018-10-31 00:29:32 +08:00
& self . vals
}
2019-02-03 21:18:55 +08:00
/// The column shifts buffer.
2021-06-07 22:34:03 +08:00
#[ must_use ]
2018-11-07 01:31:04 +08:00
pub fn p ( & self ) -> & [ usize ] {
self . p . as_slice ( )
}
2019-02-03 21:18:55 +08:00
/// The row index buffers.
2021-06-07 22:34:03 +08:00
#[ must_use ]
2018-11-07 01:31:04 +08:00
pub fn i ( & self ) -> & [ usize ] {
& self . i
}
2018-10-31 00:29:32 +08:00
}
2021-04-11 17:00:38 +08:00
impl < T : Scalar , R : Dim , C : Dim > CsVecStorage < T , R , C > where DefaultAllocator : Allocator < usize , C > { }
2018-10-21 13:42:32 +08:00
2021-04-11 17:00:38 +08:00
impl < ' a , T : Scalar , R : Dim , C : Dim > CsStorageIter < ' a , T , R , C > for CsVecStorage < T , R , C >
2020-04-05 23:53:27 +08:00
where
DefaultAllocator : Allocator < usize , C > ,
2018-10-21 13:42:32 +08:00
{
2021-04-11 17:00:38 +08:00
type ColumnEntries = ColumnEntries < ' a , T > ;
2018-10-30 14:46:34 +08:00
type ColumnRowIndices = iter ::Cloned < slice ::Iter < ' a , usize > > ;
2018-10-21 13:42:32 +08:00
#[ inline ]
fn column_entries ( & ' a self , j : usize ) -> Self ::ColumnEntries {
let rng = self . column_range ( j ) ;
2018-11-07 01:31:04 +08:00
ColumnEntries ::new ( & self . i [ rng . clone ( ) ] , & self . vals [ rng ] )
2018-10-21 13:42:32 +08:00
}
2018-10-30 14:46:34 +08:00
#[ inline ]
fn column_row_indices ( & ' a self , j : usize ) -> Self ::ColumnRowIndices {
let rng = self . column_range ( j ) ;
2021-07-04 11:19:07 +08:00
self . i [ rng ] . iter ( ) . cloned ( )
2018-10-30 14:46:34 +08:00
}
2018-10-21 13:42:32 +08:00
}
2021-04-11 17:00:38 +08:00
impl < T : Scalar , R : Dim , C : Dim > CsStorage < T , R , C > for CsVecStorage < T , R , C >
2020-04-05 23:53:27 +08:00
where
DefaultAllocator : Allocator < usize , C > ,
2018-10-21 13:42:32 +08:00
{
#[ inline ]
fn shape ( & self ) -> ( R , C ) {
self . shape
}
#[ inline ]
2018-10-24 00:18:05 +08:00
fn len ( & self ) -> usize {
2018-10-21 13:42:32 +08:00
self . vals . len ( )
}
2018-10-21 04:26:44 +08:00
#[ inline ]
fn row_index ( & self , i : usize ) -> usize {
self . i [ i ]
}
#[ inline ]
unsafe fn row_index_unchecked ( & self , i : usize ) -> usize {
* self . i . get_unchecked ( i )
}
#[ inline ]
2021-04-11 17:00:38 +08:00
unsafe fn get_value_unchecked ( & self , i : usize ) -> & T {
2018-10-21 04:26:44 +08:00
self . vals . get_unchecked ( i )
}
#[ inline ]
2021-04-11 17:00:38 +08:00
fn get_value ( & self , i : usize ) -> & T {
2018-10-21 04:26:44 +08:00
& self . vals [ i ]
}
2018-10-24 00:18:05 +08:00
#[ inline ]
fn column_range ( & self , j : usize ) -> Range < usize > {
let end = if j + 1 = = self . p . len ( ) {
self . len ( )
} else {
self . p [ j + 1 ]
} ;
self . p [ j ] .. end
}
2018-10-21 04:26:44 +08:00
}
2021-04-11 17:00:38 +08:00
impl < ' a , T : Scalar , R : Dim , C : Dim > CsStorageIterMut < ' a , T , R , C > for CsVecStorage < T , R , C >
2020-04-05 23:53:27 +08:00
where
DefaultAllocator : Allocator < usize , C > ,
2018-11-04 14:10:43 +08:00
{
2021-04-11 17:00:38 +08:00
type ValuesMut = slice ::IterMut < ' a , T > ;
type ColumnEntriesMut = iter ::Zip < iter ::Cloned < slice ::Iter < ' a , usize > > , slice ::IterMut < ' a , T > > ;
2018-11-04 14:10:43 +08:00
2018-11-07 01:31:04 +08:00
#[ inline ]
fn values_mut ( & ' a mut self ) -> Self ::ValuesMut {
self . vals . iter_mut ( )
}
2018-11-04 14:10:43 +08:00
#[ inline ]
fn column_entries_mut ( & ' a mut self , j : usize ) -> Self ::ColumnEntriesMut {
let rng = self . column_range ( j ) ;
self . i [ rng . clone ( ) ]
. iter ( )
. cloned ( )
. zip ( self . vals [ rng ] . iter_mut ( ) )
}
}
2021-04-11 17:00:38 +08:00
impl < T : Scalar , R : Dim , C : Dim > CsStorageMut < T , R , C > for CsVecStorage < T , R , C > where
2020-04-05 23:53:27 +08:00
DefaultAllocator : Allocator < usize , C >
{
}
2018-11-04 14:10:43 +08:00
2018-10-21 04:26:44 +08:00
/*
2021-04-11 17:00:38 +08:00
pub struct CsSliceStorage < ' a , T : Scalar , R : Dim , C : DimAdd < U1 > > {
2018-10-21 04:26:44 +08:00
shape : ( R , C ) ,
p : VectorSlice < usize , DimSum < C , U1 > > ,
i : VectorSlice < usize , Dynamic > ,
2021-04-11 17:00:38 +08:00
vals : VectorSlice < T , Dynamic > ,
2018-10-21 04:26:44 +08:00
} * /
/// A compressed sparse column matrix.
2018-11-07 01:31:04 +08:00
#[ derive(Clone, Debug, PartialEq) ]
pub struct CsMatrix <
2021-04-11 17:00:38 +08:00
T : Scalar ,
2018-11-07 01:31:04 +08:00
R : Dim = Dynamic ,
C : Dim = Dynamic ,
2021-04-11 17:00:38 +08:00
S : CsStorage < T , R , C > = CsVecStorage < T , R , C > ,
2018-11-07 01:31:04 +08:00
> {
2019-02-03 21:18:55 +08:00
pub ( crate ) data : S ,
2021-04-11 17:00:38 +08:00
_phantoms : PhantomData < ( T , R , C ) > ,
2018-10-21 04:26:44 +08:00
}
2019-02-03 21:18:55 +08:00
/// A column compressed sparse vector.
2021-04-11 17:00:38 +08:00
pub type CsVector < T , R = Dynamic , S = CsVecStorage < T , R , U1 > > = CsMatrix < T , R , U1 , S > ;
2018-10-21 04:26:44 +08:00
2021-04-11 17:00:38 +08:00
impl < T : Scalar , R : Dim , C : Dim > CsMatrix < T , R , C >
2020-04-05 23:53:27 +08:00
where
DefaultAllocator : Allocator < usize , C > ,
2018-10-21 04:26:44 +08:00
{
2019-02-03 21:18:55 +08:00
/// Creates a new compressed sparse column matrix with the specified dimension and
/// `nvals` possible non-zero values.
2018-10-21 04:26:44 +08:00
pub fn new_uninitialized_generic ( nrows : R , ncols : C , nvals : usize ) -> Self {
let mut i = Vec ::with_capacity ( nvals ) ;
unsafe {
i . set_len ( nvals ) ;
}
i . shrink_to_fit ( ) ;
let mut vals = Vec ::with_capacity ( nvals ) ;
unsafe {
vals . set_len ( nvals ) ;
}
vals . shrink_to_fit ( ) ;
CsMatrix {
data : CsVecStorage {
shape : ( nrows , ncols ) ,
2021-07-18 02:36:35 +08:00
p : OVector ::zeros_generic ( ncols , Const ::< 1 > ) ,
2018-10-21 04:26:44 +08:00
i ,
vals ,
} ,
_phantoms : PhantomData ,
}
}
2019-02-03 21:18:55 +08:00
/*
pub ( crate ) fn from_parts_generic (
2018-11-07 01:31:04 +08:00
nrows : R ,
ncols : C ,
2021-04-11 17:00:38 +08:00
p : OVector < usize , C > ,
2018-11-07 01:31:04 +08:00
i : Vec < usize > ,
2021-04-11 17:00:38 +08:00
vals : Vec < T > ,
2018-11-07 01:31:04 +08:00
) -> Self
where
2021-04-11 17:00:38 +08:00
T : Zero + ClosedAdd ,
DefaultAllocator : Allocator < T , R > ,
2018-11-07 01:31:04 +08:00
{
assert_eq! ( ncols . value ( ) , p . len ( ) , " Invalid inptr size. " ) ;
assert_eq! ( i . len ( ) , vals . len ( ) , " Invalid value size. " ) ;
// Check p.
for ptr in & p {
assert! ( * ptr < i . len ( ) , " Invalid inptr value. " ) ;
}
2018-10-21 04:26:44 +08:00
2018-11-07 01:31:04 +08:00
for ptr in p . as_slice ( ) . windows ( 2 ) {
assert! ( ptr [ 0 ] < = ptr [ 1 ] , " Invalid inptr ordering. " ) ;
}
// Check i.
for i in & i {
assert! ( * i < nrows . value ( ) , " Invalid row ptr value. " )
}
let mut res = CsMatrix {
data : CsVecStorage {
shape : ( nrows , ncols ) ,
p ,
i ,
vals ,
} ,
_phantoms : PhantomData ,
} ;
// Sort and remove duplicates.
res . sort ( ) ;
res . dedup ( ) ;
res
2019-02-03 21:18:55 +08:00
} * /
2018-11-07 01:31:04 +08:00
}
2018-10-21 04:26:44 +08:00
2019-02-03 21:18:55 +08:00
/*
2021-04-11 17:00:38 +08:00
impl < T : Scalar + Zero + ClosedAdd > CsMatrix < T > {
2019-02-03 21:18:55 +08:00
pub ( crate ) fn from_parts (
2018-11-07 01:31:04 +08:00
nrows : usize ,
ncols : usize ,
p : Vec < usize > ,
i : Vec < usize > ,
2021-04-11 17:00:38 +08:00
vals : Vec < T > ,
2018-11-07 01:32:20 +08:00
) -> Self
{
2018-11-07 01:31:04 +08:00
let nrows = Dynamic ::new ( nrows ) ;
let ncols = Dynamic ::new ( ncols ) ;
2019-02-03 21:18:55 +08:00
let p = DVector ::from_data ( VecStorage ::new ( ncols , U1 , p ) ) ;
2018-11-07 01:31:04 +08:00
Self ::from_parts_generic ( nrows , ncols , p , i , vals )
}
2018-10-21 04:26:44 +08:00
}
2019-02-03 21:18:55 +08:00
* /
2018-10-21 04:26:44 +08:00
2021-04-11 17:00:38 +08:00
impl < T : Scalar , R : Dim , C : Dim , S : CsStorage < T , R , C > > CsMatrix < T , R , C , S > {
2019-02-03 21:18:55 +08:00
pub ( crate ) fn from_data ( data : S ) -> Self {
2018-10-31 00:29:32 +08:00
CsMatrix {
data ,
_phantoms : PhantomData ,
}
}
2019-02-03 21:18:55 +08:00
/// The size of the data buffer.
2021-06-07 22:34:03 +08:00
#[ must_use ]
2018-10-24 00:18:05 +08:00
pub fn len ( & self ) -> usize {
self . data . len ( )
2018-10-21 04:26:44 +08:00
}
2019-02-03 21:18:55 +08:00
/// The number of rows of this matrix.
2021-06-07 22:34:03 +08:00
#[ must_use ]
2018-10-31 00:29:32 +08:00
pub fn nrows ( & self ) -> usize {
self . data . shape ( ) . 0. value ( )
}
2019-02-03 21:18:55 +08:00
/// The number of rows of this matrix.
2021-06-07 22:34:03 +08:00
#[ must_use ]
2018-10-31 00:29:32 +08:00
pub fn ncols ( & self ) -> usize {
self . data . shape ( ) . 1. value ( )
}
2019-02-03 21:18:55 +08:00
/// The shape of this matrix.
2021-06-07 22:34:03 +08:00
#[ must_use ]
2018-10-31 00:29:32 +08:00
pub fn shape ( & self ) -> ( usize , usize ) {
let ( nrows , ncols ) = self . data . shape ( ) ;
( nrows . value ( ) , ncols . value ( ) )
}
2019-02-03 21:18:55 +08:00
/// Whether this matrix is square or not.
2021-06-07 22:34:03 +08:00
#[ must_use ]
2018-10-31 00:29:32 +08:00
pub fn is_square ( & self ) -> bool {
let ( nrows , ncols ) = self . data . shape ( ) ;
nrows . value ( ) = = ncols . value ( )
}
2018-11-05 23:38:43 +08:00
/// Should always return `true`.
///
/// This method is generally used for debugging and should typically not be called in user code.
/// This checks that the row inner indices of this matrix are sorted. It takes `O(n)` time,
/// where n` is `self.len()`.
/// All operations of CSC matrices on nalgebra assume, and will return, sorted indices.
/// If at any time this `is_sorted` method returns `false`, then, something went wrong
/// and an issue should be open on the nalgebra repository with details on how to reproduce
/// this.
2021-06-07 22:34:03 +08:00
#[ must_use ]
2018-11-05 23:38:43 +08:00
pub fn is_sorted ( & self ) -> bool {
for j in 0 .. self . ncols ( ) {
let mut curr = None ;
for idx in self . data . column_row_indices ( j ) {
if let Some ( curr ) = curr {
if idx < = curr {
return false ;
}
}
curr = Some ( idx ) ;
}
}
true
}
2019-02-03 21:18:55 +08:00
/// Computes the transpose of this sparse matrix.
2021-03-24 23:28:14 +08:00
#[ must_use = " This function does not mutate the matrix. Consider using the return value or removing the function call. There's also transpose_mut() for square matrices. " ]
2021-04-11 17:00:38 +08:00
pub fn transpose ( & self ) -> CsMatrix < T , C , R >
2020-04-05 23:53:27 +08:00
where
DefaultAllocator : Allocator < usize , R > ,
{
2018-10-21 04:26:44 +08:00
let ( nrows , ncols ) = self . data . shape ( ) ;
2018-10-24 00:18:05 +08:00
let nvals = self . len ( ) ;
2018-10-21 04:26:44 +08:00
let mut res = CsMatrix ::new_uninitialized_generic ( ncols , nrows , nvals ) ;
2021-07-18 02:36:35 +08:00
let mut workspace = Vector ::zeros_generic ( nrows , Const ::< 1 > ) ;
2018-10-21 04:26:44 +08:00
// Compute p.
for i in 0 .. nvals {
let row_id = self . data . row_index ( i ) ;
workspace [ row_id ] + = 1 ;
}
2018-11-07 01:31:04 +08:00
let _ = cs_utils ::cumsum ( & mut workspace , & mut res . data . p ) ;
2018-10-21 04:26:44 +08:00
// Fill the result.
for j in 0 .. ncols . value ( ) {
2018-10-21 13:42:32 +08:00
for ( row_id , value ) in self . data . column_entries ( j ) {
2018-10-21 04:26:44 +08:00
let shift = workspace [ row_id ] ;
2018-10-21 13:42:32 +08:00
res . data . vals [ shift ] = value ;
2018-10-21 04:26:44 +08:00
res . data . i [ shift ] = j ;
workspace [ row_id ] + = 1 ;
}
}
res
}
}
2018-11-05 23:38:43 +08:00
2021-04-11 17:00:38 +08:00
impl < T : Scalar , R : Dim , C : Dim , S : CsStorageMut < T , R , C > > CsMatrix < T , R , C , S > {
2019-02-03 21:18:55 +08:00
/// Iterator through all the mutable values of this sparse matrix.
2018-11-07 01:31:04 +08:00
#[ inline ]
2021-04-11 17:00:38 +08:00
pub fn values_mut ( & mut self ) -> impl Iterator < Item = & mut T > {
2018-11-07 01:31:04 +08:00
self . data . values_mut ( )
}
}
2021-04-11 17:00:38 +08:00
impl < T : Scalar , R : Dim , C : Dim > CsMatrix < T , R , C >
2020-04-05 23:53:27 +08:00
where
DefaultAllocator : Allocator < usize , C > ,
2018-11-05 23:38:43 +08:00
{
pub ( crate ) fn sort ( & mut self )
2020-04-05 23:53:27 +08:00
where
2021-08-03 15:54:11 +08:00
T : Zero ,
2021-04-11 17:00:38 +08:00
DefaultAllocator : Allocator < T , R > ,
2020-04-05 23:53:27 +08:00
{
2018-11-05 23:38:43 +08:00
// Size = R
let nrows = self . data . shape ( ) . 0 ;
2021-08-03 00:41:46 +08:00
let mut workspace = Matrix ::zeros_generic ( nrows , Const ::< 1 > ) ;
2018-11-05 23:38:43 +08:00
self . sort_with_workspace ( workspace . as_mut_slice ( ) ) ;
}
2021-04-11 17:00:38 +08:00
pub ( crate ) fn sort_with_workspace ( & mut self , workspace : & mut [ T ] ) {
2018-11-05 23:38:43 +08:00
assert! (
workspace . len ( ) > = self . nrows ( ) ,
" Workspace must be able to hold at least self.nrows() elements. "
) ;
for j in 0 .. self . ncols ( ) {
// Scatter the row in the workspace.
for ( irow , val ) in self . data . column_entries ( j ) {
workspace [ irow ] = val ;
}
// Sort the index vector.
let range = self . data . column_range ( j ) ;
2021-07-04 11:19:07 +08:00
self . data . i [ range . clone ( ) ] . sort_unstable ( ) ;
2018-11-05 23:38:43 +08:00
// Permute the values too.
for ( i , irow ) in range . clone ( ) . zip ( self . data . i [ range ] . iter ( ) . cloned ( ) ) {
2021-08-04 23:34:25 +08:00
self . data . vals [ i ] = workspace [ irow ] . clone ( ) ;
2018-11-05 23:38:43 +08:00
}
}
}
2018-11-07 01:31:04 +08:00
// Remove dupliate entries on a sorted CsMatrix.
pub ( crate ) fn dedup ( & mut self )
2020-04-05 23:53:27 +08:00
where
2021-04-11 17:00:38 +08:00
T : Zero + ClosedAdd ,
2020-04-05 23:53:27 +08:00
{
2018-11-07 01:31:04 +08:00
let mut curr_i = 0 ;
for j in 0 .. self . ncols ( ) {
let range = self . data . column_range ( j ) ;
self . data . p [ j ] = curr_i ;
if range . start ! = range . end {
2021-04-11 17:00:38 +08:00
let mut value = T ::zero ( ) ;
2018-11-07 01:31:04 +08:00
let mut irow = self . data . i [ range . start ] ;
for idx in range {
let curr_irow = self . data . i [ idx ] ;
if curr_irow = = irow {
2021-08-04 23:34:25 +08:00
value + = self . data . vals [ idx ] . clone ( ) ;
2018-11-07 01:31:04 +08:00
} else {
self . data . i [ curr_i ] = irow ;
self . data . vals [ curr_i ] = value ;
2021-08-04 23:34:25 +08:00
value = self . data . vals [ idx ] . clone ( ) ;
2018-11-07 01:31:04 +08:00
irow = curr_irow ;
curr_i + = 1 ;
}
}
// Handle the last entry.
self . data . i [ curr_i ] = irow ;
self . data . vals [ curr_i ] = value ;
curr_i + = 1 ;
}
}
self . data . i . truncate ( curr_i ) ;
self . data . i . shrink_to_fit ( ) ;
self . data . vals . truncate ( curr_i ) ;
self . data . vals . shrink_to_fit ( ) ;
}
2018-11-05 23:38:43 +08:00
}