Skip to main content

NumCooMatrix

Struct NumCooMatrix 

Source
pub struct NumCooMatrix<T>{ /* private fields */ }
Expand description

Holds the row index, col index, and values of a matrix (also known as Triplet)

§Remarks

  • Only the non-zero values are required
  • Entries with repeated (i,j) indices are allowed
  • Repeated (i,j) entries should be summed when solving a linear system
  • The repeated (i,j) capability is of great convenience for Finite Element solvers
  • A maximum number of entries must be decided prior to allocating a new COO matrix
  • The maximum number of entries includes possible entries with repeated indices

Implementations§

Source§

impl NumCooMatrix<Complex<f64>>

Source

pub fn assign_real( &mut self, alpha: f64, beta: f64, other: &CooMatrix, ) -> Result<(), StrError>

Assigns this matrix to the values of another real matrix (scaled)

Performs:

this = (α + βi) · other

Thus:

this[p].real = α · other[p]
this[p].imag = β · other[p]

other[p] ∈ Reals
p = [0, nnz(other)]

Warning: make sure to allocate max_nnz ≥ nnz(other).

Source

pub fn augment_real( &mut self, alpha: f64, beta: f64, other: &CooMatrix, ) -> Result<(), StrError>

Augments this matrix with the entries of another real matrix (scaled)

Effectively, performs:

this += (α + βi) · other

Thus:

this[p].real += α · other[p]
this[p].imag += β · other[p]

other[p] ∈ Reals
p = [0, nnz(other)]

Warning: make sure to allocate max_nnz ≥ nnz(this) + nnz(other).

Source§

impl<T> NumCooMatrix<T>

Source

pub fn new( nrow: usize, ncol: usize, max_nnz: usize, symmetric: Sym, ) -> Result<Self, StrError>

Creates a new COO matrix representing a sparse matrix

§Input
  • nrow – (≥ 1) Is the number of rows of the sparse matrix (must be fit i32)
  • ncol – (≥ 1) Is the number of columns of the sparse matrix (must be fit i32)
  • max_nnz – (≥ 1) Maximum number of entries ≥ nnz (number of non-zeros), including entries with repeated indices. (must be fit i32)
  • symmetric – indicates whether the matrix is symmetric or not. If symmetric, indicates the representation too.
§Examples
use russell_sparse::prelude::*;
use russell_sparse::StrError;

fn main() -> Result<(), StrError> {
    // allocate the coefficient matrix
    //  2  3  .  .  .
    //  3  .  4  .  6
    //  . -1 -3  2  .
    //  .  .  1  .  .
    //  .  4  2  .  1
    let mut coo = CooMatrix::new(5, 5, 13, Sym::No)?;
    coo.put(0, 0, 1.0)?; // << (0, 0, a00/2) duplicate
    coo.put(0, 0, 1.0)?; // << (0, 0, a00/2) duplicate
    coo.put(1, 0, 3.0)?;
    coo.put(0, 1, 3.0)?;
    coo.put(2, 1, -1.0)?;
    coo.put(4, 1, 4.0)?;
    coo.put(1, 2, 4.0)?;
    coo.put(2, 2, -3.0)?;
    coo.put(3, 2, 1.0)?;
    coo.put(4, 2, 2.0)?;
    coo.put(2, 3, 2.0)?;
    coo.put(1, 4, 6.0)?;
    coo.put(4, 4, 1.0)?;

    // covert to dense
    let a = coo.as_dense();
    let correct = "┌                ┐\n\
                   │  2  3  0  0  0 │\n\
                   │  3  0  4  0  6 │\n\
                   │  0 -1 -3  2  0 │\n\
                   │  0  0  1  0  0 │\n\
                   │  0  4  2  0  1 │\n\
                   └                ┘";
    assert_eq!(format!("{}", a), correct);

    // reset
    coo.reset();

    // covert to dense
    let a = coo.as_dense();
    let correct = "┌           ┐\n\
                   │ 0 0 0 0 0 │\n\
                   │ 0 0 0 0 0 │\n\
                   │ 0 0 0 0 0 │\n\
                   │ 0 0 0 0 0 │\n\
                   │ 0 0 0 0 0 │\n\
                   └           ┘";
    assert_eq!(format!("{}", a), correct);

    // put again doubled values
    coo.put(0, 0, 2.0)?; // << duplicate
    coo.put(0, 0, 2.0)?; // << duplicate
    coo.put(1, 0, 6.0)?;
    coo.put(0, 1, 6.0)?;
    coo.put(2, 1, -2.0)?;
    coo.put(4, 1, 8.0)?;
    coo.put(1, 2, 8.0)?;
    coo.put(2, 2, -6.0)?;
    coo.put(3, 2, 2.0)?;
    coo.put(4, 2, 4.0)?;
    coo.put(2, 3, 4.0)?;
    coo.put(1, 4, 12.0)?;
    coo.put(4, 4, 2.0)?;

    // covert to dense
    let a = coo.as_dense();
    let correct = "┌                ┐\n\
                   │  4  6  0  0  0 │\n\
                   │  6  0  8  0 12 │\n\
                   │  0 -2 -6  4  0 │\n\
                   │  0  0  2  0  0 │\n\
                   │  0  8  4  0  2 │\n\
                   └                ┘";
    assert_eq!(format!("{}", a), correct);
    Ok(())
}
Source

