Addition and subtraction.
This commit is contained in:
@@ -405,6 +405,115 @@ derive_signed_shift_operators!(UCN, u32, i32);
|
||||
derive_signed_shift_operators!(UCN, u16, i16);
|
||||
derive_signed_shift_operators!(UCN, u8, i8);
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//
|
||||
// Addition and Subtraction
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
impl<'a> AddAssign<&'a UCN> for UCN {
|
||||
fn add_assign(&mut self, rhs: &UCN) {
|
||||
let mut iter_tm = rhs.contents.iter();
|
||||
let mut stolen = None;
|
||||
let mut carry = 0;
|
||||
|
||||
// loop through every element on the left hand side, breaking early
|
||||
// on if we right the end of the left hand side.
|
||||
{
|
||||
let mut iter_me = self.contents.iter_mut();
|
||||
loop {
|
||||
match(iter_me.next(), iter_tm.next()) {
|
||||
(None, None) =>
|
||||
break,
|
||||
(Some(dest), None) => {
|
||||
let dest128 = *dest as u128;
|
||||
let newdest = dest128 + carry;
|
||||
*dest = newdest as u64;
|
||||
carry = newdest >> 64;
|
||||
}
|
||||
(None, Some(x)) => {
|
||||
stolen = Some(*x);
|
||||
break;
|
||||
}
|
||||
(Some(dest), Some(r)) => {
|
||||
let newdest = (*dest as u128) + (*r as u128) + carry;
|
||||
*dest = newdest as u64;
|
||||
carry = newdest >> 64;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// if we accidentally stole something form the right iterator,
|
||||
// push it back on.
|
||||
if let Some(x) = stolen {
|
||||
let stolen128 = (x as u128) + carry;
|
||||
self.contents.push(stolen128 as u64);
|
||||
carry = stolen128 >> 64;
|
||||
}
|
||||
// now loop through any remaining items on the right hand side,
|
||||
// pushing them onto the result.
|
||||
for x in iter_tm {
|
||||
let x128 = (*x as u128) + carry;
|
||||
self.contents.push(x128 as u64);
|
||||
carry = x128 >> 64;
|
||||
}
|
||||
// finally, if there's still a carry, push it on the end.
|
||||
if carry > 0 {
|
||||
self.contents.push(carry as u64);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> SubAssign<&'a UCN> for UCN {
|
||||
fn sub_assign(&mut self, rhs: &UCN) {
|
||||
{
|
||||
let mut borrow = 0;
|
||||
let mut iter_me = self.contents.iter_mut();
|
||||
let mut iter_tm = rhs.contents.iter();
|
||||
|
||||
loop {
|
||||
assert!( (borrow == 0) | (borrow == 1) );
|
||||
match (iter_me.next(), iter_tm.next()) {
|
||||
(None, None) if borrow == 0 =>
|
||||
break,
|
||||
(None, None) =>
|
||||
panic!("Generated negative UCN in subtraction (1)."),
|
||||
(Some(x), None) => {
|
||||
if borrow == 0 {
|
||||
break;
|
||||
}
|
||||
if *x == 0 {
|
||||
*x = 0xFFFFFFFFFFFFFFFF;
|
||||
borrow = 1;
|
||||
} else {
|
||||
*x = *x - borrow;
|
||||
break;
|
||||
}
|
||||
}
|
||||
(None, Some(_)) => {
|
||||
panic!("Generated negative UCN in subtraction (2).");
|
||||
}
|
||||
(Some(x), Some(y)) => {
|
||||
if (*x - borrow) >= *y {
|
||||
*x = (*x - borrow) - *y;
|
||||
borrow = 0;
|
||||
} else {
|
||||
let x128 = (*x as u128) + 0x10000000000000000;
|
||||
let res = x128 - (*y as u128);
|
||||
*x = res as u64;
|
||||
borrow = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
self.clean();
|
||||
}
|
||||
}
|
||||
|
||||
derive_arithmetic_operators!(UCN, Add, add, AddAssign, add_assign);
|
||||
derive_arithmetic_operators!(UCN, Sub, sub, SubAssign, sub_assign);
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//
|
||||
// Tests!
|
||||
@@ -544,6 +653,9 @@ mod test {
|
||||
fn and_associative(a: UCN, b: UCN, c: UCN) -> bool {
|
||||
((&a & &b) & &c) == (&a & (&b & &c))
|
||||
}
|
||||
fn add_associative(a: UCN, b: UCN, c: UCN) -> bool {
|
||||
((&a + &b) + &c) == (&a + (&b + &c))
|
||||
}
|
||||
}
|
||||
|
||||
quickcheck! {
|
||||
@@ -556,6 +668,11 @@ mod test {
|
||||
fn and_commutative(a: UCN, b: UCN) -> bool {
|
||||
(&a & &b) == (&b & &a)
|
||||
}
|
||||
fn add_commutative(a: UCN, b: UCN) -> bool {
|
||||
let ab = &a + &b;
|
||||
let ba = &b + &a;
|
||||
(ab == ba)
|
||||
}
|
||||
}
|
||||
|
||||
quickcheck! {
|
||||
@@ -577,6 +694,12 @@ mod test {
|
||||
fn shr_identity(a: UCN) -> bool {
|
||||
(&a << 0) == a
|
||||
}
|
||||
fn add_identity(a: UCN) -> bool {
|
||||
(&a + &UCN{ contents: vec![] }) == a
|
||||
}
|
||||
fn sub_identity(a: UCN) -> bool {
|
||||
(&a - &UCN{ contents: vec![] }) == a
|
||||
}
|
||||
}
|
||||
|
||||
quickcheck! {
|
||||
@@ -595,6 +718,9 @@ mod test {
|
||||
let right = &left >> b;
|
||||
right == a
|
||||
}
|
||||
fn sub_annihilation(a: UCN) -> bool {
|
||||
(&a - &a) == UCN{ contents: vec![] }
|
||||
}
|
||||
fn xor_inverse(a: UCN, b: UCN) -> bool {
|
||||
((&a ^ &b) ^ &b) == a
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user