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