pub fn from( nrow: usize, ncol: usize, row_indices: Vec<i32>, col_indices: Vec<i32>, values: Vec<T>, symmetric: Sym, ) -> Result<Self, StrError>

Creates a COO matrix from triplets: row indices, col indices, and non-zero values

§Input
  • nrow – (≥ 1) Is the number of rows of the sparse matrix (must be fit i32)
  • ncol – (≥ 1) Is the number of columns of the sparse matrix (must be fit i32)
  • row_indices – (len = nnz) Is the array of row indices
  • col_indices – (len = nnz) Is the array of columns indices
  • values – (len = nnz) Is the array of non-zero values
  • symmetric – Indicates that this matrix is symmetric (with the storage type)
§Examples
use russell_sparse::prelude::*;
use russell_sparse::StrError;

fn main() -> Result<(), StrError> {
    // allocate a square matrix and store as CSC matrix
    //  2  3  .  .  .
    //  3  .  4  .  6
    //  . -1 -3  2  .
    //  .  .  1  .  .
    //  .  4  2  .  1
    let nrow = 5;
    let ncol = 5;
    let row_indices = vec![0, /*dup*/ 0, 1, 0, 2, 4, 1, 2, 3, 4, 2, 1, 4];
    let col_indices = vec![0, /*dup*/ 0, 0, 1, 1, 1, 2, 2, 2, 2, 3, 4, 4];
    let values = vec![
        1.0, /*dup*/ 1.0, 3.0, 3.0, -1.0, 4.0, 4.0, -3.0, 1.0, 2.0, 2.0, 6.0, 1.0,
    ];
    let coo = CooMatrix::from(nrow, ncol, row_indices, col_indices, values, Sym::No)?;

    // covert to dense
    let a = coo.as_dense();
    let correct = "┌                ┐\n\
                   │  2  3  0  0  0 │\n\
                   │  3  0  4  0  6 │\n\
                   │  0 -1 -3  2  0 │\n\
                   │  0  0  1  0  0 │\n\
                   │  0  4  2  0  1 │\n\
                   └                ┘";
    assert_eq!(format!("{}", a), correct);
    Ok(())
}
Source

pub fn put(&mut self, i: usize, j: usize, aij: T) -> Result<(), StrError>

Puts a new entry and updates pos (may be duplicate)

§Input
  • i – row index (indices start at zero; zero-based)
  • j – column index (indices start at zero; zero-based)
  • aij – the value A(i,j)
§Examples
use russell_lab::vec_approx_eq;
use russell_sparse::prelude::*;
use russell_sparse::StrError;

fn main() -> Result<(), StrError> {
    let (nrow, ncol, nnz) = (3, 3, 4);
    let mut coo = CooMatrix::new(nrow, ncol, nnz, Sym::No)?;
    coo.put(0, 0, 1.0)?;
    coo.put(1, 1, 2.0)?;
    coo.put(2, 2, 3.0)?;
    coo.put(0, 1, 4.0)?;
    let a = coo.as_dense();
    let correct = "┌       ┐\n\
                   │ 1 4 0 │\n\
                   │ 0 2 0 │\n\
                   │ 0 0 3 │\n\
                   └       ┘";
    assert_eq!(format!("{}", a), correct);
    Ok(())
}
Source

pub fn reset(&mut self)

Resets the position of the current non-zero value

