pub struct CooMat<T> { /* private fields */ }
Expand description
Coordinate (COO) format sparse matrix.
§Format
The coordinate storage format stores tuples (row, col, value)
for each
non-zero element of the matrix.
§Properties
- The coordinate format is intented for incremental matrix constructions.
- The coordinate format allows duplicates.
§Storage
Let A
a 3-by-4 (real) matrix with 6 non-zero entries:
| 0 1 0 2 |
A = | 0 0 3 0 |
| 4 5 6 0 |
In arbitrary order, ‘A’ may be stored as follows:
(row, col, val) idx
(0, 1, 1.0) [0]
(1, 2, 3.0) [1]
(2, 1, 5.0) [2]
(0, 3, 2.0) [3]
(2, 0, 4.0) [4]
(2, 2, 6.0) [5]
In row major order, A
is stored as follows:
(row, col, val) idx
(0, 1, 1.0) [0]
(0, 3, 2.0) [1]
(1, 2, 3.0) [2]
(2, 0, 4.0) [3]
(2, 1, 5.0) [4]
(2, 2, 6.0) [5]
^
| major
In column major order, A
is stored as follows:
(row, col, val) idx
(2, 0, 4.0) [0]
(0, 1, 1.0) [1]
(2, 1, 5.0) [2]
(1, 2, 3.0) [3]
(2, 2, 6.0) [4]
(0, 3, 2.0) [5]
^
| major
§Constructors
CooMat
provides multiple constructors:
// Create an empty COO matrix
let rows = 2;
let cols = 3;
let matrix = CooMat::<f64>::new(rows, cols);
// Create an empty COO matrix with initial capacity
let rows = 2;
let cols = 3;
let capacity = 6;
let matrix = CooMat::<f64>::with_capacity(rows, cols, capacity);
// Create a COO matrix with initial entries from entry vector
let rows = 2;
let cols = 2;
let entries = vec![(0, 0, 1.0), (1, 1, 2.0)];
let matrix = CooMat::with_entries(rows, cols, entries);
// Create a COO matrix with initial entries from triplet vectors
let rows = 2;
let cols = 2;
let rowind = vec![0, 1];
let colind = vec![0, 1];
let values = vec![1.0, 2.0];
let matrix = CooMat::with_triplets(rows, cols, rowind, colind, values);
§Entry get/insertion/removal/clear
CooMat
is intented for incremental matrix constructions and provides corresponding methods:
use alyx::CooMat;
let mut matrix = CooMat::with_capacity(3, 3, 9);
// matrix:
// | 0 0 0 |
// | 0 0 0 |
// | 0 0 0 |
// Insert new entries one by one
matrix.push(0, 0, 1.0);
matrix.push(0, 1, 2.0);
matrix.push(1, 0, 3.0);
matrix.push(1, 1, 4.0);
// matrix:
// | 1 2 0 |
// | 3 4 0 |
// | 0 0 0 |
// entries:
// (0, 0, 1.0) [0]
// (0, 1, 2.0) [1]
// (1, 0, 3.0) [2]
// (1, 1, 4.0) [3]
assert_eq!(matrix.len(), 4);
// Get an immutable reference to an entry
let entry = matrix.get(0);
assert_eq!(entry, Some((&0, &0, &1.0)));
// Get a mutable reference to an entry and modify it
// (only the value is mutable)
if let Some((r, c, v)) = matrix.get_mut(0) {
*v *= -1.0;
}
// matrix:
// |-1 2 0 |
// | 3 4 0 |
// | 0 0 0 |
// entries:
// (0, 0,-1.0) [0]
// (0, 1, 2.0) [1]
// (1, 0, 3.0) [2]
// (1, 1, 4.0) [3]
let entry = matrix.get(0);
assert_eq!(entry, Some((&0, &0, &-1.0)));
// Extend the matrix with new entries
let entries = vec![
(0, 2, 5.0),
(1, 2, 6.0),
(2, 1, 8.0),
(2, 2, 9.0),
];
matrix.extend(entries);
// matrix:
// |-1 2 5 |
// | 3 4 6 |
// | 0 8 9 |
// entries:
// (0, 0,-1.0) [0]
// (0, 1, 2.0) [1]
// (1, 0, 3.0) [2]
// (1, 1, 4.0) [3]
// (0, 2, 5.0) [4] <|
// (1, 2, 6.0) [5] <|
// (2, 1, 8.0) [6] <|
// (2, 2, 9.0) [7] <|- entries added
assert_eq!(matrix.len(), 8);
// Insert new entry at specified index
matrix.insert(6, 2, 0, 7.0);
// matrix:
// |-1 2 5 |
// | 3 4 6 |
// | 7 8 9 |
// entries:
// (0, 0,-1.0) [0]
// (0, 1, 2.0) [1]
// (1, 0, 3.0) [2]
// (1, 1, 4.0) [3]
// (0, 2, 5.0) [4]
// (1, 2, 6.0) [5]
// (2, 0, 7.0) [6] <- entry inserted
// (2, 1, 8.0) [7] <|
// (2, 2, 9.0) [8] <|- indices shifted
assert_eq!(matrix.len(), 9);
assert_eq!(matrix.get(6), Some((&2, &0, &7.0)));
// Remove last entry
assert_eq!(matrix.pop(), Some((2, 2, 9.0)));
// matrix:
// |-1 2 5 |
// | 3 4 6 |
// | 7 8 0 |
// entries:
// (0, 0,-1.0) [0]
// (0, 1, 2.0) [1]
// (1, 0, 3.0) [2]
// (1, 1, 4.0) [3]
// (0, 2, 5.0) [4]
// (1, 2, 6.0) [5]
// (2, 0, 7.0) [6]
// (2, 1, 8.0) [7]
// (2, 2, 9.0) [x] <- entry removed
assert_eq!(matrix.len(), 8);
// Remove a specific entry
let entry = matrix.remove(1);
assert_eq!(entry, (0, 1, 2.0));
// matrix:
// |-1 0 5 |
// | 3 4 6 |
// | 7 8 0 |
// entries:
// (0, 0,-1.0) [0]
// (0, 1, 2.0) [x] <- entry removed
// (1, 0, 3.0) [1] <|
// (1, 1, 4.0) [2] <|
// (0, 2, 5.0) [3] <|
// (1, 2, 6.0) [4] <|
// (2, 0, 7.0) [5] <|
// (2, 1, 8.0) [6] <|- indices shifted
assert_eq!(matrix.len(), 7);
// Clear matrix
matrix.clear();
assert!(matrix.is_empty())
§Capacity and Length
The matrix capacity corresponds to the amount of space allocated for the matrix entries unlike the matrix length which corresponds to the number of entries in the matrix. Initially for empty matrices, no memory is allocated. If entries are inserted, matrix capacity will grow accordingly. The growth strategy is unspecified behavior and no guarentees are made.
CooMat
provides multiple methods to manage matrix capacity and length:
let mut matrix: CooMat<f64> = CooMat::new(2, 2);
// Initially capacity and length are 0
assert_eq!(matrix.capacity(), 0);
assert_eq!(matrix.len(), 0);
// Inserting an entry allocate space for at least one entry
matrix.push(0, 0, 1.0);
assert!(matrix.capacity() >= 1);
assert_eq!(matrix.len(), 1);
// Inserting additional entries may reallocate
matrix.push(1, 1, 2.0);
assert!(matrix.capacity() >= 2);
assert_eq!(matrix.len(), 2);
// To prevent reallocation, capacity can be adjusted at construction time
let mut matrix: CooMat<f64> = CooMat::with_capacity(2, 2, 4);
assert_eq!(matrix.capacity(), 4);
assert!(matrix.is_empty());
// Pushing values will not reallocate
matrix.push(0, 0, 1.0);
assert_eq!(matrix.capacity(), 4);
assert_eq!(matrix.len(), 1);
// Additional capacity can be requested after construction
let mut matrix: CooMat<f64> = CooMat::with_capacity(2, 2, 1);
assert_eq!(matrix.capacity(), 1);
matrix.reserve(4);
assert!(matrix.capacity() >= 4);
// Capacity can be shrunk to fit actual number of entries
let mut matrix: CooMat<f64> = CooMat::with_capacity(3, 3, 9);
assert_eq!(matrix.capacity(), 9);
matrix.push(1, 1, 1.0);
matrix.shrink();
assert!(matrix.capacity() < 9);
§Iterators
CooMat
also provides convenient iterators (Iter
, IterMut
and
IntoIter
):
let entries = vec![
(0, 0, 1.0),
(0, 1, 2.0),
(1, 0, 3.0),
(1, 1, 4.0),
];
let mut matrix = CooMat::with_entries(2, 2, entries);
// Immutable iterator over entries
let mut iter = matrix.iter();
assert_eq!(iter.next(), Some((&0, &0, &1.0)));
assert_eq!(iter.next(), Some((&0, &1, &2.0)));
assert_eq!(iter.next(), Some((&1, &0, &3.0)));
assert_eq!(iter.next(), Some((&1, &1, &4.0)));
assert_eq!(iter.next(), None);
// Mutable iterator over entries
let mut iter = matrix.iter_mut();
for (r, c, v) in iter {
*v *= 2.0;
}
let mut iter = matrix.iter();
assert_eq!(iter.next(), Some((&0, &0, &2.0)));
assert_eq!(iter.next(), Some((&0, &1, &4.0)));
assert_eq!(iter.next(), Some((&1, &0, &6.0)));
assert_eq!(iter.next(), Some((&1, &1, &8.0)));
assert_eq!(iter.next(), None);
// Turn matrix into iterator
for (r, c, v) in matrix {
println!("row = {}, col = {}, value = {}", r, c, v);
}
Implementations§
Source§impl<T> CooMat<T>
impl<T> CooMat<T>
Sourcepub fn new(rows: usize, cols: usize) -> Self
pub fn new(rows: usize, cols: usize) -> Self
Creates a coordinate format sparse matrix with specified shape
(rows, cols)
.
The created matrix has following properties:
- the matrix is empty (
matrix.len() == 0
) - the matrix does not allocate memory (
matrix.capacity() == 0
) - the matrix will not allocate memory before any insert/push/extend operation
§Examples
// With type annotation ...
let matrix: CooMat<f64> = CooMat::new(2, 2);
assert_eq!(matrix.shape(), (2, 2));
assert!(matrix.is_empty());
assert_eq!(matrix.capacity(), 0);
// ... or with turbofish operator
let matrix = CooMat::<f64>::new(3, 4);
assert_eq!(matrix.shape(), (3, 4));
assert!(matrix.is_empty());
assert_eq!(matrix.capacity(), 0);
§Panics
Panics if:
size_of::<T> == 0
rows == 0
cols == 0
Sourcepub fn with_capacity(rows: usize, cols: usize, capacity: usize) -> Self
pub fn with_capacity(rows: usize, cols: usize, capacity: usize) -> Self
Creates a coordinate format sparse matrix with specified shape
(rows, cols)
and capacity.
The created matrix has following properties:
- the matrix is empty (
matrix.len() == 0
) - the matrix allocates memory for at least
capacity
entries (matrix.capacity() >= capacity
) - the matrix will not allocate if
capacity == 0
§Examples
let matrix = CooMat::<f64>::with_capacity(2, 2, 4);
assert_eq!(matrix.shape(), (2, 2));
assert!(matrix.is_empty());
assert_eq!(matrix.capacity(), 4);
§Panics
Panics if:
size_of::<T> == 0
rows == 0
cols == 0
- the allocation size exceeds
isize::MAX
bytes
Sourcepub fn with_entries(
rows: usize,
cols: usize,
entries: impl IntoIterator<Item = (usize, usize, T)>,
) -> Self
pub fn with_entries( rows: usize, cols: usize, entries: impl IntoIterator<Item = (usize, usize, T)>, ) -> Self
Creates a coordinate format sparse matrix with specified shape
(rows, cols)
and entries.
The created matrix has following properties:
- the matrix is filled with
entries
- the matrix allocates memory for at least
entries.len()
entries
§Examples
let entries = vec![
(0, 0, 1.0),
(0, 1, 2.0),
(1, 0, 3.0),
(1, 1, 4.0),
];
let matrix = CooMat::with_entries(2, 2, entries);
assert_eq!(matrix.shape(), (2, 2));
assert_eq!(matrix.len(), 4);
assert!(matrix.capacity() >= 4);
§Panics
Panics if:
size_of::<T> == 0
rows == 0
cols == 0
- for any entry
(row, col, val)
:row >= rows
orcol >= cols
Sourcepub fn with_capacity_and_entries(
rows: usize,
cols: usize,
capacity: usize,
entries: impl IntoIterator<Item = (usize, usize, T)>,
) -> Self
pub fn with_capacity_and_entries( rows: usize, cols: usize, capacity: usize, entries: impl IntoIterator<Item = (usize, usize, T)>, ) -> Self
Creates a coordinate format sparse matrix with specified shape
(rows, cols)
, capacity and entries.
The created matrix has following properties:
- the matrix is filled with
entries
- the matrix allocates memory for at least
max(capacity, entries.len())
entries
§Examples
let entries = vec![
(0, 0, 1.0),
(0, 1, 2.0),
(1, 0, 3.0),
(1, 1, 4.0),
];
let matrix = CooMat::with_capacity_and_entries(2, 2, 4, entries);
assert_eq!(matrix.shape(), (2, 2));
assert_eq!(matrix.len(), 4);
assert_eq!(matrix.capacity(), 4);
§Panics
Panics if:
size_of::<T> == 0
rows == 0
cols == 0
- for any entry
(row, col, val)
:row >= rows
orcol >= cols
- the allocation size exceeds
isize::MAX
bytes
Sourcepub fn with_triplets(
rows: usize,
cols: usize,
rowind: impl IntoIterator<Item = usize>,
colind: impl IntoIterator<Item = usize>,
values: impl IntoIterator<Item = T>,
) -> Self
pub fn with_triplets( rows: usize, cols: usize, rowind: impl IntoIterator<Item = usize>, colind: impl IntoIterator<Item = usize>, values: impl IntoIterator<Item = T>, ) -> Self
Creates a coordinate format sparse matrix with specified shape
(rows, cols)
and triplets.
The created matrix has following properties:
- the matrix is filled with
values.len()
entries - the matrix allocates memory for at least
values.len()
entries
§Examples
let rowind = vec![0, 0, 1, 1]; // entry row indices
let colind = vec![0, 1, 0, 1]; // entry column indices
let values = vec![1.0, 2.0, 3.0, 4.0]; // entry values
let matrix = CooMat::with_triplets(2, 2, rowind, colind, values);
assert_eq!(matrix.shape(), (2, 2));
assert_eq!(matrix.len(), 4);
assert!(matrix.capacity() >= 4);
§Panics
Panics if:
size_of::<T> == 0
rows == 0
cols == 0
- for any entry
(row, col, val)
:row >= rows
orcol >= cols
rowind
,colind
andvalues
length differ
Sourcepub fn with_capacity_and_triplets(
rows: usize,
cols: usize,
capacity: usize,
rowind: impl IntoIterator<Item = usize>,
colind: impl IntoIterator<Item = usize>,
values: impl IntoIterator<Item = T>,
) -> Self
pub fn with_capacity_and_triplets( rows: usize, cols: usize, capacity: usize, rowind: impl IntoIterator<Item = usize>, colind: impl IntoIterator<Item = usize>, values: impl IntoIterator<Item = T>, ) -> Self
Creates a coordinate format sparse matrix with specified shape
(rows, cols)
, capacity and triplets.
The created matrix has following properties:
- the matrix is filled with
values.len()
entries - the matrix allocates memory for at least
max(capacity, values.len())
entries
§Examples
let rowind = vec![0, 0, 1, 1]; // entry row indices
let colind = vec![0, 1, 0, 1]; // entry column indices
let values = vec![1.0, 2.0, 3.0, 4.0]; // entry values
let matrix = CooMat::with_capacity_and_triplets(
2, 2, 4,
rowind,
colind,
values
);
assert_eq!(matrix.shape(), (2, 2));
assert_eq!(matrix.len(), 4);
assert_eq!(matrix.capacity(), 4);
§Panics
Panics if:
size_of::<T> == 0
rows == 0
cols == 0
- for any entry
(row, col, val)
:row >= rows
orcol >= cols
rowind
,colind
andvalues
length differ- the allocation size exceeds
isize::MAX
bytes
Sourcepub fn rows(&self) -> usize
pub fn rows(&self) -> usize
Returns the number of rows of the matrix.
§Examples
let matrix = CooMat::<f64>::new(1, 2);
assert_eq!(matrix.rows(), 1);
Sourcepub fn cols(&self) -> usize
pub fn cols(&self) -> usize
Returns the number of columns of the matrix.
§Examples
let matrix = CooMat::<f64>::new(1, 2);
assert_eq!(matrix.cols(), 2);
Sourcepub fn shape(&self) -> (usize, usize)
pub fn shape(&self) -> (usize, usize)
Returns the shape (rows, cols)
of the matrix.
§Examples
let matrix = CooMat::<f64>::new(1, 2);
assert_eq!(matrix.shape(), (1, 2));
Sourcepub fn len(&self) -> usize
pub fn len(&self) -> usize
Returns the number of entries of the matrix.
This number is not the number of non-zero elements in the matrix because duplicates are allowed.
§Examples
let entries = vec![
(0, 0, 1.0),
(0, 1, 2.0),
(1, 0, 3.0),
(1, 1, 4.0),
];
let matrix = CooMat::with_entries(2, 2, entries);
assert_eq!(matrix.len(), 4);
Sourcepub fn is_empty(&self) -> bool
pub fn is_empty(&self) -> bool
Returns true
if the matrix contains no entry.
§Examples
let entries = vec![
(0, 0, 1.0),
(0, 1, 2.0),
(1, 0, 3.0),
(1, 1, 4.0),
];
let matrix = CooMat::with_entries(2, 2, entries);
let empty = CooMat::<f64>::new(2, 2);
assert!(!matrix.is_empty());
assert!(empty.is_empty());
Sourcepub fn capacity(&self) -> usize
pub fn capacity(&self) -> usize
Returns the capacity of the matrix.
§Examples
let matrix = CooMat::<f64>::with_capacity(1, 1, 42);
assert_eq!(matrix.capacity(), 42);
Sourcepub fn shrink(&mut self)
pub fn shrink(&mut self)
Shrink matrix capacity.
§Examples
let mut matrix = CooMat::<f64>::with_capacity(1, 1, 42);
assert_eq!(matrix.capacity(), 42);
matrix.shrink();
assert!(matrix.capacity() <= 42);
Sourcepub fn truncate(&mut self, len: usize)
pub fn truncate(&mut self, len: usize)
Shortens the matrix to len
.
§Examples
let entries = vec![
(0, 0, 1.0),
(0, 1, 2.0),
(1, 0, 3.0),
(1, 1, 4.0),
];
let mut matrix = CooMat::with_entries(2, 2, entries);
assert_eq!(matrix.len(), 4);
matrix.truncate(4);
assert_eq!(matrix.len(), 4);
matrix.truncate(2);
assert_eq!(matrix.len(), 2);
§Panics
Panics if len > self.len()
Sourcepub fn clear(&mut self)
pub fn clear(&mut self)
Clears the matrix.
§Examples
let entries = vec![
(0, 0, 1.0),
(0, 1, 2.0),
(1, 0, 3.0),
(1, 1, 4.0),
];
let mut matrix = CooMat::with_entries(2, 2, entries);
matrix.clear();
assert!(matrix.is_empty());
Sourcepub fn get(&self, index: usize) -> Option<(&usize, &usize, &T)>
pub fn get(&self, index: usize) -> Option<(&usize, &usize, &T)>
Returns an immutable reference to the entry at specified index.
§Examples
let entries = vec![(0, 0, 1.0)];
let matrix = CooMat::with_entries(1, 1, entries);
assert_eq!(matrix.get(0), Some((&0, &0, &1.0)));
Sourcepub fn get_mut(&mut self, index: usize) -> Option<(&usize, &usize, &mut T)>
pub fn get_mut(&mut self, index: usize) -> Option<(&usize, &usize, &mut T)>
Returns a mutable reference to the entry at specified index.
§Examples
let entries = vec![(0, 0, 1.0)];
let mut matrix = CooMat::with_entries(1, 1, entries);
if let Some((_, _, v)) = matrix.get_mut(0) {
*v *= 2.0;
}
assert_eq!(matrix.get_mut(0), Some((&0, &0, &mut 2.0)));
Sourcepub fn pop(&mut self) -> Option<(usize, usize, T)>
pub fn pop(&mut self) -> Option<(usize, usize, T)>
Pop entry from the matrix.
§Examples
let entries = vec![(0, 0, 1.0)];
let mut matrix = CooMat::with_entries(1, 1, entries);
assert_eq!(matrix.pop(), Some((0, 0, 1.0)));
assert_eq!(matrix.pop(), None);
Sourcepub fn extend<I: IntoIterator<Item = (usize, usize, T)>>(&mut self, iter: I)
pub fn extend<I: IntoIterator<Item = (usize, usize, T)>>(&mut self, iter: I)
Sourcepub fn iter(&self) -> Iter<'_, T>
pub fn iter(&self) -> Iter<'_, T>
Returns an iterator visiting all entries of the matrix.
The iterator element type is (&'a usize, &'a usize, &'a T)
.
§Examples
let entries = vec![
(0, 0, 1.0),
(0, 1, 2.0),
(1, 0, 3.0),
(1, 1, 4.0),
];
let matrix = CooMat::with_entries(2, 2, entries);
let mut iter = matrix.iter();
assert_eq!(iter.next(), Some((&0, &0, &1.0)));
assert_eq!(iter.next(), Some((&0, &1, &2.0)));
assert_eq!(iter.next(), Some((&1, &0, &3.0)));
assert_eq!(iter.next(), Some((&1, &1, &4.0)));
assert_eq!(iter.next(), None);
Sourcepub fn iter_mut(&mut self) -> IterMut<'_, T>
pub fn iter_mut(&mut self) -> IterMut<'_, T>
Returns an iterator visiting all mutable entries of the matrix.
The iterator element type is (&'a usize, &'a usize, &'a mut T)
.
§Examples
let entries = vec![
(0, 0, 1.0),
(0, 1, 2.0),
(1, 0, 3.0),
(1, 1, 4.0),
];
let mut matrix = CooMat::with_entries(2, 2, entries);
let mut iter = matrix.iter_mut();
for (_, _, v) in iter {
*v *= 2.0;
}
let mut iter = matrix.iter_mut();
assert_eq!(iter.next(), Some((&0, &0, &mut 2.0)));
assert_eq!(iter.next(), Some((&0, &1, &mut 4.0)));
assert_eq!(iter.next(), Some((&1, &0, &mut 6.0)));
assert_eq!(iter.next(), Some((&1, &1, &mut 8.0)));
assert_eq!(iter.next(), None);