1 #[cfg(test)] 2 mod fixed_big_int_test; 3 4 use std::fmt; 5 6 // FixedBigInt is the fix-sized multi-word integer. 7 pub(crate) struct FixedBigInt { 8 bits: Vec<u64>, 9 n: usize, 10 msb_mask: u64, 11 } 12 13 impl fmt::Display for FixedBigInt { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result14 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 15 let mut out = String::new(); 16 for i in (0..self.bits.len()).rev() { 17 out += format!("{:016X}", self.bits[i]).as_str(); 18 } 19 20 write!(f, "{out}") 21 } 22 } 23 24 impl FixedBigInt { new(n: usize) -> Self25 pub(crate) fn new(n: usize) -> Self { 26 let mut chunk_size = (n + 63) / 64; 27 if chunk_size == 0 { 28 chunk_size = 1; 29 } 30 31 FixedBigInt { 32 bits: vec![0; chunk_size], 33 n, 34 msb_mask: if n % 64 == 0 { 35 u64::MAX 36 } else { 37 (1 << (64 - n % 64)) - 1 38 }, 39 } 40 } 41 42 // lsh is the left shift operation. lsh(&mut self, n: usize)43 pub(crate) fn lsh(&mut self, n: usize) { 44 if n == 0 { 45 return; 46 } 47 let n_chunk = (n / 64) as isize; 48 let n_n = n % 64; 49 50 for i in (0..self.bits.len() as isize).rev() { 51 let mut carry: u64 = 0; 52 if i - n_chunk >= 0 { 53 carry = if n_n >= 64 { 54 0 55 } else { 56 self.bits[(i - n_chunk) as usize] << n_n 57 }; 58 if i - n_chunk > 0 { 59 carry |= if n_n == 0 { 60 0 61 } else { 62 self.bits[(i - n_chunk - 1) as usize] >> (64 - n_n) 63 }; 64 } 65 } 66 self.bits[i as usize] = if n >= 64 { 67 carry 68 } else { 69 (self.bits[i as usize] << n) | carry 70 }; 71 } 72 73 let last = self.bits.len() - 1; 74 self.bits[last] &= self.msb_mask; 75 } 76 77 // bit returns i-th bit of the fixedBigInt. bit(&self, i: usize) -> usize78 pub(crate) fn bit(&self, i: usize) -> usize { 79 if i >= self.n { 80 return 0; 81 } 82 let chunk = i / 64; 83 let pos = i % 64; 84 usize::from(self.bits[chunk] & (1 << pos) != 0) 85 } 86 87 // set_bit sets i-th bit to 1. set_bit(&mut self, i: usize)88 pub(crate) fn set_bit(&mut self, i: usize) { 89 if i >= self.n { 90 return; 91 } 92 let chunk = i / 64; 93 let pos = i % 64; 94 self.bits[chunk] |= 1 << pos; 95 } 96 } 97