diff --git a/src/dynamic.rs b/src/dynamic.rs index 2c26b2a..1e08ead 100644 --- a/src/dynamic.rs +++ b/src/dynamic.rs @@ -372,21 +372,45 @@ impl BitVector for BVD { } fn append(&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::(i) { + self.data[i + slide] = b; + i += 1; + } + } else if let Some(b) = suffix.get_int::(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::(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(&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::() - 1; + + for i in 0..last { + self.data[i] = prefix.get_int::(i).unwrap(); + } + + if let Some(b) = self.data.get_mut(last) { + *b |= prefix.get_int::(last).unwrap(); } } diff --git a/src/fixed.rs b/src/fixed.rs index 27893a9..e4ceeaf 100644 --- a/src/fixed.rs +++ b/src/fixed.rs @@ -363,23 +363,48 @@ where } fn append(&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::(i) { + self.set_int::(i + slide, b); + i += 1; + } + } else if let Some(b) = suffix.get_int::(0) { + self.set_int::( + slide, + self.get_int::(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::(i) { + self.set_int::(i + slide, (prev >> rev_offset) | (b << offset)); + prev = b; + i += 1; + } + + self.set_int::(i + slide, prev >> rev_offset); } } fn prepend(&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::() - 1; + + for i in 0..last { + self.set_int::(i, prefix.get_int::(i).unwrap()); } + + self.set_int::( + last, + self.get_int::(last).unwrap() | prefix.get_int::(last).unwrap(), + ); } fn shl_in(&mut self, bit: Bit) -> Bit { diff --git a/src/lib.rs b/src/lib.rs index 1f2f13c..93e2ee0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -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)] @@ -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.