This function allows using put all over again.

§Examples
use russell_sparse::prelude::*;
use russell_sparse::StrError;

fn main() -> Result<(), StrError> {
    let (nrow, ncol, max_nnz) = (3, 3, 10);
    let mut coo = CooMatrix::new(nrow, ncol, max_nnz, Sym::No)?;
    coo.put(0, 0, 1.0)?;
    coo.put(1, 1, 2.0)?;
    coo.put(2, 2, 3.0)?;
    coo.put(0, 1, 4.0)?;
    let a = coo.as_dense();
    let correct = "┌       ┐\n\
                   │ 1 4 0 │\n\
                   │ 0 2 0 │\n\
                   │ 0 0 3 │\n\
                   └       ┘";
    coo.reset();
    let (nrow, ncol, nnz, sym) = coo.get_info();
    assert_eq!(nrow, 3);
    assert_eq!(ncol, 3);
    assert_eq!(nnz, 0);
    assert_eq!(sym, Sym::No);
    Ok(())
}
Source

pub fn as_dense(&self) -> NumMatrix<T>

Converts this COO matrix to a dense matrix

use russell_sparse::prelude::*;
use russell_sparse::StrError;

fn main() -> Result<(), StrError> {
    // define (4 x 4) sparse matrix with 6+1 non-zero values
    // (with an extra ij-repeated entry)
    let (nrow, ncol, max_nnz) = (4, 4, 10);
    let mut coo = CooMatrix::new(nrow, ncol, max_nnz, Sym::No)?;
    coo.put(0, 0, 0.5)?; // (0, 0, a00/2)  << duplicate
    coo.put(0, 0, 0.5)?; // (0, 0, a00/2)  << duplicate
    coo.put(0, 1, 2.0)?;
    coo.put(1, 0, 3.0)?;
    coo.put(1, 1, 4.0)?;
    coo.put(2, 2, 5.0)?;
    coo.put(3, 3, 6.0)?;

    // convert to dense
    let a = coo.as_dense();
    let correct = "┌         ┐\n\
                   │ 1 2 0 0 │\n\
                   │ 3 4 0 0 │\n\
                   │ 0 0 5 0 │\n\
                   │ 0 0 0 6 │\n\
                   └         ┘";
    assert_eq!(format!("{}", a), correct);
    Ok(())
}
Source

pub fn to_dense(&self, a: &mut NumMatrix<T>) -> Result<(), StrError>

Converts this COO matrix to a dense matrix

§Input
  • a – where to store the dense matrix; it must be (nrow, ncol)
§Examples
use russell_lab::Matrix;
use russell_sparse::prelude::*;
use russell_sparse::StrError;

fn main() -> Result<(), StrError> {
    // define (4 x 4) sparse matrix with 6+1 non-zero values
    // (with an extra ij-repeated entry)
    let (nrow, ncol, max_nnz) = (4, 4, 10);
    let mut coo = CooMatrix::new(nrow, ncol, max_nnz, Sym::No)?;
    coo.put(0, 0, 0.5)?; // (0, 0, a00/2) << duplicate
    coo.put(0, 0, 0.5)?; // (0, 0, a00/2) << duplicate
    coo.put(0, 1, 2.0)?;
    coo.put(1, 0, 3.0)?;
    coo.put(1, 1, 4.0)?;
    coo.put(2, 2, 5.0)?;
    coo.put(3, 3, 6.0)?;

    // convert to dense
    let mut a = Matrix::new(nrow, ncol);
    coo.to_dense(&mut a)?;
    let correct = "┌         ┐\n\
                   │ 1 2 0 0 │\n\
                   │ 3 4 0 0 │\n\
                   │ 0 0 5 0 │\n\
                   │ 0 0 0 6 │\n\
                   └         ┘";
    assert_eq!(format!("{}", a), correct);
    Ok(())
}
Source

pub fn mat_vec_mul( &self, v: &mut NumVector<T>, alpha: T, u: &NumVector<T>, ) -> Result<(), StrError>

Performs the matrix-vector multiplication

 v  :=  α ⋅  a   ⋅  u
(m)        (m,n)   (n)
§Input
  • u – Vector with dimension equal to the number of columns of the matrix
§Output
  • v – Vector with dimension equal to the number of rows of the matrix
§Note

This method is not highly efficient but should useful in verifications.

