bigint.rs 1.6 KB

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