diff --git a/src/rational.rs b/src/rational.rs index 1bb1bb8..3b38c0e 100644 --- a/src/rational.rs +++ b/src/rational.rs @@ -1,6 +1,7 @@ //! # Rational Numbers (fractions) use crate::num::*; +use std::cmp::{Ord, Ordering, PartialOrd}; use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign}; /// Type representing a fraction @@ -104,7 +105,65 @@ impl Frac { } } -impl> Mul for Frac { +impl + Sub + Mul + Div> PartialOrd + for Frac +{ + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } + + fn lt(&self, other: &Self) -> bool { + self.cmp(other) == Ordering::Less + } + + fn le(&self, other: &Self) -> bool { + self == other || self.cmp(other) == Ordering::Less + } + + fn gt(&self, other: &Self) -> bool { + self.cmp(other) == Ordering::Greater + } + + fn ge(&self, other: &Self) -> bool { + self == other || self.cmp(other) == Ordering::Greater + } +} + +impl + Sub + Mul + Div> Ord + for Frac +{ + fn cmp(&self, other: &Self) -> Ordering { + if self.sign == other.sign { + if self.denom == other.denom { + return self.numer.cmp(&other.numer); + } else { + let gcd = T::gcd(self.denom, other.denom); + let x = gcd / self.denom; + let y = gcd / self.denom; + let mut a = self.clone(); + let mut b = other.clone(); + + a.numer *= x; + a.denom *= x; + + b.numer *= y; + b.denom *= y; + + a.numer.cmp(&b.numer) + } + } else { + if self.sign == Sign::Positive { + return Ordering::Greater; + } else { + return Ordering::Less; + } + } + } +} + +impl + Sub + Mul + Div> Mul + for Frac +{ type Output = Self; fn mul(self, rhs: Self) -> Self { @@ -116,13 +175,17 @@ impl> Mul for Frac { } } -impl> MulAssign for Frac { +impl + Sub + Mul + Div> MulAssign + for Frac +{ fn mul_assign(&mut self, rhs: Self) { *self = self.clone() * rhs } } -impl> Div for Frac { +impl + Sub + Mul + Div> Div + for Frac +{ type Output = Self; fn div(self, rhs: Self) -> Self { @@ -134,13 +197,17 @@ impl> Div for Frac { } } -impl> DivAssign for Frac { +impl + Sub + Mul + Div> DivAssign + for Frac +{ fn div_assign(&mut self, rhs: Self) { *self = self.clone() / rhs } } -impl + Sub + Mul> Add for Frac { +impl + Sub + Mul + Div> Add + for Frac +{ type Output = Self; fn add(self, rhs: Self) -> Self::Output { @@ -150,9 +217,9 @@ impl + Sub + Mul> Add for // If the sign of one input differs, // subtraction is equivalent if self.sign != rhs.sign { - if a.numer > b.numer { + if a > b { return a - b; - } else if a.numer < b.numer { + } else if a < b { return b - a; } } @@ -176,20 +243,25 @@ impl + Sub + Mul> Add for } } -impl + Sub + Mul> AddAssign for Frac { +impl + Sub + Mul + Div> AddAssign + for Frac +{ fn add_assign(&mut self, rhs: Self) { *self = self.clone() + rhs } } -impl + Mul> Sub for Frac { +impl + Sub + Mul + Div> Sub + for Frac +{ type Output = Self; fn sub(self, rhs: Self) -> Self::Output { - // Set the larger argument as `a` - let a = self; + let a = self; let b = rhs; + // @TODO handle sign "overflow" conditions + if a.denom != b.denom { let numer = (a.numer * b.denom) - (b.numer * a.denom); let denom = a.denom * b.denom; @@ -206,7 +278,9 @@ impl + Mul> Sub for Frac { } } -impl + Mul> SubAssign for Frac { +impl + Sub + Mul + Div> SubAssign + for Frac +{ fn sub_assign(&mut self, rhs: Self) { *self = self.clone() - rhs } @@ -247,8 +321,8 @@ mod tests { #[test] fn sub_test() { assert_eq!(frac!(1 / 6), frac!(1 / 2) - frac!(1 / 3)); - // assert_eq!(frac!(1), frac!(1/3) - -frac!(2/3), "1/3 - -2/3"); - // assert_eq!(-frac!(1 / 1), -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!(2 / 3) - frac!(1 / 3), "-2/3 - 1/3"); } #[test]