§Examples
use russell_lab::{Matrix, Vector};
use russell_sparse::prelude::*;
use russell_sparse::StrError;

fn main() -> Result<(), StrError> {
    // set sparse matrix (3 x 3) with 6 non-zeros
    let (nrow, ncol, max_nnz) = (3, 3, 6);
    let mut coo = CooMatrix::new(nrow, ncol, max_nnz, Sym::No)?;
    coo.put(0, 0, 1.0)?;
    coo.put(1, 0, 2.0)?;
    coo.put(1, 1, 3.0)?;
    coo.put(2, 0, 4.0)?;
    coo.put(2, 1, 5.0)?;
    coo.put(2, 2, 6.0)?;

    // check matrix
    let a = coo.as_dense();
    let correct_a = "┌       ┐\n\
                     │ 1 0 0 │\n\
                     │ 2 3 0 │\n\
                     │ 4 5 6 │\n\
                     └       ┘";
    assert_eq!(format!("{}", a), correct_a);

    // perform mat-vec-mul
    let u = Vector::from(&[1.0, 1.0, 1.0]);
    let mut v = Vector::new(nrow);
    coo.mat_vec_mul(&mut v, 1.0, &u)?;

    // check vector
    let correct_v = "┌    ┐\n\
                     │  1 │\n\
                     │  5 │\n\
                     │ 15 │\n\
                     └    ┘";
    assert_eq!(format!("{}", v), correct_v);
    Ok(())
}
Source

pub fn assign( &mut self, alpha: T, other: &NumCooMatrix<T>, ) -> Result<(), StrError>

Assigns this matrix to the values of another matrix (scaled)

Performs:

this = α · other

Warning: make sure to allocate max_nnz ≥ nnz(other).

Source

pub fn augment( &mut self, alpha: T, other: &NumCooMatrix<T>, ) -> Result<(), StrError>

Augments this matrix with the entries of another matrix (scaled)

Effectively, performs:

this += α · other

Warning: make sure to allocate max_nnz ≥ nnz(this) + nnz(other).

Source

pub fn get_info(&self) -> (usize, usize, usize, Sym)

Returns information about the dimensions and symmetric type

Returns (nrow, ncol, nnz, sym)

§Examples
use russell_sparse::prelude::*;
use russell_sparse::StrError;

fn main() -> Result<(), StrError> {
    let coo = CooMatrix::new(1, 2, 3, Sym::No)?;
    let (nrow, ncol, nnz, sym) = coo.get_info();
    assert_eq!(nrow, 1);
    assert_eq!(ncol, 2);
    assert_eq!(nnz, 0);
    assert_eq!(sym, Sym::No);
    Ok(())
}
Source

pub fn get_row_indices(&self) -> &[i32]

Get an access to the row indices

row_indices.len() == nnz
Source

pub fn get_col_indices(&self) -> &[i32]

Get an access to the column indices

col_indices.len() == nnz
Source

pub fn get_values(&self) -> &[T]

Get an access to the values

values.len() == nnz
Source

pub fn get_values_mut(&mut self) -> &mut [T]

Get a mutable access the values

values.len() == nnz

Note: the values may be modified externally, but not the indices.

Trait Implementations§

Source§

impl<T> Clone for NumCooMatrix<T>

Source§

fn clone(&self) -> NumCooMatrix<T>

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl<T> Debug for NumCooMatrix<T>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<'de, T> Deserialize<'de> for NumCooMatrix<T>

Source§

fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>
where __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
Source§

impl<T> Serialize for NumCooMatrix<T>

Source§

fn serialize<__S>(&self, __serializer: __S) -> Result<__S::Ok, __S::Error>
where __S: Serializer,

Serialize this value into the given Serde serializer. Read more

Auto Trait Implementations§

§

impl<T> Freeze for NumCooMatrix<T>

§

impl<T> RefUnwindSafe for NumCooMatrix<T>
where T: RefUnwindSafe,

§

impl<T> Send for NumCooMatrix<T>
where T: Send,

§

impl<T> Sync for NumCooMatrix<T>
where T: Sync,

§

impl<T> Unpin for NumCooMatrix<T>
where T: Unpin,

§

impl<T> UnsafeUnpin for NumCooMatrix<T>

§

impl<T> UnwindSafe for NumCooMatrix<T>
where T: UnwindSafe,

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> DeserializeOwned for T
where T: for<'de> Deserialize<'de>,