From d5d973060794e64a3c72826b10c99cff0e51253e Mon Sep 17 00:00:00 2001 From: Timothy Warren Date: Tue, 3 Mar 2020 16:33:21 -0500 Subject: [PATCH] First shot at adding bigints --- src/bigint.rs | 103 +++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 93 insertions(+), 10 deletions(-) diff --git a/src/bigint.rs b/src/bigint.rs index a87a461..51e4df6 100644 --- a/src/bigint.rs +++ b/src/bigint.rs @@ -20,24 +20,96 @@ pub struct BigInt { sign: Sign, } +macro_rules! impl_from_smaller { + ($($Type: ty),* ) => { + $( + impl From<$Type> for BigInt { + fn from(n: $Type) -> Self { + let mut new = Self::default(); + new.inner[0] = n as usize; + + new + } + } + )* + } +} + +#[cfg(target_pointer_width = "16")] +impl_from_smaller!(u8, u16); + +#[cfg(target_pointer_width = "32")] +impl_from_smaller!(u8, u16, u32); + +#[cfg(target_pointer_width = "64")] +impl_from_smaller!(u8, u16, u32, u64); + +#[cfg(target_pointer_width = "16")] +static BITS:usize = 16; + +#[cfg(target_pointer_width = "32")] +static BITS:usize = 32; + +#[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 + 1; + } 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 { - inner: vec![], + inner: vec![0], sign: Sign::Positive, } } } -impl From for BigInt { - fn from(n: T) -> Self { - let mut new = Self::default(); - - if n > T::max_value() { - new.split(n); +impl From for BigInt { + fn from(n: usize) -> Self { + Self { + inner: vec![n], + sign: Sign::Positive, } - - new } } @@ -84,6 +156,17 @@ mod tests { #[test] fn sanity_checks() { - + let int = BigInt::from(45u8); + assert_eq!(int.inner[0], 45usize) } + + /* #[test] + fn test_add() { + let a = BigInt::from(core::u64::MAX); + let b = BigInt::from(core::u64::MAX); + + let sum = add(a, b); + + assert!(false, "{:#?} should have inner equal to {:?}", sum, core::u64::MAX as u128 + core::u64::MAX as u128); + } */ }