From 6d5ae4456c4737ccc6a37aba21e86a6d09a55c25 Mon Sep 17 00:00:00 2001 From: LucaCappelletti94 Date: Sat, 24 Aug 2024 22:19:45 +0200 Subject: [PATCH] Removed newly dead code --- hyperloglog-derive/src/lib.rs | 589 +--------------------------------- src/hybrid.rs | 2 +- src/registers.rs | 4 - src/utils.rs | 4 +- src/utils/variable_word.rs | 6 - src/utils/variable_words.rs | 108 ------- 6 files changed, 3 insertions(+), 710 deletions(-) delete mode 100644 src/utils/variable_words.rs diff --git a/hyperloglog-derive/src/lib.rs b/hyperloglog-derive/src/lib.rs index a8d9fc6..f2c995f 100644 --- a/hyperloglog-derive/src/lib.rs +++ b/hyperloglog-derive/src/lib.rs @@ -1,7 +1,7 @@ //! Submodule providing the derive macro for the VariableWord trait. use proc_macro::TokenStream; use quote::{quote, ToTokens}; -use syn::{parse_macro_input, Data, DeriveInput, Fields, Ident, ItemFn, Type}; +use syn::{parse_macro_input, Ident, ItemFn, Type}; #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] /// Possible variants for the word size currently supported. @@ -10,8 +10,6 @@ enum WordType { U8, /// 16-bit word. U16, - /// 24-bit word. - U24, /// 32-bit word. U32, /// 64-bit word. @@ -26,7 +24,6 @@ impl core::fmt::Display for WordType { match self { WordType::U8 => "u8", WordType::U16 => "u16", - WordType::U24 => "u24", WordType::U32 => "u32", WordType::U64 => "u64", } @@ -39,7 +36,6 @@ impl From<&str> for WordType { match s { "u8" => WordType::U8, "u16" => WordType::U16, - "u24" => WordType::U24, "u32" => WordType::U32, "u64" => WordType::U64, _ => panic!("Unsupported word size"), @@ -53,8 +49,6 @@ impl From<&Ident> for WordType { WordType::U8 } else if ident.to_string().contains("u16") { WordType::U16 - } else if ident.to_string().contains("u24") { - WordType::U24 } else if ident.to_string().contains("u32") { WordType::U32 } else if ident.to_string().contains("u64") { @@ -70,7 +64,6 @@ impl ToTokens for WordType { match self { WordType::U8 => quote! { u8 }, WordType::U16 => quote! { u16 }, - WordType::U24 => quote! { u24 }, WordType::U32 => quote! { u32 }, WordType::U64 => quote! { u64 }, } @@ -88,8 +81,6 @@ impl From for WordType { WordType::U8 } else if *ident == "u16" { WordType::U16 - } else if *ident == "u24" { - WordType::U24 } else if *ident == "u32" { WordType::U32 } else if *ident == "u64" { @@ -109,587 +100,10 @@ impl WordType { vec![ WordType::U8, WordType::U16, - WordType::U24, WordType::U32, WordType::U64, ] } - - /// Returns whether the word is a power of two. - fn is_power_of_two(&self) -> bool { - match self { - WordType::U8 => true, - WordType::U16 => true, - WordType::U24 => false, - WordType::U32 => true, - WordType::U64 => true, - } - } - - /// Returns the underlying field type. - fn field_type(&self) -> Type { - match self { - WordType::U8 => syn::parse_quote! { u8 }, - WordType::U16 => syn::parse_quote! { u16 }, - WordType::U24 => syn::parse_quote! { u32 }, - WordType::U32 => syn::parse_quote! { u32 }, - WordType::U64 => syn::parse_quote! { u64 }, - } - } - - /// Returns all the smaller variants of the word size. - fn smaller_variants(&self) -> Vec { - Self::variants() - .into_iter() - .filter(|variant| variant.number_of_bits() < self.number_of_bits()) - .collect() - } - - /// Returns all variants that are strictly larger than the current one, and are a power of two. - fn larger_power_of_two_variants(&self) -> Vec { - Self::variants() - .into_iter() - .filter(|variant| { - (variant.number_of_bits() > self.number_of_bits()) && variant.is_power_of_two() - }) - .collect() - } - - fn number_of_bits(&self) -> u8 { - match self { - WordType::U8 => 8, - WordType::U16 => 16, - WordType::U24 => 24, - WordType::U32 => 32, - WordType::U64 => 64, - } - } - - fn mask(&self) -> u64 { - match self { - WordType::U8 => 0xFF, - WordType::U16 => 0xFFFF, - WordType::U24 => 0xFF_FFFF, - WordType::U32 => 0xFFFF_FFFF, - WordType::U64 => 0xFFFF_FFFF_FFFF_FFFF, - } - } - - fn bytes(&self) -> usize { - usize::from(self.number_of_bits() / 8) - } -} - -#[proc_macro_derive(VariableWord)] -pub fn derive_variable_word(input: TokenStream) -> TokenStream { - // Parse the input TokenStream into a syntax tree - let input = parse_macro_input!(input as DeriveInput); - - let name = &input.ident; - - // Ensure the input is a struct - let data_struct = match &input.data { - Data::Struct(data_struct) => data_struct, - _ => panic!("VariableWord can only be derived for structs"), - }; - - // Ensure the struct has exactly one unnamed field (i.e., a tuple struct) - let field = match &data_struct.fields { - Fields::Unnamed(fields) if fields.unnamed.len() == 1 => &fields.unnamed[0], - _ => panic!("The struct must have exactly one unnamed field"), - }; - - // We get the type of the field - let field_type = &field.ty; - let word_type: WordType = WordType::from(field_type.clone()); - - // Get the word size from the struct name - let word_size = WordType::from(name); - let number_of_bits = word_size.number_of_bits(); - let number_of_bits_usize = number_of_bits as usize; - let mask = word_size.mask(); - let word_bytes = word_type.bytes(); - - let test_bytes_symmetry_for_name = - Ident::new(&format!("test_bytes_symmetry_for_{name}"), name.span()); - - // Generate the necessary traits for the word - let mut expanded = quote! { - impl crate::prelude::VariableWord for #name { - const NUMBER_OF_BITS: u8 = #number_of_bits; - const MASK: u64 = #mask; - type Word = Self; - - #[inline] - #[allow(unsafe_code)] - unsafe fn unchecked_from_u64(value: u64) -> Self::Word { - debug_assert!(value <= ::MASK, "The value is too large for the number."); - Self(value as #field_type) - } - } - - impl From<[u8; #number_of_bits_usize / 8]> for #name { - #[inline] - #[must_use] - fn from(bytes: [u8; #number_of_bits_usize / 8]) -> Self { - let mut array = [0; #word_bytes]; - array[..#number_of_bits_usize / 8].copy_from_slice(&bytes); - Self(<#field_type>::from_le_bytes(array)) - } - } - - impl Into<[u8; #number_of_bits_usize / 8]> for #name { - #[inline] - #[must_use] - fn into(self) -> [u8; #number_of_bits_usize / 8] { - let array = self.0.to_le_bytes(); - let mut bytes = [0; #number_of_bits_usize / 8]; - bytes.copy_from_slice(&array[..#number_of_bits_usize / 8]); - bytes - } - } - - #[cfg(test)] - mod #test_bytes_symmetry_for_name { - use super::*; - - #[test] - fn test_bytes_symmetry() { - for value in crate::prelude::iter_random_values::<#name>(1_000, Some(#name::try_from(#name::MASK).unwrap()), None) { - let bytes: [u8; #number_of_bits_usize / 8] = value.into(); - let value_from_bytes: #name = <#name>::from(bytes); - assert_eq!(value, value_from_bytes); - } - } - } - - impl core::fmt::Display for #name { - fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { - write!(f, "{}", self.0) - } - } - - impl core::ops::Add for #name { - type Output = Self; - - #[inline] - #[must_use] - fn add(self, rhs: Self) -> Self::Output { - Self((self.0 + rhs.0) & (::MASK as #field_type)) - } - } - - impl core::ops::AddAssign for #name { - #[inline] - #[must_use] - fn add_assign(&mut self, rhs: Self) { - *self = *self + rhs; - } - } - - impl core::ops::Sub for #name { - type Output = Self; - - #[inline] - #[must_use] - fn sub(self, rhs: Self) -> Self::Output { - Self(self.0 - rhs.0) - } - } - - impl core::ops::SubAssign for #name { - #[inline] - #[must_use] - fn sub_assign(&mut self, rhs: Self) { - *self = *self - rhs; - } - } - - impl core::ops::Mul for #name { - type Output = Self; - - #[inline] - #[must_use] - fn mul(self, rhs: Self) -> Self::Output { - Self((self.0 * rhs.0) & (::MASK as #field_type)) - } - } - - impl core::ops::MulAssign for #name { - #[inline] - #[must_use] - fn mul_assign(&mut self, rhs: Self) { - *self = *self * rhs; - } - } - - impl core::ops::Div for #name { - type Output = Self; - - #[inline] - #[must_use] - fn div(self, rhs: Self) -> Self::Output { - Self(self.0 / rhs.0) - } - } - - impl core::ops::DivAssign for #name { - #[inline] - #[must_use] - fn div_assign(&mut self, rhs: Self) { - *self = *self / rhs; - } - } - - impl core::ops::Rem for #name { - type Output = Self; - - #[inline] - #[must_use] - fn rem(self, rhs: Self) -> Self::Output { - Self(self.0 % rhs.0) - } - } - - impl core::ops::RemAssign for #name { - #[inline] - #[must_use] - fn rem_assign(&mut self, rhs: Self) { - *self = *self % rhs; - } - } - - impl core::ops::BitAnd for #name { - type Output = Self; - - #[inline] - #[must_use] - fn bitand(self, rhs: Self) -> Self::Output { - Self(self.0 & rhs.0) - } - } - - impl core::ops::BitAndAssign for #name { - #[inline] - #[must_use] - fn bitand_assign(&mut self, rhs: Self) { - *self = *self & rhs; - } - } - - impl core::ops::BitOr for #name { - type Output = Self; - - #[inline] - #[must_use] - fn bitor(self, rhs: Self) -> Self::Output { - Self(self.0 | rhs.0) - } - } - - impl core::ops::BitOrAssign for #name { - #[inline] - #[must_use] - fn bitor_assign(&mut self, rhs: Self) { - *self = *self | rhs; - } - } - - impl core::ops::BitXor for #name { - type Output = Self; - - #[inline] - #[must_use] - fn bitxor(self, rhs: Self) -> Self::Output { - Self(self.0 ^ rhs.0) - } - } - - impl core::ops::BitXorAssign for #name { - #[inline] - #[must_use] - fn bitxor_assign(&mut self, rhs: Self) { - *self = *self ^ rhs; - } - } - - impl core::ops::Shl for #name where #field_type: core::ops::Shl { - type Output = Self; - - #[inline] - #[must_use] - fn shl(self, rhs: A) -> Self::Output { - let result = self.0 << rhs; - debug_assert!(result <= ::MASK as #field_type, "The value {result} is too large for the number."); - Self(result) - } - } - - impl core::ops::ShlAssign for #name where #field_type: core::ops::ShlAssign { - #[inline] - #[must_use] - fn shl_assign(&mut self, rhs: A) { - self.0 <<= rhs; - } - } - - impl core::ops::Shr for #name where #field_type: core::ops::Shr { - type Output = Self; - - #[inline] - #[must_use] - fn shr(self, rhs: A) -> Self::Output { - Self(self.0 >> rhs) - } - } - - impl core::ops::ShrAssign for #name where #field_type: core::ops::ShrAssign { - #[inline] - #[must_use] - fn shr_assign(&mut self, rhs: A) { - self.0 >>= rhs; - } - } - - impl core::cmp::PartialEq for #name { - #[inline] - #[must_use] - fn eq(&self, other: &Self) -> bool { - self.0 == other.0 - } - } - - impl core::cmp::Eq for #name {} - - impl core::cmp::PartialOrd for #name { - #[inline] - #[must_use] - fn partial_cmp(&self, other: &Self) -> Option { - self.0.partial_cmp(&other.0) - } - } - - impl core::cmp::Ord for #name { - #[inline] - #[must_use] - fn cmp(&self, other: &Self) -> core::cmp::Ordering { - self.0.cmp(&other.0) - } - } - - impl core::hash::Hash for #name { - #[inline] - #[must_use] - fn hash(&self, state: &mut H) { - self.0.hash(state); - } - } - - impl core::default::Default for #name { - #[inline] - #[must_use] - fn default() -> Self { - Self(0) - } - } - - impl crate::prelude::Number for #name { - #[inline] - #[must_use] - fn saturating_zero_sub(self, other: Self) -> Self { - if self < other { - ::ZERO - } else { - self - other - } - } - } - - impl crate::prelude::PositiveInteger for #name { - #[inline] - #[must_use] - fn to_usize(self) -> usize { - self.0 as usize - } - } - - impl crate::prelude::Zero for #name { - const ZERO: Self = Self(0); - - #[inline] - #[must_use] - fn is_zero(&self) -> bool { - self.0 == 0 - } - } - - impl crate::prelude::One for #name { - const ONE: Self = Self(1); - - #[inline] - #[must_use] - fn is_one(&self) -> bool { - self.0 == 1 - } - } - - impl core::ops::Not for #name { - type Output = Self; - - #[inline] - #[must_use] - fn not(self) -> Self::Output { - Self(!self.0 & (::MASK as #field_type)) - } - } - - impl Copy for #name {} - - impl core::fmt::Debug for #name { - fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { - write!(f, "{}", self.0) - } - } - - impl From for #name { - #[inline] - #[must_use] - fn from(value: bool) -> Self { - Self(#field_type::from(value)) - } - } - - #[cfg(feature = "std")] - impl crate::prelude::Named for #name { - #[inline] - #[must_use] - fn name(&self) -> String { - stringify!(#name).to_string() - } - } - }; - - // We iterate the variant that are smaller than the current one and implement the From trait - // for each one. Next, we iterate all variants that are larger and we implement the TryFrom. - - // We iterate the smaller variants - for smaller_variant in word_size.smaller_variants() { - let smaller_variant_name = smaller_variant.to_string(); - let smaller_variant_ident = Ident::new(&smaller_variant_name, name.span()); - - let field_type_of_smaller_variant = smaller_variant.field_type(); - - if smaller_variant.is_power_of_two() { - expanded.extend(quote! { - impl TryInto<#smaller_variant_ident> for #name { - type Error = &'static str; - - #[inline] - #[must_use] - fn try_into(self) -> Result<#smaller_variant_ident, Self::Error> { - if self.0 > ::MASK as #field_type{ - Err("The value is too large for the number.") - } else { - Ok(self.0 as #field_type_of_smaller_variant) - } - } - } - - impl From<#smaller_variant_ident> for #name { - #[inline] - #[must_use] - fn from(value: #smaller_variant_ident) -> Self { - Self(value as #field_type) - } - } - }); - } else { - expanded.extend(quote! { - impl TryInto<#smaller_variant_ident> for #name { - type Error = &'static str; - - #[inline] - #[must_use] - fn try_into(self) -> Result<#smaller_variant_ident, Self::Error> { - if self.0 > ::MASK as #field_type{ - Err("The value is too large for the number.") - } else { - Ok(#smaller_variant_ident(self.0 as #field_type_of_smaller_variant)) - } - } - } - - impl From<#smaller_variant_ident> for #name { - #[inline] - #[must_use] - fn from(value: #smaller_variant_ident) -> Self { - Self(value.0 as #field_type) - } - } - }); - } - } - - // We iterate the larger variants - for larger_variant in word_size.larger_power_of_two_variants() { - let larger_variant_name = larger_variant.to_string(); - let larger_variant_ident = Ident::new(&larger_variant_name, name.span()); - - let field_type_of_larger_variant = larger_variant.field_type(); - - if larger_variant.is_power_of_two() { - expanded.extend(quote! { - impl TryFrom<#larger_variant_ident> for #name { - type Error = &'static str; - - #[inline] - #[must_use] - fn try_from(value: #larger_variant_ident) -> Result { - if value > ::MASK as #field_type_of_larger_variant { - Err("The value is too large for the number.") - } else { - Ok(Self(value as #field_type)) - } - } - } - - impl Into<#larger_variant_ident> for #name { - #[inline] - #[must_use] - fn into(self) -> #field_type_of_larger_variant { - self.0 as #field_type_of_larger_variant - } - } - }); - } else { - expanded.extend(quote! { - impl TryFrom<#larger_variant_ident> for #name { - type Error = &'static str; - - #[inline] - #[must_use] - fn try_from(value: #larger_variant_ident) -> Result { - if value.0 > ::MASK as #field_type_of_larger_variant { - Err("The value is too large for the number.") - } else { - Ok(Self(value.0 as #field_type)) - } - } - } - - impl Into<#larger_variant_ident> for #name { - #[inline] - #[must_use] - fn into(self) -> #larger_variant_ident { - #larger_variant_ident(self.0 as #field_type_of_larger_variant) - } - } - }); - } - } - - // Return the generated impl - TokenStream::from(expanded) } #[proc_macro_attribute] @@ -704,7 +118,6 @@ pub fn test_variable_words(_attr: TokenStream, item: TokenStream) -> TokenStream let mut generics = vec![ Ident::new("u8", fn_name.span()), Ident::new("u16", fn_name.span()), - Ident::new("u24", fn_name.span()), Ident::new("u32", fn_name.span()), ]; diff --git a/src/hybrid.rs b/src/hybrid.rs index baee923..58a0999 100644 --- a/src/hybrid.rs +++ b/src/hybrid.rs @@ -1,6 +1,6 @@ //! Marker struct for the hybrid approach, that keeps the hash explicit up until they fit into the registers. -use crate::composite_hash::current::CurrentHash; +// use crate::composite_hash::current::CurrentHash; use crate::composite_hash::switch::SwitchHash; use crate::composite_hash::CompositeHash; use crate::prelude::*; diff --git a/src/registers.rs b/src/registers.rs index 60a1b49..b603e75 100644 --- a/src/registers.rs +++ b/src/registers.rs @@ -32,10 +32,6 @@ pub trait Registers: + Default + AsMut<[u8]> + AsRef<[u8]> - + VariableWords - + VariableWords - + VariableWords - + VariableWords { /// Iterator over the registers. type Iter<'register>: ExactSizeIterator diff --git a/src/utils.rs b/src/utils.rs index 31345ea..9a1d40e 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -16,15 +16,13 @@ mod matrix; mod number; mod random; mod variable_word; -mod variable_words; pub use constants::*; pub use hasher_type::HasherType; pub use matrix::Matrix; pub(crate) use number::{FloatOps, Number, PositiveInteger}; pub use random::*; -pub(crate) use variable_word::{u24, VariableWord}; -pub(crate) use variable_words::VariableWords; +pub(crate) use variable_word::VariableWord; #[cfg(feature = "std")] /// Trait for an object with a name. diff --git a/src/utils/variable_word.rs b/src/utils/variable_word.rs index 8c85f8a..9932af2 100644 --- a/src/utils/variable_word.rs +++ b/src/utils/variable_word.rs @@ -3,7 +3,6 @@ //! are not a power of two. use super::PositiveInteger; use core::fmt::Debug; -use hyperloglog_derive::VariableWord; /// Trait marker for the variable word. pub trait VariableWord: Send + Sync + Clone + Copy + Debug + Default { @@ -29,11 +28,6 @@ pub trait VariableWord: Send + Sync + Clone + Copy + Debug + Default { unsafe fn unchecked_from_u64(value: u64) -> Self::Word; } -/// Virtual word with 24 bits. -#[allow(non_camel_case_types)] -#[derive(Clone, VariableWord)] -pub struct u24(u32); - impl VariableWord for u8 { const NUMBER_OF_BITS: u8 = 8; type Word = u8; diff --git a/src/utils/variable_words.rs b/src/utils/variable_words.rs deleted file mode 100644 index 04800e7..0000000 --- a/src/utils/variable_words.rs +++ /dev/null @@ -1,108 +0,0 @@ -//! Submodule for words-arrays -use super::{u24, VariableWord}; -use core::fmt::Debug; -use core::iter::{Copied, Map}; -use core::slice::Iter; - -/// Trait for arrays of words. -pub trait VariableWords { - /// The type of the iterator over the words. - type Words<'words>: ExactSizeIterator + DoubleEndedIterator - where - W: 'words, - Self: 'words; - - /// Searches a value in the array and returns `true` if the value is found. - fn find_sorted_with_len(&self, value: W::Word, len: usize) -> bool; - - /// Inserts a value into the array searching for the correct position within a given length. - fn sorted_insert_with_len(&mut self, value: W::Word, len: usize) -> bool; - - /// Returns an iterator over the words. - fn iter_variable_words<'words>(&'words self, len: usize) -> Self::Words<'words> - where - W: 'words; -} - -/// Trait for arrays of words. -pub trait Words: - AsRef<[>::SliceType]> + AsMut<[>::SliceType]> -where - W::Word: From<>::SliceType>, -{ - type SliceType: Ord + Copy + Debug; -} -impl + AsMut<[u8]>> Words for T { - type SliceType = u8; -} -impl + AsMut<[u16]>> Words for T { - type SliceType = u16; -} -impl + AsMut<[[u8; 3]]>> Words for T { - type SliceType = [u8; 3]; -} -impl + AsMut<[u32]>> Words for T { - type SliceType = u32; -} - -impl, W: VariableWord> VariableWords for WS -where - W::Word: From<>::SliceType>, - W::Word: Into<>::SliceType>, -{ - type Words<'words> = Map< - Copied>::SliceType>>, - fn(>::SliceType) -> W::Word, - > where - W: 'words, - Self: 'words; - - fn find_sorted_with_len(&self, value: W::Word, len: usize) -> bool { - debug_assert!( - self.as_ref().len() >= len, - "The array must have enough elements." - ); - debug_assert!( - self.as_ref()[0..len].is_sorted_by_key(|x| W::Word::from(*x)), - "The array with len ({len}) must be sorted but got {:?}", - &self.as_ref()[0..len], - ); - self.as_ref()[0..len].binary_search_by_key(&value, |x| W::Word::from(*x)).is_ok() - } - - fn sorted_insert_with_len(&mut self, value: W::Word, len: usize) -> bool { - debug_assert!( - self.as_ref().len() > len, - "The array must have enough space for the new value. The length is {len} and the number of words is {}.", - self.as_ref().len() - ); - debug_assert!( - self.as_ref()[0..len].is_sorted_by_key(|x| W::Word::from(*x)), - "The array with len ({len}) must be sorted but got {:?}", - &self.as_ref()[0..len], - ); - - let slice_type: >::SliceType = value.into(); - match self.as_mut()[0..len].binary_search_by_key(&value, |x| W::Word::from(*x)) { - Ok(_) => false, - Err(index) => { - self.as_mut().copy_within(index..len, index + 1); - self.as_mut()[index] = slice_type; - - debug_assert!( - self.as_ref()[0..=len].is_sorted_by_key(|x| W::Word::from(*x)), - "The array must be sorted." - ); - - true - } - } - } - - fn iter_variable_words<'words>(&'words self, len: usize) -> Self::Words<'words> - where - W: 'words, - { - self.as_ref()[0..len].iter().copied().map(W::Word::from) - } -} \ No newline at end of file