crypto_bigint/uint/
shl.rs
1use crate::{Limb, UInt, Word};
4use core::ops::{Shl, ShlAssign};
5
6impl<const LIMBS: usize> UInt<LIMBS> {
7 #[inline(always)]
14 pub const fn shl_vartime(&self, n: usize) -> Self {
15 let mut limbs = [Limb::ZERO; LIMBS];
16
17 if n >= Limb::BIT_SIZE * LIMBS {
18 return Self { limbs };
19 }
20
21 let shift_num = n / Limb::BIT_SIZE;
22 let rem = n % Limb::BIT_SIZE;
23 let nz = Limb(rem as Word).is_nonzero();
24 let lshift_rem = rem as Word;
25 let rshift_rem = Limb::ct_select(Limb::ZERO, Limb((Limb::BIT_SIZE - rem) as Word), nz).0;
26
27 let mut i = LIMBS - 1;
28 while i > shift_num {
29 let mut limb = self.limbs[i - shift_num].0 << lshift_rem;
30 let hi = self.limbs[i - shift_num - 1].0 >> rshift_rem;
31 limb |= hi & nz;
32 limbs[i] = Limb(limb);
33 i -= 1
34 }
35 limbs[shift_num] = Limb(self.limbs[0].0 << lshift_rem);
36
37 Self { limbs }
38 }
39}
40
41impl<const LIMBS: usize> Shl<usize> for UInt<LIMBS> {
42 type Output = UInt<LIMBS>;
43
44 fn shl(self, rhs: usize) -> UInt<LIMBS> {
49 self.shl_vartime(rhs)
50 }
51}
52
53impl<const LIMBS: usize> Shl<usize> for &UInt<LIMBS> {
54 type Output = UInt<LIMBS>;
55
56 fn shl(self, rhs: usize) -> UInt<LIMBS> {
61 self.shl_vartime(rhs)
62 }
63}
64
65impl<const LIMBS: usize> ShlAssign<usize> for UInt<LIMBS> {
66 fn shl_assign(&mut self, rhs: usize) {
71 *self = self.shl_vartime(rhs)
72 }
73}
74
75#[cfg(test)]
76mod tests {
77 use crate::U256;
78
79 const N: U256 =
80 U256::from_be_hex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141");
81
82 const TWO_N: U256 =
83 U256::from_be_hex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD755DB9CD5E9140777FA4BD19A06C8282");
84
85 const FOUR_N: U256 =
86 U256::from_be_hex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFAEABB739ABD2280EEFF497A3340D90504");
87
88 const SIXTY_FIVE: U256 =
89 U256::from_be_hex("FFFFFFFFFFFFFFFD755DB9CD5E9140777FA4BD19A06C82820000000000000000");
90
91 const EIGHTY_EIGHT: U256 =
92 U256::from_be_hex("FFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD03641410000000000000000000000");
93
94 const SIXTY_FOUR: U256 =
95 U256::from_be_hex("FFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD03641410000000000000000");
96
97 #[test]
98 fn shl_simple() {
99 let mut t = U256::from(1u8);
100 assert_eq!(t << 1, U256::from(2u8));
101 t = U256::from(3u8);
102 assert_eq!(t << 8, U256::from(0x300u16));
103 }
104
105 #[test]
106 fn shl1() {
107 assert_eq!(N << 1, TWO_N);
108 }
109
110 #[test]
111 fn shl2() {
112 assert_eq!(N << 2, FOUR_N);
113 }
114
115 #[test]
116 fn shl65() {
117 assert_eq!(N << 65, SIXTY_FIVE);
118 }
119
120 #[test]
121 fn shl88() {
122 assert_eq!(N << 88, EIGHTY_EIGHT);
123 }
124
125 #[test]
126 fn shl256() {
127 assert_eq!(N << 256, U256::default());
128 }
129
130 #[test]
131 fn shl64() {
132 assert_eq!(N << 64, SIXTY_FOUR);
133 }
134}