diff --git a/src/bigint.rs b/src/bigint.rs index e5ebd37..336ec7c 100644 --- a/src/bigint.rs +++ b/src/bigint.rs @@ -2,11 +2,12 @@ //! \[WIP\] Arbitrarily large integers use crate::num::Sign::*; use crate::num::*; +use core::convert::TryInto; +use core::mem::replace; use core::ops::{ Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Not, Rem, RemAssign, Sub, SubAssign, }; use core::usize; -use std::convert::TryInto; #[derive(Clone, Debug, PartialEq)] pub struct BigInt { @@ -242,7 +243,7 @@ impl Mul for BigInt { } } - out.trim_zeros(); + out.shrink_to_fit(); out } @@ -266,31 +267,36 @@ impl Rem for BigInt { impl AddAssign for BigInt { fn add_assign(&mut self, rhs: Self) { - *self = self.clone() + rhs; + let this = replace(self, BigInt::new()); + *self = this + rhs; } } impl SubAssign for BigInt { fn sub_assign(&mut self, rhs: Self) { - *self = self.clone() - rhs; + let this = replace(self, BigInt::new()); + *self = this - rhs; } } impl MulAssign for BigInt { fn mul_assign(&mut self, rhs: Self) { - *self = self.clone() * rhs; + let this = replace(self, BigInt::new()); + *self = this * rhs; } } impl DivAssign for BigInt { fn div_assign(&mut self, rhs: Self) { - *self = self.clone() / rhs; + let this = replace(self, BigInt::new()); + *self = this / rhs; } } impl RemAssign for BigInt { fn rem_assign(&mut self, rhs: Self) { - *self = self.clone() % rhs; + let this = replace(self, BigInt::new()); + *self = this % rhs; } } @@ -445,6 +451,21 @@ mod tests { assert_eq!(sum.inner[1], 1usize); } + #[test] + fn test_add_assign() { + let mut a = BigInt::from(core::usize::MAX); + let b = BigInt::from(core::usize::MAX); + + a += b; + + assert_eq!( + a.inner[0], + core::usize::MAX - 1, + "least significant place should be MAX - 1" + ); + assert_eq!(a.inner[1], 1usize, "most significant place should be 1"); + } + #[test] fn test_sub() { let a = BigInt::from(core::usize::MAX); @@ -484,6 +505,69 @@ mod tests { assert_eq!(a.inner, vec![core::usize::MAX, core::usize::MAX]); } + #[test] + fn test_mul() { + let a = BigInt::from(65536); + let b = BigInt::from(4); + + let product = a * b; + assert_eq!(product.inner[0], 65536usize * 4); + } + + #[test] + #[should_panic] + fn test_mul_overflow() { + let a = BigInt::from(core::usize::MAX); + let b = BigInt::from(5); + + let product = a * b; + } + + #[test] + #[should_panic] + fn test_mul_assign_overflow() { + let mut a = BigInt::from(core::usize::MAX); + let b = BigInt::from(5); + + a *= b; + } + + #[test] + #[should_panic] + fn test_div() { + let a = BigInt::from(128); + let b = BigInt::from(32); + + let quotient = a / b; + } + + #[test] + #[should_panic] + fn test_div_assign() { + let mut a = BigInt::from(128); + let b = BigInt::from(32); + + a /= b; + } + + #[test] + #[should_panic] + fn test_rem() { + let a = BigInt::from(5); + let b = BigInt::from(2); + + let rem = a % b; + } + + #[test] + #[should_panic] + fn test_rem_assign() { + let mut a = BigInt::from(5); + let b = BigInt::from(2); + + a %= b; + } + #[test] fn test_zeros() { let a = BigInt::new(); @@ -506,21 +590,6 @@ mod tests { assert_eq!(b.inner[0], core::usize::MAX); } - #[test] - fn test_add_assign() { - let mut a = BigInt::from(core::usize::MAX); - let b = BigInt::from(core::usize::MAX); - - a += b; - - assert_eq!( - a.inner[0], - core::usize::MAX - 1, - "least significant place should be MAX - 1" - ); - assert_eq!(a.inner[1], 1usize, "most significant place should be 1"); - } - #[test] fn test_from() { // Signed numbers @@ -529,4 +598,16 @@ mod tests { // Larger than usize assert_eq!(BigInt::from(45u128), BigInt::from(45usize)); } + + #[test] + #[should_panic] + fn test_from_large_unsigned() { + BigInt::from(core::u128::MAX); + } + + #[test] + #[should_panic] + fn test_from_large_signed() { + BigInt::from(128i128); + } }