From 3a5f4f250911560faf899ce9b6e1e5e6746fac82 Mon Sep 17 00:00:00 2001 From: Adam Wick Date: Sun, 25 Feb 2018 20:33:24 -0800 Subject: [PATCH] Add some shiftiness. --- src/cryptonum.rs | 119 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 119 insertions(+) diff --git a/src/cryptonum.rs b/src/cryptonum.rs index 99ff208..77c413c 100644 --- a/src/cryptonum.rs +++ b/src/cryptonum.rs @@ -5,6 +5,7 @@ //! of course, but that's its origin. use std::cmp::Ordering; +use std::iter::repeat; use std::ops::*; /// A 512-bit unsigned value @@ -316,6 +317,90 @@ impl<'a> BitXor<&'a U512> for &'a U512 { //------------------------------------------------------------------------------ +impl ShlAssign for U512 { + fn shl_assign(&mut self, amount: usize) { + let digits = amount / 63; + let bits = amount % 63; + let orig = self.contents.clone(); + + for i in 0..9 { + if i < digits { + self.contents[i] = 0; + } else { + let origidx = i - digits; + let prev = if origidx == 0 { 0 } else { orig[origidx - 1] }; + let carry = prev >> (63 - bits); + self.contents[i] = (orig[origidx] << bits) | carry; + self.contents[i] &= 0x7FFFFFFFFFFFFFFF; + } + } + self.contents[8] &= 0xFF; + } +} + +impl Shl for U512 { + type Output = U512; + + fn shl(self, rhs: usize) -> U512 { + let mut copy = self.clone(); + copy <<= rhs; + copy + } +} + +impl<'a> Shl for &'a U512 { + type Output = U512; + + fn shl(self, rhs: usize) -> U512 { + let mut copy = self.clone(); + copy <<= rhs; + copy + } +} + +//------------------------------------------------------------------------------ + +impl ShrAssign for U512 { + fn shr_assign(&mut self, amount: usize) { + let digits = amount / 63; + let bits = amount % 63; + let orig = self.contents.clone(); + + for i in 0..9 { + let oldidx = i + digits; + let caridx = i + digits + 1; + let old = if oldidx > 8 { 0 } else { orig[oldidx] }; + let carry = if caridx > 8 { 0 } else { orig[caridx] }; + let (cb,_) = carry.overflowing_shl(63 - bits as u32); + self.contents[i] = (old >> bits) | cb; + self.contents[i] &= 0x7FFFFFFFFFFFFFFF; + } + self.contents[8] &= 0xFF; + } +} + +impl Shr for U512 { + type Output = U512; + + fn shr(self, rhs: usize) -> U512 { + let mut copy = self.clone(); + copy >>= rhs; + copy + } +} + +impl<'a> Shr for &'a U512 { + type Output = U512; + + fn shr(self, rhs: usize) -> U512 { + let mut copy = self.clone(); + copy >>= rhs; + copy + } +} + +//------------------------------------------------------------------------------ + #[cfg(test)] mod test { use quickcheck::{Arbitrary,Gen}; @@ -475,4 +560,38 @@ mod test { z512.to_u64() == !x } } + + #[test] + fn shl_tests() { + assert_eq!(U512{ contents: [1,1,1,1,1,1,1,1,1] } << 0, + U512{ contents: [1,1,1,1,1,1,1,1,1] }); + assert_eq!(U512{ contents: [1,1,1,1,1,1,1,1,1] } << 512, + U512{ contents: [0,0,0,0,0,0,0,0,0] }); + assert_eq!(U512{ contents: [2,0,0,0,0,0,0,0,0] } << 1, + U512{ contents: [4,0,0,0,0,0,0,0,0] }); + assert_eq!(U512{ contents: [1,0,0,0,0,0,0,0,0] } << 63, + U512{ contents: [0,1,0,0,0,0,0,0,0] }); + assert_eq!(U512{ contents: [1,0,0,0,0,0,0,0,0] } << 65, + U512{ contents: [0,4,0,0,0,0,0,0,0] }); + assert_eq!(U512{ contents: [0x4000000000000000,0,0,0,0,0,0,0,0] } << 1, + U512{ contents: [0,1,0,0,0,0,0,0,0] }); + assert_eq!(U512{ contents: [1,0,0,0,0,0,0,0,0xFF] } << 1, + U512{ contents: [2,0,0,0,0,0,0,0,0xFE] }); + } + + #[test] + fn shr_tests() { + assert_eq!(U512{ contents: [1,1,1,1,1,1,1,1,1] } >> 0, + U512{ contents: [1,1,1,1,1,1,1,1,1] }); + assert_eq!(U512{ contents: [1,1,1,1,1,1,1,1,1] } >> 512, + U512{ contents: [0,0,0,0,0,0,0,0,0] }); + assert_eq!(U512{ contents: [2,0,0,0,0,0,0,0,0] } >> 1, + U512{ contents: [1,0,0,0,0,0,0,0,0] }); + assert_eq!(U512{ contents: [0,1,0,0,0,0,0,0,0] } >> 1, + U512{ contents: [0x4000000000000000,0,0,0,0,0,0,0,0] }); + assert_eq!(U512{ contents: [0,1,0,0,0,0,0,0,0] } >> 63, + U512{ contents: [1,0,0,0,0,0,0,0,0] }); + assert_eq!(U512{ contents: [0,4,0,0,0,0,0,0,0] } >> 65, + U512{ contents: [1,0,0,0,0,0,0,0,0] }); + } }