mirror of
https://github.com/cberner/raptorq.git
synced 2024-06-29 18:21:43 +00:00
Merge SparseVec into SparseOctetVec
This commit is contained in:
parent
8f8637be8a
commit
f0f0f98247
@ -1,7 +1,7 @@
|
||||
use crate::octet::Octet;
|
||||
use crate::octets::fused_addassign_mul_scalar;
|
||||
use crate::octets::{add_assign, count_ones_and_nonzeros, mulassign_scalar};
|
||||
use crate::sparse_vec::{SparseOctetVec, SparseVec};
|
||||
use crate::sparse_vec::{SparseOctetVec, SparseValuelessVec};
|
||||
use crate::util::get_both_indices;
|
||||
use std::cmp::min;
|
||||
|
||||
@ -32,7 +32,7 @@ pub struct BorrowedKeyIter<'a> {
|
||||
sparse: bool,
|
||||
dense_index: usize,
|
||||
dense_end: usize,
|
||||
sparse_rows: Option<&'a Vec<(usize, ())>>,
|
||||
sparse_rows: Option<&'a Vec<(usize, Octet)>>,
|
||||
sparse_start_row: usize,
|
||||
sparse_end_row: usize,
|
||||
sparse_index: usize,
|
||||
@ -397,7 +397,7 @@ pub struct SparseOctetMatrix {
|
||||
dense_elements: Vec<Vec<u8>>,
|
||||
// Sparse vector indicating which rows may have a non-zero value in the given column
|
||||
// Does not guarantee that the row has a non-zero value, since FMA may have added to zero
|
||||
sparse_column_index: Vec<SparseVec<()>>,
|
||||
sparse_column_index: Vec<SparseValuelessVec>,
|
||||
// Mapping of logical row numbers to index in sparse_elements, dense_elements, and sparse_column_index
|
||||
logical_row_to_physical: Vec<usize>,
|
||||
physical_row_to_logical: Vec<usize>,
|
||||
@ -440,7 +440,7 @@ impl OctetMatrix for SparseOctetMatrix {
|
||||
let mut column_index = Vec::with_capacity(width);
|
||||
#[allow(clippy::needless_range_loop)]
|
||||
for i in 0..width {
|
||||
column_index.push(SparseVec::with_capacity(10));
|
||||
column_index.push(SparseValuelessVec::with_capacity(10));
|
||||
col_mapping[i] = i;
|
||||
}
|
||||
SparseOctetMatrix {
|
||||
@ -467,7 +467,7 @@ impl OctetMatrix for SparseOctetMatrix {
|
||||
self.sparse_elements[physical_i].insert(physical_j, value);
|
||||
}
|
||||
if !self.column_index_disabled {
|
||||
self.sparse_column_index[physical_j].insert(physical_i, ());
|
||||
self.sparse_column_index[physical_j].insert(physical_i);
|
||||
}
|
||||
}
|
||||
|
||||
@ -532,7 +532,7 @@ impl OctetMatrix for SparseOctetMatrix {
|
||||
unimplemented!("It was assumed that this wouldn't be needed, because the method would only be called on the V section of matrix A");
|
||||
}
|
||||
let physical_row = self.logical_row_to_physical[row];
|
||||
let sparse_elements = &self.sparse_elements[physical_row].elements.elements;
|
||||
let sparse_elements = &self.sparse_elements[physical_row].elements;
|
||||
OctetIter {
|
||||
sparse: true,
|
||||
start_col,
|
||||
@ -551,7 +551,7 @@ impl OctetMatrix for SparseOctetMatrix {
|
||||
sparse: true,
|
||||
dense_index: 0,
|
||||
dense_end: 0,
|
||||
sparse_rows: Some(&self.sparse_column_index[physical_col].elements),
|
||||
sparse_rows: Some(&self.sparse_column_index[physical_col].elements.elements),
|
||||
sparse_start_row: start_row,
|
||||
sparse_end_row: end_row,
|
||||
sparse_index: 0,
|
||||
@ -598,7 +598,7 @@ impl OctetMatrix for SparseOctetMatrix {
|
||||
}
|
||||
let mut physical_row = 0;
|
||||
let physical_i = self.logical_col_to_physical[i];
|
||||
for (maybe_present_in_row, _) in self.sparse_column_index[physical_i].keys_values() {
|
||||
for maybe_present_in_row in self.sparse_column_index[physical_i].keys() {
|
||||
while physical_row < *maybe_present_in_row {
|
||||
physical_row += 1;
|
||||
}
|
||||
@ -647,7 +647,7 @@ impl OctetMatrix for SparseOctetMatrix {
|
||||
self.dense_elements[physical_row] = temp_dense.pop().unwrap();
|
||||
if !self.column_index_disabled {
|
||||
for (col, _) in self.sparse_elements[physical_row].keys_values() {
|
||||
self.sparse_column_index[*col].insert(physical_row, ())
|
||||
self.sparse_column_index[*col].insert(physical_row)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -690,7 +690,7 @@ impl OctetMatrix for SparseOctetMatrix {
|
||||
let new_columns = dest_row.fma(temp_row, scalar);
|
||||
if !self.column_index_disabled {
|
||||
for new_col in new_columns {
|
||||
self.sparse_column_index[new_col].insert(physical_dest, ());
|
||||
self.sparse_column_index[new_col].insert(physical_dest);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2,99 +2,55 @@ use crate::octet::Octet;
|
||||
use std::cmp::Ordering;
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub struct SparseVec<T: Clone> {
|
||||
pub struct SparseOctetVec {
|
||||
// Kept sorted by the usize (key)
|
||||
pub elements: Vec<(usize, T)>,
|
||||
pub elements: Vec<(usize, Octet)>,
|
||||
}
|
||||
|
||||
impl<T: Clone> SparseVec<T> {
|
||||
pub fn with_capacity(capacity: usize) -> SparseVec<T> {
|
||||
SparseVec {
|
||||
impl SparseOctetVec {
|
||||
pub fn with_capacity(capacity: usize) -> SparseOctetVec {
|
||||
SparseOctetVec {
|
||||
elements: Vec::with_capacity(capacity),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn retain<P: Fn(&(usize, T)) -> bool>(&mut self, predicate: P) {
|
||||
self.elements.retain(predicate);
|
||||
}
|
||||
|
||||
// Returns the internal index into self.elements matching key i, or the index
|
||||
// at which it can be inserted (maintaining sorted order)
|
||||
fn key_to_internal_index(&self, i: usize) -> Result<usize, usize> {
|
||||
self.elements.binary_search_by_key(&i, |(index, _)| *index)
|
||||
}
|
||||
|
||||
pub fn remove(&mut self, i: usize) -> Option<T> {
|
||||
match self.key_to_internal_index(i) {
|
||||
Ok(index) => Some(self.elements.remove(index).1),
|
||||
Err(_) => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get(&self, i: usize) -> Option<&T> {
|
||||
match self.key_to_internal_index(i) {
|
||||
Ok(index) => Some(&self.elements[index].1),
|
||||
Err(_) => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn keys_values(&self) -> impl Iterator<Item = &(usize, T)> {
|
||||
self.elements.iter()
|
||||
}
|
||||
|
||||
pub fn insert(&mut self, i: usize, value: T) {
|
||||
match self.key_to_internal_index(i) {
|
||||
Ok(index) => self.elements[index] = (i, value),
|
||||
Err(index) => self.elements.insert(index, (i, value)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub struct SparseOctetVec {
|
||||
// Kept sorted by the usize (key)
|
||||
pub elements: SparseVec<Octet>,
|
||||
}
|
||||
|
||||
impl SparseOctetVec {
|
||||
pub fn with_capacity(capacity: usize) -> SparseOctetVec {
|
||||
SparseOctetVec {
|
||||
elements: SparseVec::with_capacity(capacity),
|
||||
}
|
||||
}
|
||||
|
||||
// Returns a vector of new column indices that this row contains
|
||||
pub fn fma(&mut self, other: &SparseOctetVec, scalar: &Octet) -> Vec<usize> {
|
||||
// Fast path for a single value that's being eliminated
|
||||
// TODO: Probably wouldn't need this if we implemented "Furthermore, the row operations
|
||||
// required for the HDPC rows may be performed for all such rows in one
|
||||
// process, by using the algorithm described in Section 5.3.3.3."
|
||||
if other.elements.elements.len() == 1 {
|
||||
let (other_col, other_value) = &other.elements.elements[0];
|
||||
match self.elements.key_to_internal_index(*other_col) {
|
||||
if other.elements.len() == 1 {
|
||||
let (other_col, other_value) = &other.elements[0];
|
||||
match self.key_to_internal_index(*other_col) {
|
||||
Ok(index) => {
|
||||
let elements_len = self.elements.elements.len();
|
||||
let self_value = &mut self.elements.elements[index].1;
|
||||
let elements_len = self.elements.len();
|
||||
let self_value = &mut self.elements[index].1;
|
||||
self_value.fma(other_value, scalar);
|
||||
// XXX: heuristic for handling large rows, since these are somewhat common (HDPC rows)
|
||||
// It would be very expensive to always remove from those rows
|
||||
if elements_len < 1000 && *self_value == Octet::zero() {
|
||||
self.elements.elements.remove(index);
|
||||
self.elements.remove(index);
|
||||
}
|
||||
}
|
||||
Err(index) => {
|
||||
let value = other_value * scalar;
|
||||
self.elements.elements.insert(index, (*other_col, value));
|
||||
self.elements.insert(index, (*other_col, value));
|
||||
return vec![*other_col];
|
||||
}
|
||||
};
|
||||
return vec![];
|
||||
}
|
||||
|
||||
let mut result =
|
||||
Vec::with_capacity(self.elements.elements.len() + other.elements.elements.len());
|
||||
let mut self_iter = self.elements.elements.iter();
|
||||
let mut other_iter = other.elements.elements.iter();
|
||||
let mut result = Vec::with_capacity(self.elements.len() + other.elements.len());
|
||||
let mut self_iter = self.elements.iter();
|
||||
let mut other_iter = other.elements.iter();
|
||||
let mut self_entry = self_iter.next();
|
||||
let mut other_entry = other_iter.next();
|
||||
|
||||
@ -141,13 +97,16 @@ impl SparseOctetVec {
|
||||
break;
|
||||
}
|
||||
}
|
||||
self.elements.elements = result;
|
||||
self.elements = result;
|
||||
|
||||
return new_columns;
|
||||
}
|
||||
|
||||
pub fn remove(&mut self, i: usize) -> Option<Octet> {
|
||||
self.elements.remove(i)
|
||||
match self.key_to_internal_index(i) {
|
||||
Ok(index) => Some(self.elements.remove(index).1),
|
||||
Err(_) => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn retain<P: Fn(&(usize, Octet)) -> bool>(&mut self, predicate: P) {
|
||||
@ -155,21 +114,53 @@ impl SparseOctetVec {
|
||||
}
|
||||
|
||||
pub fn get(&self, i: usize) -> Option<&Octet> {
|
||||
self.elements.get(i)
|
||||
match self.key_to_internal_index(i) {
|
||||
Ok(index) => Some(&self.elements[index].1),
|
||||
Err(_) => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn mul_assign(&mut self, scalar: &Octet) {
|
||||
for (_, value) in self.elements.elements.iter_mut() {
|
||||
for (_, value) in self.elements.iter_mut() {
|
||||
*value = value as &Octet * scalar;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn keys_values(&self) -> impl Iterator<Item = &(usize, Octet)> {
|
||||
self.elements.keys_values()
|
||||
self.elements.iter()
|
||||
}
|
||||
|
||||
pub fn insert(&mut self, i: usize, value: Octet) {
|
||||
self.elements.insert(i, value);
|
||||
match self.key_to_internal_index(i) {
|
||||
Ok(index) => self.elements[index] = (i, value),
|
||||
Err(index) => self.elements.insert(index, (i, value)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub struct SparseValuelessVec {
|
||||
pub elements: SparseOctetVec,
|
||||
}
|
||||
|
||||
impl SparseValuelessVec {
|
||||
pub fn with_capacity(capacity: usize) -> SparseValuelessVec {
|
||||
SparseValuelessVec {
|
||||
elements: SparseOctetVec::with_capacity(capacity),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(debug_assertions)]
|
||||
pub fn get(&self, i: usize) -> Option<()> {
|
||||
self.elements.get(i).map(|_| ())
|
||||
}
|
||||
|
||||
pub fn keys(&self) -> impl Iterator<Item = &usize> {
|
||||
self.elements.keys_values().map(|(key, _)| key)
|
||||
}
|
||||
|
||||
pub fn insert(&mut self, i: usize) {
|
||||
self.elements.insert(i, Octet::zero())
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user