Add borrowing for subtraction
All checks were successful
timw4mail/rusty-numbers/pipeline/head This commit looks good
All checks were successful
timw4mail/rusty-numbers/pipeline/head This commit looks good
This commit is contained in:
parent
ae77ede1c0
commit
a8de0cfa88
@ -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]
|
||||
|
Loading…
Reference in New Issue
Block a user