diff options
author | Andreas Grois <andi@grois.info> | 2022-10-20 23:28:08 +0200 |
---|---|---|
committer | Andreas Grois <andi@grois.info> | 2022-10-20 23:28:08 +0200 |
commit | 8da1c8a10dedb66a21f90957cbbb33c0e0ceece5 (patch) | |
tree | cfa02f1774547bbe4f61bf58fc8f37b596226b57 | |
parent | e484af8f3c683e81d6445a4d66972ca1fa6897a6 (diff) |
Macro for single-digit-division.
Just to remove code duplication.
-rw-r--r-- | src/passwordmaker/base_conversion/iterative_conversion_impl.rs | 74 |
1 files changed, 37 insertions, 37 deletions
diff --git a/src/passwordmaker/base_conversion/iterative_conversion_impl.rs b/src/passwordmaker/base_conversion/iterative_conversion_impl.rs index 94c8b8b..c402b20 100644 --- a/src/passwordmaker/base_conversion/iterative_conversion_impl.rs +++ b/src/passwordmaker/base_conversion/iterative_conversion_impl.rs @@ -310,49 +310,41 @@ impl<const N : usize> SubAssign<&ArbitraryBytes<N>> for ArbitraryBytes<N>{ } } +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 { + debug_assert!((<$t_long>::MAX >> 32) as u128 >= <$t_divisor>::MAX as u128); + + 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; + let dividend = (carry_shifted) | (*current as $t_long); + let remainder = dividend % divisor; + let ratio = dividend / divisor; + debug_assert_eq!(ratio, ratio & 0xffff_ffff); //this is fine. The first digit after re-adding the carry is alwys zero. + *current = (ratio) as u32; + remainder + }); + debug_assert_eq!(remainder, remainder & (<$t_divisor>::MAX as $t_long)); + remainder as $t_divisor + } + }; +} impl<const N : usize> ArbitraryBytes<N>{ pub(super) fn new(data : [u32;N]) -> Self { ArbitraryBytes(data) } - /// Replaces self with Quotient and returns Remainder - fn div_assign_with_remainder_usize(&mut self, rhs: &usize) -> usize { - #[cfg(target_pointer_width = "64")] - type UsizeAndFour = u128; - #[cfg(not(target_pointer_width = "64"))] - type UsizeAndFour = u64; - debug_assert!((UsizeAndFour::MAX >> 32) as u128 >= usize::MAX as u128); - - let divisor : UsizeAndFour = *rhs as UsizeAndFour; - let remainder = self.0.iter_mut().fold(0 as UsizeAndFour,|carry, current| { - debug_assert_eq!(carry, carry & (usize::MAX as UsizeAndFour)); //carry has to be lower than divisor, and divisor is usize. - let carry_shifted = carry << 32; - let dividend = (carry_shifted) + (*current as UsizeAndFour); - let ratio = dividend / divisor; - debug_assert_eq!(ratio, ratio & 0xffff_ffff); //this is fine. The first digit after re-adding the carry is alwys zero. - *current = (ratio) as u32; - dividend - ratio * divisor - }); - debug_assert_eq!(remainder, remainder & (usize::MAX as UsizeAndFour)); - remainder as usize - } - - /// Used in rem_assign_with_quotient_knuth. The normalization factor is u32, and u32 might be larger than usize. - fn div_assign_with_remainder_u32(&mut self, rhs: &u32) -> u32 { - let divisor : u64 = *rhs as u64; - let remainder = self.0.iter_mut().fold(0_u64,|carry, current| { - debug_assert_eq!(carry, carry & (u32::MAX as u64)); //carry has to be lower than divisor, and divisor is usize. - let carry_shifted = carry << 32; - let dividend = (carry_shifted) + (*current as u64); - let ratio = dividend / divisor; - debug_assert_eq!(ratio, ratio & 0xffff_ffff); //this is fine. The first digit after re-adding the carry is alwys zero. - *current = (ratio) as u32; - dividend - ratio * divisor - }); - debug_assert_eq!(remainder, remainder & (u32::MAX as u64)); - remainder as u32 - } + #[cfg(target_pointer_width = "64")] + make_div_assign_with_remainder!(div_assign_with_remainder_usize, usize, u128); + + #[cfg(not(target_pointer_width = "64"))] + make_div_assign_with_remainder!(div_assign_with_remainder_usize, usize, u64); + + 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> { let remainder = self.div_assign_with_remainder_u32(divisor); @@ -570,4 +562,12 @@ mod iterative_conversion_impl_tests{ assert_eq!(remainder, expexted_remainder); } } + + #[test] + fn sub_assign_test() { + let mut a = ArbitraryBytes::new([0xaf4a816a,0xb414f734,0x7a2167c7,0x47ea7314,0xfba75574]); + let b = ArbitraryBytes::new([0x42a7bf02,0xffffffff,0xc7138bd5,0x12345678,0xabcde012]); + a.sub_assign(&b); + assert_eq!(a.0, [0x6CA2C267,0xb414f734,0xb30ddbf2,0x35b61c9c,0x4fd97562]); + } }
\ No newline at end of file |