raptorq/src/sparse_vec.rs

146 lines
4.7 KiB
Rust
Raw Permalink Normal View History

#[cfg(feature = "std")]
use std::{cmp::Ordering, mem::size_of, vec::Vec};
#[cfg(not(feature = "std"))]
use core::{cmp::Ordering, mem::size_of};
#[cfg(not(feature = "std"))]
use alloc::vec::Vec;
2020-01-04 20:07:52 +00:00
use crate::octet::Octet;
2020-08-30 05:35:08 +00:00
#[derive(Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Hash)]
pub struct SparseBinaryVec {
// Kept sorted by the usize (key). Only ones are stored, zeros are implicit
elements: Vec<u16>,
2020-01-04 20:07:52 +00:00
}
impl SparseBinaryVec {
pub fn with_capacity(capacity: usize) -> SparseBinaryVec {
// Matrix width can never exceed maximum L
debug_assert!(capacity < 65536);
SparseBinaryVec {
2020-01-04 20:07:52 +00:00
elements: Vec::with_capacity(capacity),
}
}
// 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: u16) -> Result<usize, usize> {
self.elements.binary_search(&i)
2020-01-04 20:07:52 +00:00
}
2020-01-13 00:56:45 +00:00
pub fn size_in_bytes(&self) -> usize {
size_of::<Self>() + size_of::<u16>() * self.elements.len()
2020-01-13 00:56:45 +00:00
}
pub fn len(&self) -> usize {
self.elements.len()
}
pub fn get_by_raw_index(&self, i: usize) -> (usize, Octet) {
(self.elements[i] as usize, Octet::one())
}
2020-01-16 06:14:22 +00:00
// Returns true, if a new column was added
pub fn add_assign(&mut self, other: &SparseBinaryVec) -> bool {
2020-01-04 20:07:52 +00:00
// Fast path for a single value that's being eliminated
2020-01-04 20:26:58 +00:00
if other.elements.len() == 1 {
let other_index = &other.elements[0];
match self.key_to_internal_index(*other_index) {
2020-01-04 20:07:52 +00:00
Ok(index) => {
// Adding 1 + 1 = 0 in GF(256), so remove this
self.elements.remove(index);
2020-01-04 20:07:52 +00:00
}
Err(index) => {
self.elements.insert(index, *other_index);
2020-01-16 06:14:22 +00:00
return true;
2020-01-04 20:07:52 +00:00
}
};
2020-01-16 06:14:22 +00:00
return false;
2020-01-04 20:07:52 +00:00
}
2020-01-04 20:26:58 +00:00
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_next = self_iter.next();
let mut other_next = other_iter.next();
2020-01-04 20:07:52 +00:00
2020-01-16 06:14:22 +00:00
let mut column_added = false;
2020-01-04 20:07:52 +00:00
loop {
if let Some(self_index) = self_next {
if let Some(other_index) = other_next {
2021-10-22 00:50:01 +00:00
match self_index.cmp(other_index) {
2020-01-04 20:07:52 +00:00
Ordering::Less => {
2020-06-24 03:26:18 +00:00
result.push(*self_index);
self_next = self_iter.next();
2020-01-04 20:07:52 +00:00
}
Ordering::Equal => {
// Adding 1 + 1 = 0 in GF(256), so skip this index
self_next = self_iter.next();
other_next = other_iter.next();
2020-01-04 20:07:52 +00:00
}
Ordering::Greater => {
2020-01-16 06:14:22 +00:00
column_added = true;
result.push(*other_index);
other_next = other_iter.next();
2020-01-04 20:07:52 +00:00
}
}
} else {
result.push(*self_index);
self_next = self_iter.next();
2020-01-04 20:07:52 +00:00
}
} else if let Some(other_index) = other_next {
2020-01-16 06:14:22 +00:00
column_added = true;
result.push(*other_index);
other_next = other_iter.next();
2020-01-04 20:07:52 +00:00
} else {
break;
}
}
2020-01-04 20:26:58 +00:00
self.elements = result;
2020-01-04 20:07:52 +00:00
2020-01-16 06:14:22 +00:00
return column_added;
2020-01-04 20:07:52 +00:00
}
pub fn remove(&mut self, i: usize) -> Option<Octet> {
match self.key_to_internal_index(i as u16) {
Ok(index) => {
self.elements.remove(index);
Some(Octet::one())
}
2020-01-04 20:26:58 +00:00
Err(_) => None,
}
2020-01-04 20:07:52 +00:00
}
pub fn retain<P: Fn(&(usize, Octet)) -> bool>(&mut self, predicate: P) {
self.elements
.retain(|entry| predicate(&(*entry as usize, Octet::one())));
2020-01-04 20:07:52 +00:00
}
pub fn get(&self, i: usize) -> Option<Octet> {
match self.key_to_internal_index(i as u16) {
Ok(_) => Some(Octet::one()),
2020-01-04 20:26:58 +00:00
Err(_) => None,
}
2020-01-04 20:07:52 +00:00
}
pub fn keys_values(&self) -> impl Iterator<Item = (usize, Octet)> + '_ {
self.elements
.iter()
.map(|entry| (*entry as usize, Octet::one()))
2020-01-04 20:07:52 +00:00
}
pub fn insert(&mut self, i: usize, value: Octet) {
debug_assert!(i < 65536);
if value == Octet::zero() {
self.remove(i);
} else {
match self.key_to_internal_index(i as u16) {
Ok(_) => {}
Err(index) => self.elements.insert(index, i as u16),
}
2020-01-04 20:26:58 +00:00
}
}
}