X-Git-Url: https://git.ralfj.de/rust-101.git/blobdiff_plain/17ab30e2988868e5f59b36bb0364cadb0a1c42f8..35c4d2161ea07cfbb4085d7e5242ab9939889afa:/solutions/src/bigint.rs?ds=inline diff --git a/solutions/src/bigint.rs b/solutions/src/bigint.rs index 0abb6b3..91e3ccf 100644 --- a/solutions/src/bigint.rs +++ b/solutions/src/bigint.rs @@ -55,15 +55,35 @@ impl BigInt { } } - /// Construct a BigInt from a vector of 64-bit "digits", with the last significant digit being first + /// Construct a BigInt from a vector of 64-bit "digits", with the last significant digit being first. Solution to 05.1. pub fn from_vec(mut v: Vec) -> Self { - // remove trailing zeroes + // remove trailing zeros while v.len() > 0 && v[v.len()-1] == 0 { v.pop(); } BigInt { data: v } } + /// Increments the number by 1. + pub fn inc1(&mut self) { + let mut idx = 0; + // This loop adds "(1 << idx)". If there is no more carry, we leave. + while idx < self.data.len() { + let cur = self.data[idx]; + let sum = u64::wrapping_add(cur, 1); + self.data[idx] = sum; + if sum >= cur { + // No overflow, we are done. + return; + } else { + // We need to go on. + idx += 1; + } + } + // If we came here, there is a last carry to add + self.data.push(1); + } + /// Increments the number by "by". pub fn inc(&mut self, mut by: u64) { let mut idx = 0; @@ -111,6 +131,7 @@ impl PartialEq for BigInt { } impl Minimum for BigInt { + // This is essentially the solution to 06.1. fn min<'a>(&'a self, other: &'a Self) -> &'a Self { debug_assert!(self.test_invariant() && other.test_invariant()); if self.data.len() < other.data.len() { @@ -191,6 +212,7 @@ impl ops::Add for BigInt { #[cfg(test)] mod tests { + use std::u64; use super::overflowing_add; use super::BigInt; @@ -203,6 +225,21 @@ mod tests { assert_eq!(overflowing_add(1 << 63, (1 << 63) -1 , true), (0, true)); } + #[test] + fn test_inc1() { + let mut b = BigInt::new(0); + b.inc1(); + assert_eq!(b, BigInt::new(1)); + b.inc1(); + assert_eq!(b, BigInt::new(2)); + + b = BigInt::new(u64::MAX); + b.inc1(); + assert_eq!(b, BigInt::from_vec(vec![0, 1])); + b.inc1(); + assert_eq!(b, BigInt::from_vec(vec![1, 1])); + } + #[test] fn test_power_of_2() { assert_eq!(BigInt::power_of_2(0), BigInt::new(1));