diff options
author | Andreas Grois <andi@grois.info> | 2022-11-04 00:12:14 +0100 |
---|---|---|
committer | Andreas Grois <andi@grois.info> | 2022-11-04 00:12:14 +0100 |
commit | 344264e03d7635b9bd2688390100d3b9f623c58a (patch) | |
tree | 98235141d3ca3c829506518971fd3f984dc386be /src | |
parent | db2e6ce5b648fa513009863e81a13f0e64281a78 (diff) |
Some clippy lints.
Some were fixed, some were ignored because they seem to make a
(negative) performance impact.
Diffstat (limited to 'src')
-rw-r--r-- | src/passwordmaker/base_conversion/iterative_conversion.rs | 5 | ||||
-rw-r--r-- | src/passwordmaker/base_conversion/iterative_conversion_impl/mod.rs | 69 |
2 files changed, 41 insertions, 33 deletions
diff --git a/src/passwordmaker/base_conversion/iterative_conversion.rs b/src/passwordmaker/base_conversion/iterative_conversion.rs index 710903e..c8c121c 100644 --- a/src/passwordmaker/base_conversion/iterative_conversion.rs +++ b/src/passwordmaker/base_conversion/iterative_conversion.rs @@ -20,6 +20,7 @@ pub(crate) struct IterativeBaseConversion<V,B>{ switch_to_multiplication : bool, //count the number of divisions. After 1, current_value is smaller than max_base_power. After 2, it's safe to mutliply current_value by base. } +#[allow(clippy::trait_duplication_in_bounds)] //That's obviously a false-positive in clippy... impl<V,B> IterativeBaseConversion<V,B> where V: for<'a> From<&'a B> + //could be replaced by num::traits::identities::One. PrecomputedMaxPowers<B>, @@ -37,6 +38,7 @@ impl<V,B> IterativeBaseConversion<V,B> } } + #[allow(clippy::map_unwrap_or)] //current code seems to be measurably faster. fn find_highest_fitting_power(base : &B) -> PowerAndExponent<V> { V::lookup(base).map(|(power,count)| PowerAndExponent{ power, exponent: count }) .unwrap_or_else(|| Self::find_highest_fitting_power_non_cached(base)) @@ -66,6 +68,7 @@ impl<V,B> std::iter::Iterator for IterativeBaseConversion<V,B> { type Item = B; + #[allow(clippy::assign_op_pattern)] //measurable performance difference. No, this doesn't make sense. fn next(&mut self) -> Option<Self::Item> { if self.remaining_digits == 0 { None @@ -75,7 +78,7 @@ impl<V,B> std::iter::Iterator for IterativeBaseConversion<V,B> if self.switch_to_multiplication { //mul_assign is in principle dangerous. //Since we do two rem_assign_with_quotient calls first, we can be sure that the result is always smaller than base^max_power though. - self.current_value *= &self.base + self.current_value *= &self.base; } else { self.current_base_power /= &self.base; self.switch_to_multiplication = true; diff --git a/src/passwordmaker/base_conversion/iterative_conversion_impl/mod.rs b/src/passwordmaker/base_conversion/iterative_conversion_impl/mod.rs index 6c6193d..3d5351a 100644 --- a/src/passwordmaker/base_conversion/iterative_conversion_impl/mod.rs +++ b/src/passwordmaker/base_conversion/iterative_conversion_impl/mod.rs @@ -38,7 +38,7 @@ impl From<&usize> for SixteenBytes{ } impl DivAssign<&usize> for SixteenBytes{ fn div_assign(&mut self, rhs: &usize) { - self.0 /= *rhs as u128 + self.0 /= *rhs as u128; } } impl RemAssignWithQuotient for SixteenBytes{ @@ -89,17 +89,18 @@ impl PrecomputedMaxPowers<usize> for ArbitraryBytes<5>{} #[cfg(not(any(feature="precomputed_max_powers", feature="precomputed_common_max_powers")))] impl PrecomputedMaxPowers<usize> for ArbitraryBytes<8>{} -const fn from_usize<const N : usize>(x : &usize) -> ArbitraryBytes<N> { +#[allow(clippy::cast_possible_truncation)] +const fn from_usize<const N : usize>(x : usize) -> ArbitraryBytes<N> { let mut result = [0;N]; //from Godbolt it looks like the compiler is smart enough to skip the unnecessary inits. #[cfg(target_pointer_width = "64")] - if N > 1 { result[N-2] = (*x >> 32) as u32;} - if N > 0 { result[N-1] = *x as u32;} //Compiler should hopefully be smart enough to yeet the condition. + if N > 1 { result[N-2] = (x >> 32) as u32;} + if N > 0 { result[N-1] = x as u32;} //Compiler should hopefully be smart enough to yeet the condition. ArbitraryBytes(result) } impl<const N : usize> From<&usize> for ArbitraryBytes<N>{ fn from(x: &usize) -> Self { - from_usize(x) + from_usize(*x) } } impl<const N : usize> From<&u32> for ArbitraryBytes<N>{ @@ -198,7 +199,7 @@ impl PaddedShiftLeft for ArbitraryBytes<8>{ impl<const N : usize> DivAssign<&usize> for ArbitraryBytes<N>{ //just do long division. fn div_assign(&mut self, rhs: &usize) { - self.div_assign_with_remainder_usize(rhs); + self.div_assign_with_remainder_usize(*rhs); } } @@ -231,6 +232,7 @@ impl<const N : usize> TryFrom<&ArbitraryBytes<N>> for usize{ let last_bit = value.0.get(N-1).ok_or(ArbitraryBytesToUsizeError).copied(); //second-last is not an error though. let second_last_bit = value.0.get(N-2).copied().unwrap_or_default(); + #[allow(clippy::cast_possible_truncation)] //false positive. This function is only compiled on 64bit systems. last_bit.map(|last_bit| u64_from_u32s(second_last_bit, last_bit) as usize) } } @@ -308,6 +310,7 @@ impl<const N : usize> Mul<&usize> for &ArbitraryBytes<N>{ //Done separately, because "mut references not allowed in const contexts" impl<const N : usize> MulAssign<&usize> for ArbitraryBytes<N>{ + #[allow(clippy::cast_possible_truncation)] //truncation is intentional here. fn mul_assign(&mut self, rhs: &usize) { #[cfg(target_pointer_width = "64")] type Long = u128; @@ -315,9 +318,9 @@ impl<const N : usize> MulAssign<&usize> for ArbitraryBytes<N>{ type Long = u64; let rhs = *rhs as Long; let carry = self.0.iter_mut().rev().fold(0 as Long, |carry, current| { - let res = (*current as Long) * rhs + carry; - *current = res as u32; - res >> 32 + let result = (*current as Long) * rhs + carry; + *current = result as u32; + result >> 32 }); debug_assert_eq!(carry, 0); } @@ -333,7 +336,7 @@ impl<const N : usize> Mul<&ArbitraryBytes<N>> for &ArbitraryBytes<N> where Arbit let p = p.filter(|p| p.0[0..(N-1-i)].iter().all(|&i| i == 0)); let carry = p.map(|p|{ //for some reason it's faster to use slices than iterators here. - slice_overflowing_add_assign(&mut result.0[0..(i+1)], &p.0[(N-1-i)..]) + slice_overflowing_add_assign(&mut result.0[0..=i], &p.0[(N-1-i)..]) }); carry.filter(|x| !x).map(|_|()) }); @@ -341,6 +344,7 @@ impl<const N : usize> Mul<&ArbitraryBytes<N>> for &ArbitraryBytes<N> where Arbit } } +#[allow(clippy::trait_duplication_in_bounds)] //obvious false positive. u32 and usize aren't the same. impl<const N : usize, const M : usize> RemAssignWithQuotient for ArbitraryBytes<N> where Self : for<'a> From<&'a usize> + for<'a> From<&'a u32> + PaddedShiftLeft<Output = ArbitraryBytes<M>> { @@ -354,7 +358,7 @@ impl<const N : usize, const M : usize> RemAssignWithQuotient for ArbitraryBytes< std::cmp::Ordering::Greater => { //If a single digit division suffices, do a single digit division. if let Ok(divisor_as_u32) = divisor.try_into() { - self.rem_assign_with_quotient_u32(&divisor_as_u32) + self.rem_assign_with_quotient_u32(divisor_as_u32) } else { self.rem_assign_with_quotient_knuth(divisor) } @@ -366,10 +370,10 @@ impl<const N : usize, const M : usize> RemAssignWithQuotient for ArbitraryBytes< macro_rules! make_div_assign_with_remainder { ($name:ident, $t_divisor:ty, $t_long:ty) => { /// Replaces self with Quotient and returns Remainder - fn $name(&mut self, rhs: &$t_divisor) -> $t_divisor { + fn $name(&mut self, rhs: $t_divisor) -> $t_divisor { debug_assert!((<$t_long>::MAX >> 32) as u128 >= <$t_divisor>::MAX as u128); - let divisor = *rhs as $t_long; + let divisor = rhs as $t_long; let remainder = self.0.iter_mut().fold(0 as $t_long,|carry, current| { debug_assert_eq!(carry, carry & (<$t_divisor>::MAX as $t_long)); //carry has to be lower than divisor, and divisor is $t_divisor. let carry_shifted = carry << 32; @@ -399,7 +403,7 @@ impl<const N : usize> ArbitraryBytes<N>{ make_div_assign_with_remainder!(div_assign_with_remainder_u32, u32, u64); - fn rem_assign_with_quotient_u32(&mut self, divisor: &u32) -> Self where Self : for<'a> From<&'a u32> { + fn rem_assign_with_quotient_u32(&mut self, divisor: u32) -> Self where Self : for<'a> From<&'a u32> { let remainder = self.div_assign_with_remainder_u32(divisor); std::mem::replace(self, Self::from(&remainder)) } @@ -427,8 +431,8 @@ impl<const N : usize> ArbitraryBytes<N>{ let mut quotient : Self = (&0_usize).into(); //needed for Step D3, but is the same for all iterations -> factored out. - let guess_divisor = divisor.get_digit_from_right(n_digits_divisor - 1) as u64; - let divisor_second_significant_digit = divisor.get_digit_from_right(n_digits_divisor-2) as u64; + let guess_divisor = u64::from(divisor.get_digit_from_right(n_digits_divisor - 1)); + let divisor_second_significant_digit = u64::from(divisor.get_digit_from_right(n_digits_divisor-2)); //step D2, D7: the loop. for j in (0..=m_extra_digits_dividend).rev() { @@ -437,16 +441,17 @@ impl<const N : usize> ArbitraryBytes<N>{ let mut guesstimate = guess_dividend/guess_divisor; let mut guess_reminder = guess_dividend % guess_divisor; //refine our guesstimate (still step D3). Ensures that error of guesstimate is either 0 or +1. - while guess_reminder <= u32::MAX as u64 - && (guesstimate > u32::MAX as u64 + while u32::try_from(guess_reminder).is_ok() + && (guesstimate > u64::from(u32::MAX) || divisor_second_significant_digit * guesstimate - > (guess_reminder << 32) | (dividend.get_digit_from_right(j + n_digits_divisor - 2) as u64) + > (guess_reminder << 32) | u64::from(dividend.get_digit_from_right(j + n_digits_divisor - 2)) ) { guesstimate -= 1; guess_reminder += guess_divisor; } //Step D4: Pretend the guess was correct and subtract guesstimate * divisor from dividend. - debug_assert!(guesstimate & (u32::MAX as u64) == guesstimate, "The while above should have made guesstimate a one-digit number. Debug!"); + debug_assert!(guesstimate & u64::from(u32::MAX) == guesstimate, "The while above should have made guesstimate a one-digit number. Debug!"); + #[allow(clippy::cast_possible_truncation)] let mut guesstimate = guesstimate as u32; let s = (divisor.clone() * guesstimate).expect("Multipliation by a digit cannot overflow for a padded type."); let s_range = (M - 1 - n_digits_divisor)..M; @@ -458,7 +463,7 @@ impl<const N : usize> ArbitraryBytes<N>{ guesstimate -= 1; //The addition must overflow again. The two overflows cancel out, and since we are using wrapping arithmetics, the result becomes correct again. let did_overflow = slice_overflowing_add_assign(&mut dividend.0[d_range], &divisor.0[s_range]); - debug_assert!(did_overflow, "Knuth, TAOCP Vol 2, Chap 4.3.1 exercise 21 says: if this fails, the while above is wrong. Debug.") + debug_assert!(did_overflow, "Knuth, TAOCP Vol 2, Chap 4.3.1 exercise 21 says: if this fails, the while above is wrong. Debug."); } quotient.set_digit_from_right(guesstimate, j); } @@ -516,10 +521,10 @@ fn slice_overflowing_add_assign(lhs : &mut [u32], rhs : &[u32]) -> bool { }) } -fn u64_from_u32s(msb : u32, lsb : u32) -> u64{ - let msb = msb as u64; - let lsb = lsb as u64; - (msb << 32) | lsb +fn u64_from_u32s(m : u32, l : u32) -> u64{ + let m = m as u64; + let l = l as u64; + (m << 32) | l } #[cfg(test)] @@ -640,7 +645,7 @@ mod arbitrary_bytes_tests{ fn rem_assign_with_quotient_u32_many_numbers_test() { let input = prepare_many_numbers(4,1, 1, 1); for (mut dividend, divisor, expected_quotient, expexted_remainder) in input { - let quotient = dividend.rem_assign_with_quotient_u32(&divisor.0.last().unwrap()); + let quotient = dividend.rem_assign_with_quotient_u32(*divisor.0.last().unwrap()); let remainder = dividend; let quotient = ((quotient.0[1] as u128)<<(96)) + ((quotient.0[2] as u128)<<64) + ((quotient.0[3] as u128)<<32) + (quotient.0[4] as u128); let remainder = ((remainder.0[1] as u128)<<(96)) + ((remainder.0[2] as u128)<<64) + ((remainder.0[3] as u128)<<32) + (remainder.0[4] as u128); @@ -652,7 +657,7 @@ mod arbitrary_bytes_tests{ #[test] fn rem_assign_with_quotient_u32_test(){ let mut a = ArbitraryBytes::new([0xaf4a816a,0xb414f734,0x7a2167c7,0x47ea7314,0xfba75574]); - let quotient = a.rem_assign_with_quotient_u32(&0x12345); + let quotient = a.rem_assign_with_quotient_u32(0x12345); assert_eq!(quotient.0, [0x9A10,0xB282B7BA,0xE4948E98,0x2AE63D74,0xE6FDFF4A]); assert_eq!(a.0, [0,0,0,0,0x6882]); } @@ -660,7 +665,7 @@ mod arbitrary_bytes_tests{ #[test] fn rem_assign_with_quotient_u32_test2(){ let mut a = ArbitraryBytes::new([0,0,0,0,0x1234]); - let quotient = a.rem_assign_with_quotient_u32(&0x12345); + let quotient = a.rem_assign_with_quotient_u32(0x12345); assert_eq!(quotient.0, [0,0,0,0,0]); assert_eq!(a.0, [0,0,0,0,0x1234]); } @@ -668,7 +673,7 @@ mod arbitrary_bytes_tests{ #[test] fn div_assign_with_remainder_usize_test(){ let mut a = ArbitraryBytes::new([0xaf4a816a,0xb414f734,0x7a2167c7,0x47ea7314,0xfba75574]); - let remainder = a.div_assign_with_remainder_usize(&0x1234_usize); + let remainder = a.div_assign_with_remainder_usize(0x1234_usize); assert_eq!(a.0, [0x9A135,0x79AA8650,0xD251DC7A,0x9AA8C1F2,0x8B9729EF]); assert_eq!(remainder, 0x2E8); } @@ -676,7 +681,7 @@ mod arbitrary_bytes_tests{ #[test] fn div_assign_with_remainder_usize_test2(){ let mut a = ArbitraryBytes::new([0,0,0,0,0x1234]); - let remainder = a.div_assign_with_remainder_usize(&0x1235_usize); + let remainder = a.div_assign_with_remainder_usize(0x1235_usize); assert_eq!(a.0, [0,0,0,0,0]); assert_eq!(remainder, 0x1234); } @@ -685,7 +690,7 @@ mod arbitrary_bytes_tests{ #[test] fn div_assign_with_remainder_usize_test3(){ let mut a = ArbitraryBytes::new([0xaf4a816a,0xb414f734,0x7a2167c7,0x47ea7314,0xfba75574]); - let remainder = a.div_assign_with_remainder_usize(&0x123456789ab_usize); + let remainder = a.div_assign_with_remainder_usize(0x123456789ab_usize); assert_eq!(a.0, [0,0x9A107B,0xBEC8B35A,0xEC9D3B43,0x056F803A]); assert_eq!(remainder, 0xD7537A4B6); } @@ -961,7 +966,7 @@ mod arbitrary_bytes_tests{ None } else { let mut v = v.clone(); - let remainder = v.div_assign_with_remainder_usize(&base); + let remainder = v.div_assign_with_remainder_usize(base); Some((v, remainder)) } }).skip(1).map(|(_,b)| b).collect::<Vec<_>>().into_iter().rev() |