ruint/algorithms/
shift.rs

1#[inline(always)]
2pub fn shift_left_small(limbs: &mut [u64], amount: usize) -> u64 {
3    debug_assert!(amount < 64);
4    let mut overflow = 0;
5    for limb in limbs {
6        let value = (*limb << amount) | overflow;
7        overflow = *limb >> (64 - amount);
8        *limb = value;
9    }
10    overflow
11}
12
13#[inline(always)]
14pub fn shift_right_small(limbs: &mut [u64], amount: usize) -> u64 {
15    debug_assert!(amount < 64);
16
17    let mut overflow = 0;
18    for limb in limbs.iter_mut().rev() {
19        let value = (*limb >> amount) | overflow;
20        overflow = *limb << (64 - amount);
21        *limb = value;
22    }
23    overflow
24}
25
26#[cfg(test)]
27mod tests {
28    use super::*;
29
30    #[test]
31    fn test_shift_left_small() {
32        let mut limbs = [0x1234_5678_9abc_def0, 0x1234_5678_9abc_def0];
33        let overflow = shift_left_small(&mut limbs, 4);
34        assert_eq!(limbs, [0x2345_6789_abcd_ef00, 0x2345_6789_abcd_ef01]);
35        assert_eq!(overflow, 0x1);
36    }
37
38    #[test]
39    fn test_shift_right_small() {
40        let mut limbs = [0x1234_5678_9abc_deff, 0x1234_5678_9abc_def0];
41        let overflow = shift_right_small(&mut limbs, 4);
42        assert_eq!(limbs, [0x0123_4567_89ab_cdef, 0x0123_4567_89ab_cdef]);
43        assert_eq!(overflow, 0xf << 60);
44    }
45}