Skip to content

Commit

Permalink
Append / prepend optimization
Browse files Browse the repository at this point in the history
  • Loading branch information
haxelion committed Jul 14, 2024
1 parent 7c34b6d commit 0afeedc
Show file tree
Hide file tree
Showing 3 changed files with 80 additions and 28 deletions.
44 changes: 34 additions & 10 deletions src/dynamic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -372,21 +372,45 @@ impl BitVector for BVD {
}

fn append<B: BitVector>(&mut self, suffix: &B) {
self.reserve(self.length + suffix.len());
// TODO: can be optimized with a shift and data copy via IArray.
// The IArray trait would need rework to support this.
for b in suffix.iter() {
self.push(b);
let offset = self.length % Self::BIT_UNIT;
let slide = self.length / Self::BIT_UNIT;
self.resize(self.length + suffix.len(), Bit::Zero);
if offset == 0 {
let mut i = 0;
while let Some(b) = suffix.get_int::<u64>(i) {
self.data[i + slide] = b;
i += 1;
}
} else if let Some(b) = suffix.get_int::<u64>(0) {
self.data[slide] |= b << offset;

let rev_offset = Self::BIT_UNIT - offset;
let mut i = 1;
let mut prev = b;

while let Some(b) = suffix.get_int::<u64>(i) {
self.data[i + slide] = (prev >> rev_offset) | (b << offset);
prev = b;
i += 1;
}

if let Some(b) = self.data.get_mut(i + slide) {
*b = prev >> rev_offset;
}
}
}

fn prepend<B: BitVector>(&mut self, prefix: &B) {
self.resize(prefix.len() + self.length, Bit::Zero);
self.resize(self.length + prefix.len(), Bit::Zero);
*self <<= prefix.len();
// TODO: can be optimized with data copy via IArray.
// The IArray trait would need rework to support this.
for (i, b) in prefix.iter().enumerate() {
self.set(i, b);
let last = prefix.int_len::<u64>() - 1;

for i in 0..last {
self.data[i] = prefix.get_int::<u64>(i).unwrap();
}

if let Some(b) = self.data.get_mut(last) {
*b |= prefix.get_int::<u64>(last).unwrap();
}
}

Expand Down
47 changes: 36 additions & 11 deletions src/fixed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -363,23 +363,48 @@ where
}

fn append<B: BitVector>(&mut self, suffix: &B) {
debug_assert!(self.length + suffix.len() <= self.capacity());
// TODO: can be optimized with a shift and data copy via IArray.
// The IArray trait would need rework to support this.
for b in suffix.iter() {
self.push(b);
let offset = self.length % u8::BITS as usize;
let slide = self.length / u8::BITS as usize;
self.resize(self.length + suffix.len(), Bit::Zero);
if offset == 0 {
let mut i = 0;
while let Some(b) = suffix.get_int::<u8>(i) {
self.set_int::<u8>(i + slide, b);
i += 1;
}
} else if let Some(b) = suffix.get_int::<u8>(0) {
self.set_int::<u8>(
slide,
self.get_int::<u8>(slide).unwrap_or(0) | (b << offset),
);

let rev_offset = u8::BITS as usize - offset;
let mut i = 1;
let mut prev = b;

while let Some(b) = suffix.get_int::<u8>(i) {
self.set_int::<u8>(i + slide, (prev >> rev_offset) | (b << offset));
prev = b;
i += 1;
}

self.set_int::<u8>(i + slide, prev >> rev_offset);
}
}

fn prepend<B: BitVector>(&mut self, prefix: &B) {
debug_assert!(prefix.len() + self.length <= self.capacity());
self.resize(prefix.len() + self.length, Bit::Zero);
self.resize(self.length + prefix.len(), Bit::Zero);
*self <<= prefix.len();
// TODO: can be optimized with data copy via IArray.
// The IArray trait would need rework to support this.
for (i, b) in prefix.iter().enumerate() {
self.set(i, b);
let last = prefix.int_len::<u8>() - 1;

for i in 0..last {
self.set_int::<u8>(i, prefix.get_int::<u8>(i).unwrap());
}

self.set_int::<u8>(
last,
self.get_int::<u8>(last).unwrap() | prefix.get_int::<u8>(last).unwrap(),
);
}

fn shl_in(&mut self, bit: Bit) -> Bit {
Expand Down
17 changes: 10 additions & 7 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ mod utils;

use bit::Bit;
use iter::BitIterator;
use utils::{IArray, IArrayMut};

/// An enumeration representing the endianness of an I/O or memory operation.
#[derive(Copy, Clone, PartialEq, Eq)]
Expand Down Expand Up @@ -80,17 +81,19 @@ impl std::error::Error for ConvertionError {}

/// A trait representing common bit vector operations.
pub trait BitVector:
Sized
Binary
+ Clone
+ Debug
+ PartialEq
+ Eq
+ PartialOrd
+ Ord
+ Display
+ Binary
+ Octal
+ Eq
+ IArray
+ IArrayMut
+ LowerHex
+ Octal
+ Ord
+ PartialEq
+ PartialOrd
+ Sized
+ UpperHex
{
/// Construct an empty pre-allocated with enough capacity to store `length` bits.
Expand Down

0 comments on commit 0afeedc

Please sign in to comment.