Add borrowing for subtraction
timw4mail/rusty-numbers/pipeline/head This commit looks good Details

This commit is contained in:
Timothy Warren 2020-03-11 10:52:49 -04:00
parent ae77ede1c0
commit a8de0cfa88
1 changed files with 50 additions and 7 deletions

View File

@ -1,6 +1,7 @@
#![allow(unused_variables)]
//! \[WIP\] Arbitrarily large integers
use crate::num::*;
use crate::num::Sign::*;
use core::ops::{
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 {
// @TODO: handle signs
if self.sign == Positive && rhs.sign == Negative {
return self - -rhs;
}
let mut out = BigInt::new_empty();
let u_digits = self.inner.len();
@ -153,16 +158,37 @@ impl Sub for BigInt {
let a = *self.inner.get(i).unwrap_or(&0usize);
let b = *rhs.inner.get(i).unwrap_or(&0usize);
if a > b {
out.inner.push(a - b - borrow);
if a == 0 && b == 0 {
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;
} else if a < b {
todo!();
} else {
todo!();
} else {
// 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
}
}
@ -368,9 +394,26 @@ mod tests {
let diff = a - b;
assert_eq!(
diff.inner[0],
diff.clone().inner[0],
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]