Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implemented Hash trait #25

Merged
merged 2 commits into from
Jan 11, 2025
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