From 063f6ffa48647f2fdf4e503f32bcf1024fcd58f2 Mon Sep 17 00:00:00 2001 From: Timothy Warren Date: Tue, 24 Mar 2020 13:26:00 -0400 Subject: [PATCH] Implement sign handling for addition and subtraction --- src/bigint.rs | 38 +++++++++++++++++++++++++++++++++++--- src/num.rs | 8 ++++++++ src/rational.rs | 7 ------- 3 files changed, 43 insertions(+), 10 deletions(-) diff --git a/src/bigint.rs b/src/bigint.rs index 1245fcb..e496912 100644 --- a/src/bigint.rs +++ b/src/bigint.rs @@ -123,14 +123,36 @@ impl BigInt { a_digits } } + + /// Determine the output sign given the two input signs and operation + fn get_sign(a: Self, b: Self, op: FracOp) -> Sign { + // -a + -b = -c + if op == FracOp::Addition && a.sign == Negative && b.sign == Negative { + return Negative; + } + + // a - -b = c + if op == FracOp::Subtraction && a.sign == Positive && b.sign == Negative { + return Positive; + } + + if a.sign != b.sign { + Negative + } else { + Positive + } + } } impl Add for BigInt { type Output = Self; - // @TODO: handle signs fn add(self, rhs: Self) -> Self::Output { - if self.sign == Positive && rhs.sign == Negative { + // If the sign of one input differs, + // subtraction is equivalent + if self.sign == Negative && rhs.sign == Positive { + return rhs - -self; + } else if self.sign == Positive && rhs.sign == Negative { return self - -rhs; } @@ -161,6 +183,8 @@ impl Add for BigInt { } } + out.sign = Self::get_sign(self, rhs, FracOp::Addition); + out.trim_zeros(); out @@ -170,11 +194,17 @@ impl Add for BigInt { impl Sub for BigInt { type Output = Self; - // @TODO: handle signs fn sub(self, rhs: Self) -> Self::Output { let digits = Self::get_digit_count(&self, &rhs); let mut out = BigInt::with_capacity(digits); + // Handle cases where addition makes more sense + if self.sign == Positive && rhs.sign == Negative { + return self + -rhs; + } else if self.sign == Negative && rhs.sign == Positive { + return -(rhs + -self); + } + let mut borrow = 0usize; for i in 0..digits { let a = *self.inner.get(i).unwrap_or(&0usize); @@ -199,6 +229,8 @@ impl Sub for BigInt { } } + out.sign = Self::get_sign(self, rhs, FracOp::Subtraction); + out.trim_zeros(); out diff --git a/src/num.rs b/src/num.rs index ff3aeab..20e2d8d 100644 --- a/src/num.rs +++ b/src/num.rs @@ -21,6 +21,14 @@ pub enum Sign { Negative, } +/// The type of mathematical operation +#[derive(Debug, Copy, Clone, PartialEq)] +pub enum FracOp { + Addition, + Subtraction, + Other, +} + impl Default for Sign { fn default() -> Self { Sign::Positive diff --git a/src/rational.rs b/src/rational.rs index ca9bcaa..562ecf1 100644 --- a/src/rational.rs +++ b/src/rational.rs @@ -61,13 +61,6 @@ macro_rules! frac { }; } -#[derive(Debug, Copy, Clone, PartialEq)] -enum FracOp { - Addition, - Subtraction, - Other, -} - impl Frac { /// Create a new rational number from signed or unsigned arguments ///