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)]
|
#![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]
|
||||||
|
Loading…
Reference in New Issue
Block a user