Fix another negative fraction condition
timw4mail/rusty-numbers/pipeline/head This commit looks good Details

This commit is contained in:
Timothy Warren 2020-02-19 15:07:40 -05:00
parent 84656e74c9
commit 44467df38f
1 changed files with 16 additions and 24 deletions

View File

@ -1,7 +1,7 @@
//! # Rational Numbers (fractions) //! # Rational Numbers (fractions)
use crate::num::*;
use crate::num::Sign::*; use crate::num::Sign::*;
use crate::num::*;
use std::cmp::{Ord, Ordering, PartialOrd}; use std::cmp::{Ord, Ordering, PartialOrd};
use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign}; use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign};
@ -77,11 +77,7 @@ impl<T: Unsigned> Frac<T> {
let numer = n.to_unsigned(); let numer = n.to_unsigned();
let denom = d.to_unsigned(); let denom = d.to_unsigned();
Frac { Frac { numer, denom, sign }
numer,
denom,
sign,
}
} }
/// Create a new rational from all the raw parts /// Create a new rational from all the raw parts
@ -94,12 +90,13 @@ impl<T: Unsigned> Frac<T> {
numer: n, numer: n,
denom: d, denom: d,
sign: s, sign: s,
}.reduce() }
.reduce()
} }
/// Determine the output sign given the two input signs /// Determine the output sign given the two input signs
fn get_sign(a: Self, b: Self, c: FracOp) -> Sign { fn get_sign(a: Self, b: Self, op: FracOp) -> Sign {
if c == FracOp::Addition { if op == FracOp::Addition {
return if a.sign == Positive && b.sign == Positive { return if a.sign == Positive && b.sign == Positive {
Positive Positive
} else { } else {
@ -108,7 +105,7 @@ impl<T: Unsigned> Frac<T> {
} }
if a.sign != b.sign { if a.sign != b.sign {
if c == FracOp::Subtraction && b.sign == Negative { if op == FracOp::Subtraction && b.sign == Negative {
Positive Positive
} else { } else {
Negative Negative
@ -288,30 +285,25 @@ where
if a.sign == Positive && b.sign == Negative { if a.sign == Positive && b.sign == Negative {
return a + -b; return a + -b;
} else if a.sign == Negative && b.sign == Positive { } else if a.sign == Negative && b.sign == Positive {
return b + -a; return -(b + -a);
} }
if a.denom != b.denom { if a.denom != b.denom {
let (numer, overflowed) = (a.numer * b.denom).left_overflowing_sub(b.numer * a.denom); let (numer, overflowed) = (a.numer * b.denom).left_overflowing_sub(b.numer * a.denom);
let denom = a.denom * b.denom; let denom = a.denom * b.denom;
let mut sign = Self::get_sign(a, b, FracOp::Subtraction); let sign = Self::get_sign(a, b, FracOp::Subtraction);
if overflowed { let res = Self::raw(numer, denom, sign);
sign = !sign return if overflowed { -res } else { res };
}
return Self::raw(numer, denom, sign);
} }
let (numer, overflowed) = a.numer.left_overflowing_sub(b.numer); let (numer, overflowed) = a.numer.left_overflowing_sub(b.numer);
let denom = a.denom; let denom = a.denom;
let mut sign = Self::get_sign(a, b, FracOp::Subtraction); let sign = Self::get_sign(a, b, FracOp::Subtraction);
if overflowed { let res = Self::raw(numer, denom, sign);
sign = !sign
}
Self::raw(numer, denom, sign) if overflowed { -res } else { res }
} }
} }
@ -374,8 +366,8 @@ mod tests {
fn negative_fractions() { fn negative_fractions() {
assert_eq!(-frac!(1 / 3), -frac!(2 / 3) + frac!(1 / 3), "-2/3 + 1/3"); assert_eq!(-frac!(1 / 3), -frac!(2 / 3) + frac!(1 / 3), "-2/3 + 1/3");
assert_eq!(frac!(1), frac!(1 / 3) - -frac!(2 / 3), "1/3 - -2/3"); assert_eq!(frac!(1), frac!(1 / 3) - -frac!(2 / 3), "1/3 - -2/3");
// assert_eq!(-frac!(1), -frac!(2 / 3) - frac!(1 / 3), "-2/3 - +1/3"); assert_eq!(-frac!(1), -frac!(2 / 3) - frac!(1 / 3), "-2/3 - +1/3");
assert_eq!(-frac!(1), -frac!(2 / 3) + -frac!(1/3), "-2/3 + -1/3"); assert_eq!(-frac!(1), -frac!(2 / 3) + -frac!(1 / 3), "-2/3 + -1/3");
} }
#[test] #[test]