Add borrowing for subtraction
All checks were successful
timw4mail/rusty-numbers/pipeline/head This commit looks good

This commit is contained in:
Timothy Warren 2020-03-11 10:52:49 -04:00
parent ae77ede1c0
commit a8de0cfa88

View File

@ -1,6 +1,7 @@
#![allow(unused_variables)] #![allow(unused_variables)]
//! \[WIP\] Arbitrarily large integers //! \[WIP\] Arbitrarily large integers
use crate::num::*; use crate::num::*;
use crate::num::Sign::*;
use core::ops::{ use core::ops::{
Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Not, Rem, RemAssign, Sub, SubAssign, Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Not, Rem, RemAssign, Sub, SubAssign,
}; };
@ -100,6 +101,10 @@ impl Add for BigInt {
fn add(self, rhs: Self) -> Self::Output { fn add(self, rhs: Self) -> Self::Output {
// @TODO: handle signs // @TODO: handle signs
if self.sign == Positive && rhs.sign == Negative {
return self - -rhs;
}
let mut out = BigInt::new_empty(); let mut out = BigInt::new_empty();
let u_digits = self.inner.len(); let u_digits = self.inner.len();
@ -153,16 +158,37 @@ impl Sub for BigInt {
let a = *self.inner.get(i).unwrap_or(&0usize); let a = *self.inner.get(i).unwrap_or(&0usize);
let b = *rhs.inner.get(i).unwrap_or(&0usize); let b = *rhs.inner.get(i).unwrap_or(&0usize);
if a > b { if a == 0 && b == 0 {
out.inner.push(a - b - borrow); continue;
}
if a > 0 && (a - borrow) >= b {
let res = a - b - borrow;
// Don't add an extra zero if you borrowed everything
// from the most significant digit
if res == 0 && digits > 0 && i == digits -1 {
return out;
}
out.inner.push(res);
borrow = 0; borrow = 0;
} else if a < b {
todo!();
} else { } else {
todo!(); // To prevent subtraction overflow, the max borrowed
// value is usize::MAX. The rest of the borrowed value
// will be added on afterwords.
// In base ten, this would be like:
// 18 - 9 = 9-9 + 9
let rem = (a + 1) - borrow;
let res = (core::usize::MAX - b) + rem;
out.inner.push(res);
borrow = 1;
} }
} }
out.trim_zeros();
out out
} }
} }
@ -368,9 +394,26 @@ mod tests {
let diff = a - b; let diff = a - b;
assert_eq!( assert_eq!(
diff.inner[0], diff.clone().inner[0],
core::usize::MAX - core::u16::MAX as usize core::usize::MAX - core::u16::MAX as usize
); );
assert_eq!(diff.inner.len(), 1);
}
#[test]
fn test_sub_borrow() {
let a = BigInt {
inner: vec![0, 1],
sign: Positive
};
let b = BigInt::from(2);
let diff = a - b;
assert_eq!(diff.clone().inner.len(), 1, "{:#?}", diff.clone());
assert_eq!(
diff.inner[0],
core::usize::MAX - 1
);
} }
#[test] #[test]