From 94f39fff07e352c200780828e569342bc4f6ab44 Mon Sep 17 00:00:00 2001 From: Timothy Warren Date: Wed, 4 Mar 2020 16:16:28 -0500 Subject: [PATCH] Start implementations of basic arithmatic operators --- src/bigint.rs | 206 +++++++++++++++++++++++++++++++++++--------------- 1 file changed, 147 insertions(+), 59 deletions(-) diff --git a/src/bigint.rs b/src/bigint.rs index 376ba0b..0a5f8cd 100644 --- a/src/bigint.rs +++ b/src/bigint.rs @@ -1,18 +1,15 @@ //! \[WIP\] Arbitrarily large integers //! //! Traits to implement: -//! * Add -//! * AddAssign -//! * Div -//! * DivAssign -//! * Mul -//! * MulAssign //! * Neg //! * Rem //! * RemAssign //! * Sub //! * SubAssign use crate::num::*; +use core::ops::{ + Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Not, Rem, RemAssign, Sub, SubAssign, +}; #[derive(Clone, Debug)] pub struct BigInt { @@ -37,64 +34,19 @@ macro_rules! impl_from_smaller { #[cfg(target_pointer_width = "16")] impl_from_smaller!(u8, u16); - #[cfg(target_pointer_width = "16")] static BITS:usize = 16; #[cfg(target_pointer_width = "32")] impl_from_smaller!(u8, u16, u32); - #[cfg(target_pointer_width = "32")] static BITS:usize = 32; #[cfg(target_pointer_width = "64")] impl_from_smaller!(u8, u16, u32, u64); - #[cfg(target_pointer_width = "64")] static BITS:usize = 64; -fn add(u: BigInt, v: BigInt) -> BigInt { - let mut out = BigInt::default(); - - let u_digits = u.inner.len(); - let v_digits = v.inner.len(); - - let digits = if v_digits > u_digits { - v_digits - } else { - u_digits - }; - - let mut carry = 0usize; - for i in 0..=digits { - let a = *u.inner.get(i).unwrap_or(&0usize); - let b = *v.inner.get(i).unwrap_or(&0usize); - - let (res, overflowed) = a.overflowing_add(b); - // assert!(!overflowed, "Expected to overflow: {:#?}", (res, overflowed)); - if overflowed { - if i == 0 { - out.inner[i] = res; - } else { - out.inner.push(res); - } - carry = core::usize::MAX - res; - } else { - if res < core::usize::MAX { - out.inner.push(res + carry); - carry = 0; - } else { - out.inner.push(0usize); - carry = 1; - } - - carry = 0; - } - } - - out -} - impl Default for BigInt { fn default() -> Self { Self { @@ -114,14 +66,14 @@ impl From for BigInt { } impl From<&str> for BigInt { - fn from(_: &str) -> Self { - unimplemented!() + fn from(s: &str) -> Self { + Self::from_str_radix(s, 10) } } impl From for BigInt { - fn from(_: String) -> Self { - unimplemented!() + fn from(s: String) -> Self { + Self::from_str_radix(s, 10) } } @@ -134,11 +86,130 @@ impl BigInt { todo!(); } - pub fn from_str_radix(s: T, radix: usize) { + pub fn from_str_radix(s: T, radix: usize) -> BigInt { todo!(); } } +impl Add for BigInt { + type Output = Self; + + fn add(self, rhs: Self) -> Self::Output { + let mut out = BigInt::default(); + + let u_digits = self.inner.len(); + let v_digits = rhs.inner.len(); + + let digits = if v_digits > u_digits { + v_digits + } else { + u_digits + }; + + let mut carry = 0usize; + for i in 0..=digits { + let a = *self.inner.get(i).unwrap_or(&0usize); + let b = *rhs.inner.get(i).unwrap_or(&0usize); + + let (res, overflowed) = a.overflowing_add(b); + // assert!(!overflowed, "Expected to overflow: {:#?}", (res, overflowed)); + if overflowed { + if i == 0 { + out.inner[i] = res; + } else { + out.inner.push(res); + } + carry = core::usize::MAX - res; + } else { + if res < core::usize::MAX { + out.inner.push(res + carry); + carry = 0; + } else { + out.inner.push(0usize); + carry = 1; + } + + carry = 0; + } + } + + out + } +} + +impl Sub for BigInt { + type Output = Self; + + fn sub(self, rhs: Self) -> Self::Output { + unimplemented!() + } +} + +impl Mul for BigInt { + type Output = Self; + + fn mul(self, rhs: Self) -> Self::Output { + unimplemented!() + } +} + +impl Div for BigInt { + type Output = Self; + + fn div(self, rhs: Self) -> Self::Output { + unimplemented!() + } +} + +impl Rem for BigInt { + type Output = Self; + + fn rem(self, rhs: Self) -> Self::Output { + unimplemented!() + } +} + +impl AddAssign for BigInt { + fn add_assign(&mut self, rhs: Self) { + *self = self.clone() + rhs; + } +} + +impl SubAssign for BigInt { + fn sub_assign(&mut self, rhs: Self) { + *self = self.clone() - rhs; + } +} + +impl MulAssign for BigInt { + fn mul_assign(&mut self, rhs: Self) { + *self = self.clone() * rhs; + } +} + +impl DivAssign for BigInt { + fn div_assign(&mut self, rhs: Self) { + *self = self.clone() / rhs; + } +} + +impl RemAssign for BigInt { + fn rem_assign(&mut self, rhs: Self) { + *self = self.clone() % rhs; + } +} + +impl Neg for BigInt { + type Output = Self; + + fn neg(self) -> Self::Output { + let mut output = self.clone(); + output.sign = !output.sign; + + output + } +} + #[cfg(test)] mod tests { use super::*; @@ -158,11 +229,28 @@ mod tests { let a = BigInt::from(core::usize::MAX); let b = BigInt::from(core::usize::MAX); - let sum = add(a, b); + let sum = a + b; - assert_eq!(sum.inner[0], core::usize::MAX - 1, "least significant place should be MAX - 1"); + assert_eq!( + sum.inner[0], + core::usize::MAX - 1, + "least significant place should be MAX - 1" + ); assert_eq!(sum.inner[1], 1usize, "most significant place should be 1"); + } - // assert!(false, "{:#?} should have inner equal to {:?}", sum, core::u64::MAX as u128 + core::u64::MAX as u128); + #[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"); } }