1 use std::ops::{AddAssign, MulAssign}; 2 3 // For implementing base10_digits() accessor on LitInt. 4 pub struct BigInt { 5 digits: Vec<u8>, 6 } 7 8 impl BigInt { new() -> Self9 pub fn new() -> Self { 10 BigInt { digits: Vec::new() } 11 } 12 to_string(&self) -> String13 pub fn to_string(&self) -> String { 14 let mut repr = String::with_capacity(self.digits.len()); 15 16 let mut has_nonzero = false; 17 for digit in self.digits.iter().rev() { 18 has_nonzero |= *digit != 0; 19 if has_nonzero { 20 repr.push((*digit + b'0') as char); 21 } 22 } 23 24 if repr.is_empty() { 25 repr.push('0'); 26 } 27 28 repr 29 } 30 reserve_two_digits(&mut self)31 fn reserve_two_digits(&mut self) { 32 let len = self.digits.len(); 33 let desired = 34 len + !self.digits.ends_with(&[0, 0]) as usize + !self.digits.ends_with(&[0]) as usize; 35 self.digits.resize(desired, 0); 36 } 37 } 38 39 impl AddAssign<u8> for BigInt { 40 // Assumes increment <16. add_assign(&mut self, mut increment: u8)41 fn add_assign(&mut self, mut increment: u8) { 42 self.reserve_two_digits(); 43 44 let mut i = 0; 45 while increment > 0 { 46 let sum = self.digits[i] + increment; 47 self.digits[i] = sum % 10; 48 increment = sum / 10; 49 i += 1; 50 } 51 } 52 } 53 54 impl MulAssign<u8> for BigInt { 55 // Assumes base <=16. mul_assign(&mut self, base: u8)56 fn mul_assign(&mut self, base: u8) { 57 self.reserve_two_digits(); 58 59 let mut carry = 0; 60 for digit in &mut self.digits { 61 let prod = *digit * base + carry; 62 *digit = prod % 10; 63 carry = prod / 10; 64 } 65 } 66 } 67