Start implementations of basic arithmatic operators
All checks were successful
timw4mail/rusty-numbers/pipeline/head This commit looks good

This commit is contained in:
Timothy Warren 2020-03-04 16:16:28 -05:00
parent fce5d42be2
commit 94f39fff07

View File

@ -1,18 +1,15 @@
//! \[WIP\] Arbitrarily large integers //! \[WIP\] Arbitrarily large integers
//! //!
//! Traits to implement: //! Traits to implement:
//! * Add
//! * AddAssign
//! * Div
//! * DivAssign
//! * Mul
//! * MulAssign
//! * Neg //! * Neg
//! * Rem //! * Rem
//! * RemAssign //! * RemAssign
//! * Sub //! * Sub
//! * SubAssign //! * SubAssign
use crate::num::*; use crate::num::*;
use core::ops::{
Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Not, Rem, RemAssign, Sub, SubAssign,
};
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct BigInt { pub struct BigInt {
@ -37,27 +34,71 @@ macro_rules! impl_from_smaller {
#[cfg(target_pointer_width = "16")] #[cfg(target_pointer_width = "16")]
impl_from_smaller!(u8, u16); impl_from_smaller!(u8, u16);
#[cfg(target_pointer_width = "16")] #[cfg(target_pointer_width = "16")]
static BITS:usize = 16; static BITS:usize = 16;
#[cfg(target_pointer_width = "32")] #[cfg(target_pointer_width = "32")]
impl_from_smaller!(u8, u16, u32); impl_from_smaller!(u8, u16, u32);
#[cfg(target_pointer_width = "32")] #[cfg(target_pointer_width = "32")]
static BITS:usize = 32; static BITS:usize = 32;
#[cfg(target_pointer_width = "64")] #[cfg(target_pointer_width = "64")]
impl_from_smaller!(u8, u16, u32, u64); impl_from_smaller!(u8, u16, u32, u64);
#[cfg(target_pointer_width = "64")] #[cfg(target_pointer_width = "64")]
static BITS:usize = 64; static BITS:usize = 64;
fn add(u: BigInt, v: BigInt) -> BigInt { impl Default for BigInt {
fn default() -> Self {
Self {
inner: vec![0],
sign: Sign::Positive,
}
}
}
impl From<usize> for BigInt {
fn from(n: usize) -> Self {
Self {
inner: vec![n],
sign: Sign::Positive,
}
}
}
impl From<&str> for BigInt {
fn from(s: &str) -> Self {
Self::from_str_radix(s, 10)
}
}
impl From<String> for BigInt {
fn from(s: String) -> Self {
Self::from_str_radix(s, 10)
}
}
impl BigInt {
pub fn new() -> Self {
Self::default()
}
pub fn shrink_to_fit(&mut self) {
todo!();
}
pub fn from_str_radix<T: ToString>(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 mut out = BigInt::default();
let u_digits = u.inner.len(); let u_digits = self.inner.len();
let v_digits = v.inner.len(); let v_digits = rhs.inner.len();
let digits = if v_digits > u_digits { let digits = if v_digits > u_digits {
v_digits v_digits
@ -67,8 +108,8 @@ fn add(u: BigInt, v: BigInt) -> BigInt {
let mut carry = 0usize; let mut carry = 0usize;
for i in 0..=digits { for i in 0..=digits {
let a = *u.inner.get(i).unwrap_or(&0usize); let a = *self.inner.get(i).unwrap_or(&0usize);
let b = *v.inner.get(i).unwrap_or(&0usize); let b = *rhs.inner.get(i).unwrap_or(&0usize);
let (res, overflowed) = a.overflowing_add(b); let (res, overflowed) = a.overflowing_add(b);
// assert!(!overflowed, "Expected to overflow: {:#?}", (res, overflowed)); // assert!(!overflowed, "Expected to overflow: {:#?}", (res, overflowed));
@ -94,48 +135,78 @@ fn add(u: BigInt, v: BigInt) -> BigInt {
out out
} }
impl Default for BigInt {
fn default() -> Self {
Self {
inner: vec![0],
sign: Sign::Positive,
}
}
} }
impl From<usize> for BigInt { impl Sub for BigInt {
fn from(n: usize) -> Self { type Output = Self;
Self {
inner: vec![n],
sign: Sign::Positive,
}
}
}
impl From<&str> for BigInt { fn sub(self, rhs: Self) -> Self::Output {
fn from(_: &str) -> Self {
unimplemented!() unimplemented!()
} }
} }
impl From<String> for BigInt { impl Mul for BigInt {
fn from(_: String) -> Self { type Output = Self;
fn mul(self, rhs: Self) -> Self::Output {
unimplemented!() unimplemented!()
} }
} }
impl BigInt { impl Div for BigInt {
pub fn new() -> Self { type Output = Self;
Self::default()
fn div(self, rhs: Self) -> Self::Output {
unimplemented!()
}
} }
pub fn shrink_to_fit(&mut self) { impl Rem for BigInt {
todo!(); type Output = Self;
fn rem(self, rhs: Self) -> Self::Output {
unimplemented!()
}
} }
pub fn from_str_radix<T: ToString>(s: T, radix: usize) { impl AddAssign for BigInt {
todo!(); 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
} }
} }
@ -158,11 +229,28 @@ mod tests {
let a = BigInt::from(core::usize::MAX); let a = BigInt::from(core::usize::MAX);
let b = 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_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");
} }
} }