Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions src/auto.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use std::cmp::Ordering;
use std::fmt::{Binary, Display, LowerHex, Octal, UpperHex};
use std::hash::{Hash, Hasher};

use std::ops::{
Add, AddAssign, BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Div, DivAssign,
Expand Down Expand Up @@ -438,6 +439,15 @@ impl BitVector for Bv {
}
}

impl Hash for Bv {
fn hash<H: Hasher>(&self, state: &mut H) {
self.len().hash(state);
for i in 0..Self::int_len::<u64>(self) {
self.get_int::<u64>(i).unwrap().hash(state);
}
}
}

// ------------------------------------------------------------------------------------------------
// Bv - Bit iterator trait
// ------------------------------------------------------------------------------------------------
Expand Down
41 changes: 28 additions & 13 deletions src/dynamic.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use std::cmp::Ordering;
use std::fmt;
use std::hash::{Hash, Hasher};
use std::io::{Read, Write};
use std::iter::repeat;
use std::mem::size_of;
Expand Down Expand Up @@ -279,14 +280,14 @@ impl BitVector for Bvd {
match endianness {
Endianness::Little => {
for i in 0..num_bytes {
buf[i] = (self.data[i / Self::BYTE_UNIT] >> ((i % Self::BYTE_UNIT) * 8) & 0xff)
as u8;
buf[i] = ((self.data[i / Self::BYTE_UNIT] >> ((i % Self::BYTE_UNIT) * 8))
& 0xff) as u8;
}
}
Endianness::Big => {
for i in 0..num_bytes {
buf[num_bytes - i - 1] = (self.data[i / Self::BYTE_UNIT]
>> ((i % Self::BYTE_UNIT) * 8)
buf[num_bytes - i - 1] = ((self.data[i / Self::BYTE_UNIT]
>> ((i % Self::BYTE_UNIT) * 8))
& 0xff) as u8;
}
}
Expand All @@ -312,12 +313,12 @@ impl BitVector for Bvd {
}

fn write<W: Write>(&self, writer: &mut W, endianness: Endianness) -> std::io::Result<()> {
return writer.write_all(self.to_vec(endianness).as_slice());
writer.write_all(self.to_vec(endianness).as_slice())
}

fn get(&self, index: usize) -> Bit {
debug_assert!(index < self.length);
(self.data[index / Self::BIT_UNIT] >> (index % Self::BIT_UNIT) & 1).into()
((self.data[index / Self::BIT_UNIT] >> (index % Self::BIT_UNIT)) & 1).into()
}

fn set(&mut self, index: usize, bit: Bit) {
Expand Down Expand Up @@ -445,15 +446,15 @@ impl BitVector for Bvd {
fn shl_in(&mut self, bit: Bit) -> Bit {
let mut carry = bit;
for i in 0..(self.length / Self::BIT_UNIT) {
let b = self.data[i] >> (Self::BIT_UNIT - 1) & 1;
self.data[i] = self.data[i] << 1 | carry as u64;
let b = (self.data[i] >> (Self::BIT_UNIT - 1)) & 1;
self.data[i] = (self.data[i] << 1) | carry as u64;
carry = b.into();
}
if self.length % Self::BIT_UNIT != 0 {
let i = self.length / Self::BIT_UNIT;
let b = self.data[i] >> (self.length % Self::BIT_UNIT - 1) & 1;
let b = (self.data[i] >> (self.length % Self::BIT_UNIT - 1)) & 1;
self.data[i] =
(self.data[i] << 1 | carry as u64) & u64::mask(self.length % Self::BIT_UNIT);
((self.data[i] << 1) | carry as u64) & u64::mask(self.length % Self::BIT_UNIT);
carry = b.into();
}
carry
Expand All @@ -464,12 +465,13 @@ impl BitVector for Bvd {
if self.length % Self::BIT_UNIT != 0 {
let i = self.length / Self::BIT_UNIT;
let b = self.data[i] & 1;
self.data[i] = self.data[i] >> 1 | (carry as u64) << (self.length % Self::BIT_UNIT - 1);
self.data[i] =
(self.data[i] >> 1) | ((carry as u64) << (self.length % Self::BIT_UNIT - 1));
carry = b.into();
}
for i in (0..(self.length / Self::BIT_UNIT)).rev() {
let b = self.data[i] & 1;
self.data[i] = self.data[i] >> 1 | (carry as u64) << (Self::BIT_UNIT - 1);
self.data[i] = (self.data[i] >> 1) | ((carry as u64) << (Self::BIT_UNIT - 1));
carry = b.into();
}
carry
Expand Down Expand Up @@ -621,6 +623,19 @@ impl BitVector for Bvd {
}
}

// ------------------------------------------------------------------------------------------------
// Bvd - Hasher Implementation
// ------------------------------------------------------------------------------------------------

impl Hash for Bvd {
fn hash<H: Hasher>(&self, state: &mut H) {
self.length.hash(state);
for i in 0..Self::capacity_from_bit_len(self.length) {
self.data[i].hash(state);
}
}
}

// ------------------------------------------------------------------------------------------------
// Bvd - Bit iterator traits
// ------------------------------------------------------------------------------------------------
Expand Down Expand Up @@ -711,7 +726,7 @@ impl fmt::Octal for Bvd {
while let Some(b0) = it.next() {
let b1 = it.next().unwrap_or(Bit::Zero);
let b2 = it.next().unwrap_or(Bit::Zero);
let octet = (b2 as u8) << 2 | (b1 as u8) << 1 | b0 as u8;
let octet = ((b2 as u8) << 2) | ((b1 as u8) << 1) | b0 as u8;
if octet != 0 {
last_nz = s.len();
}
Expand Down
33 changes: 24 additions & 9 deletions src/fixed.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use std::cmp::Ordering;
use std::fmt;
use std::hash::{Hash, Hasher};
use std::iter::repeat;
use std::mem::size_of;
use std::ops::{
Expand Down Expand Up @@ -312,12 +313,12 @@ where
writer: &mut W,
endianness: Endianness,
) -> std::io::Result<()> {
return writer.write_all(self.to_vec(endianness).as_slice());
writer.write_all(self.to_vec(endianness).as_slice())
}

fn get(&self, index: usize) -> Bit {
debug_assert!(index < self.length);
(self.data[index / Self::BIT_UNIT] >> (index % Self::BIT_UNIT) & I::ONE).into()
((self.data[index / Self::BIT_UNIT] >> (index % Self::BIT_UNIT)) & I::ONE).into()
}

fn set(&mut self, index: usize, bit: Bit) {
Expand Down Expand Up @@ -447,15 +448,15 @@ where
fn shl_in(&mut self, bit: Bit) -> Bit {
let mut carry = bit;
for i in 0..(self.length / Self::BIT_UNIT) {
let b = self.data[i] >> (Self::BIT_UNIT - 1) & I::ONE;
self.data[i] = self.data[i] << 1 | carry.into();
let b = (self.data[i] >> (Self::BIT_UNIT - 1)) & I::ONE;
self.data[i] = (self.data[i] << 1) | carry.into();
carry = b.into();
}
if self.length % Self::BIT_UNIT != 0 {
let i = self.length / Self::BIT_UNIT;
let b = self.data[i] >> (self.length % Self::BIT_UNIT - 1) & I::ONE;
let b = (self.data[i] >> (self.length % Self::BIT_UNIT - 1)) & I::ONE;
self.data[i] =
(self.data[i] << 1 | carry.into()) & I::mask(self.length % Self::BIT_UNIT);
((self.data[i] << 1) | carry.into()) & I::mask(self.length % Self::BIT_UNIT);
carry = b.into();
}
carry
Expand All @@ -466,12 +467,13 @@ where
if self.length % Self::BIT_UNIT != 0 {
let i = self.length / Self::BIT_UNIT;
let b = self.data[i] & I::ONE;
self.data[i] = self.data[i] >> 1 | I::from(carry) << (self.length % Self::BIT_UNIT - 1);
self.data[i] =
(self.data[i] >> 1) | (I::from(carry) << (self.length % Self::BIT_UNIT - 1));
carry = b.into();
}
for i in (0..(self.length / Self::BIT_UNIT)).rev() {
let b = self.data[i] & I::ONE;
self.data[i] = self.data[i] >> 1 | I::from(carry) << (Self::BIT_UNIT - 1);
self.data[i] = (self.data[i] >> 1) | (I::from(carry) << (Self::BIT_UNIT - 1));
carry = b.into();
}
carry
Expand Down Expand Up @@ -619,6 +621,19 @@ where
}
}

// ------------------------------------------------------------------------------------------------
// Bvf - Hasher Implementation
// ------------------------------------------------------------------------------------------------

impl<I: Integer, const N: usize> Hash for Bvf<I, N> {
fn hash<H: Hasher>(&self, state: &mut H) {
self.length.hash(state);
for i in 0..Self::capacity_from_bit_len(self.length) {
self.data[i].hash(state);
}
}
}

// ------------------------------------------------------------------------------------------------
// Bvf - Bit iterator trait
// ------------------------------------------------------------------------------------------------
Expand Down Expand Up @@ -711,7 +726,7 @@ impl<I: Integer, const N: usize> fmt::Octal for Bvf<I, N> {
while let Some(b0) = it.next() {
let b1 = it.next().unwrap_or(Bit::Zero);
let b2 = it.next().unwrap_or(Bit::Zero);
let octet = (b2 as u8) << 2 | (b1 as u8) << 1 | b0 as u8;
let octet = ((b2 as u8) << 2) | ((b1 as u8) << 1) | b0 as u8;
if octet != 0 {
last_nz = s.len();
}
Expand Down
4 changes: 2 additions & 2 deletions src/iter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ impl<'a, B: BitVector> BitIterator<'a, B> {
}
}

impl<'a, B: BitVector> Iterator for BitIterator<'a, B> {
impl<B: BitVector> Iterator for BitIterator<'_, B> {
type Item = Bit;

fn next(&mut self) -> Option<Self::Item> {
Expand Down Expand Up @@ -59,7 +59,7 @@ impl<'a, B: BitVector> Iterator for BitIterator<'a, B> {
}
}

impl<'a, B: BitVector> DoubleEndedIterator for BitIterator<'a, B> {
impl<B: BitVector> DoubleEndedIterator for BitIterator<'_, B> {
fn next_back(&mut self) -> Option<Self::Item> {
if self.range.start < self.range.end {
self.range.end -= 1;
Expand Down
2 changes: 2 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@
)]

use std::fmt::{Binary, Debug, Display, LowerHex, Octal, UpperHex};
use std::hash::Hash;
use std::io::{Read, Write};
use std::ops::Range;

Expand Down Expand Up @@ -164,6 +165,7 @@ pub trait BitVector:
+ Debug
+ Display
+ Eq
+ Hash
+ IArray
+ IArrayMut
+ LowerHex
Expand Down
16 changes: 16 additions & 0 deletions src/tests/auto.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
use std::hash::{DefaultHasher, Hash, Hasher};

use crate::auto::Bv;
use crate::bit::Bit;
use crate::tests::random_bv;
use crate::BitVector;

#[test]
Expand All @@ -14,3 +17,16 @@ fn shrink_to_fit_bv() {
assert_eq!(bv, Bv::ones(length));
}
}

#[test]
fn hash() {
for length in 0..512 {
let bv1 = random_bv::<Bv>(length);
let bv2 = random_bv::<Bv>(length);
let mut hasher1 = DefaultHasher::new();
let mut hasher2 = DefaultHasher::new();
bv1.hash(&mut hasher1);
bv2.hash(&mut hasher2);
assert_eq!(hasher1.finish() == hasher2.finish(), bv1 == bv2);
}
}
15 changes: 15 additions & 0 deletions src/tests/dynamic.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use std::hash::{DefaultHasher, Hash, Hasher};

use crate::bit::Bit;
use crate::dynamic::Bvd;
use crate::tests::random_bv;
Expand All @@ -13,6 +15,19 @@ fn new_into() {
}
}

#[test]
fn hash() {
for length in 0..512 {
let bv1 = random_bv::<Bvd>(length);
let bv2 = random_bv::<Bvd>(length);
let mut hasher1 = DefaultHasher::new();
let mut hasher2 = DefaultHasher::new();
bv1.hash(&mut hasher1);
bv2.hash(&mut hasher2);
assert_eq!(hasher1.finish() == hasher2.finish(), bv1 == bv2);
}
}

#[test]
fn shrink_to_fit_bvd() {
let capacity = 512;
Expand Down
19 changes: 19 additions & 0 deletions src/tests/fixed.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use std::hash::{DefaultHasher, Hash, Hasher};

use crate::fixed::Bvf;
use crate::tests::{bvf_inner_unroll, random_bv};
use crate::utils::Integer;
Expand All @@ -11,7 +13,24 @@ fn new_into_inner<I: Integer, const N: usize>() {
}
}

fn hash_inner<I: Integer, const N: usize>() {
for length in 0..Bvf::<I, N>::capacity() {
let bv1 = random_bv::<Bvf<I, N>>(length);
let bv2 = random_bv::<Bvf<I, N>>(length);
let mut hasher1 = DefaultHasher::new();
let mut hasher2 = DefaultHasher::new();
bv1.hash(&mut hasher1);
bv2.hash(&mut hasher2);
assert_eq!(hasher1.finish() == hasher2.finish(), bv1 == bv2);
}
}

#[test]
fn new_into() {
bvf_inner_unroll!(new_into_inner, {u8, u16, u32, u64, u128}, {1, 2, 3, 4, 5});
}

#[test]
fn hash() {
bvf_inner_unroll!(hash_inner, {u8, u16, u32, u64, u128}, {1, 2, 3, 4, 5});
}
2 changes: 2 additions & 0 deletions src/utils.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use std::fmt::{Debug, Display};
use std::hash::Hash;
use std::mem::{align_of, size_of, size_of_val};
use std::ops::{
Add, AddAssign, BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Div, DivAssign,
Expand Down Expand Up @@ -80,6 +81,7 @@ pub trait Integer:
+ Display
+ Eq
+ From<Bit>
+ Hash
+ Into<Bit>
+ Mul<Output = Self>
+ MulAssign
Expand Down
Loading