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