implement operator overloading for comparision operators
Some checks failed
timw4mail/rusty-numbers/pipeline/head There was a failure building this commit
Some checks failed
timw4mail/rusty-numbers/pipeline/head There was a failure building this commit
This commit is contained in:
parent
caeb1879c4
commit
2f8b61dab5
@ -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<T: Unsigned> Frac<T> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Unsigned + Mul<Output = T>> Mul for Frac<T> {
|
||||
impl<T: Unsigned + Add<Output = T> + Sub<Output = T> + Mul<Output = T> + Div<Output = T>> PartialOrd
|
||||
for Frac<T>
|
||||
{
|
||||
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
||||
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<T: Unsigned + Add<Output = T> + Sub<Output = T> + Mul<Output = T> + Div<Output = T>> Ord
|
||||
for Frac<T>
|
||||
{
|
||||
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<T: Unsigned + Add<Output = T> + Sub<Output = T> + Mul<Output = T> + Div<Output = T>> Mul
|
||||
for Frac<T>
|
||||
{
|
||||
type Output = Self;
|
||||
|
||||
fn mul(self, rhs: Self) -> Self {
|
||||
@ -116,13 +175,17 @@ impl<T: Unsigned + Mul<Output = T>> Mul for Frac<T> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Unsigned + Mul<Output = T>> MulAssign for Frac<T> {
|
||||
impl<T: Unsigned + Add<Output = T> + Sub<Output = T> + Mul<Output = T> + Div<Output = T>> MulAssign
|
||||
for Frac<T>
|
||||
{
|
||||
fn mul_assign(&mut self, rhs: Self) {
|
||||
*self = self.clone() * rhs
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Unsigned + Mul<Output = T>> Div for Frac<T> {
|
||||
impl<T: Unsigned + Add<Output = T> + Sub<Output = T> + Mul<Output = T> + Div<Output = T>> Div
|
||||
for Frac<T>
|
||||
{
|
||||
type Output = Self;
|
||||
|
||||
fn div(self, rhs: Self) -> Self {
|
||||
@ -134,13 +197,17 @@ impl<T: Unsigned + Mul<Output = T>> Div for Frac<T> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Unsigned + Mul<Output = T>> DivAssign for Frac<T> {
|
||||
impl<T: Unsigned + Add<Output = T> + Sub<Output = T> + Mul<Output = T> + Div<Output = T>> DivAssign
|
||||
for Frac<T>
|
||||
{
|
||||
fn div_assign(&mut self, rhs: Self) {
|
||||
*self = self.clone() / rhs
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Unsigned + Add<Output = T> + Sub<Output = T> + Mul<Output = T>> Add for Frac<T> {
|
||||
impl<T: Unsigned + Add<Output = T> + Sub<Output = T> + Mul<Output = T> + Div<Output = T>> Add
|
||||
for Frac<T>
|
||||
{
|
||||
type Output = Self;
|
||||
|
||||
fn add(self, rhs: Self) -> Self::Output {
|
||||
@ -150,9 +217,9 @@ impl<T: Unsigned + Add<Output = T> + Sub<Output = T> + Mul<Output = T>> 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<T: Unsigned + Add<Output = T> + Sub<Output = T> + Mul<Output = T>> Add for
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Unsigned + Add<Output = T> + Sub<Output = T> + Mul<Output = T>> AddAssign for Frac<T> {
|
||||
impl<T: Unsigned + Add<Output = T> + Sub<Output = T> + Mul<Output = T> + Div<Output = T>> AddAssign
|
||||
for Frac<T>
|
||||
{
|
||||
fn add_assign(&mut self, rhs: Self) {
|
||||
*self = self.clone() + rhs
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Unsigned + Sub<Output = T> + Mul<Output = T>> Sub for Frac<T> {
|
||||
impl<T: Unsigned + Add<Output = T> + Sub<Output = T> + Mul<Output = T> + Div<Output = T>> Sub
|
||||
for Frac<T>
|
||||
{
|
||||
type Output = Self;
|
||||
|
||||
fn sub(self, rhs: Self) -> Self::Output {
|
||||
// Set the larger argument as `a`
|
||||
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<T: Unsigned + Sub<Output = T> + Mul<Output = T>> Sub for Frac<T> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Unsigned + Sub<Output = T> + Mul<Output = T>> SubAssign for Frac<T> {
|
||||
impl<T: Unsigned + Add<Output = T> + Sub<Output = T> + Mul<Output = T> + Div<Output = T>> SubAssign
|
||||
for Frac<T>
|
||||
{
|
||||
fn sub_assign(&mut self, rhs: Self) {
|
||||
*self = self.clone() - rhs
|
||||
}
|
||||
@ -248,7 +322,7 @@ mod tests {
|
||||
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!(2 / 3) - frac!(1 / 3), "-2/3 - 1/3");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
Loading…
Reference in New Issue
Block a user