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
102
src/rational.rs
102
src/rational.rs
@ -1,6 +1,7 @@
|
|||||||
//! # Rational Numbers (fractions)
|
//! # Rational Numbers (fractions)
|
||||||
|
|
||||||
use crate::num::*;
|
use crate::num::*;
|
||||||
|
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};
|
||||||
|
|
||||||
/// Type representing a fraction
|
/// 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;
|
type Output = Self;
|
||||||
|
|
||||||
fn mul(self, rhs: Self) -> 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) {
|
fn mul_assign(&mut self, rhs: Self) {
|
||||||
*self = self.clone() * rhs
|
*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;
|
type Output = Self;
|
||||||
|
|
||||||
fn div(self, rhs: Self) -> 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) {
|
fn div_assign(&mut self, rhs: Self) {
|
||||||
*self = self.clone() / rhs
|
*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;
|
type Output = Self;
|
||||||
|
|
||||||
fn add(self, rhs: Self) -> Self::Output {
|
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,
|
// If the sign of one input differs,
|
||||||
// subtraction is equivalent
|
// subtraction is equivalent
|
||||||
if self.sign != rhs.sign {
|
if self.sign != rhs.sign {
|
||||||
if a.numer > b.numer {
|
if a > b {
|
||||||
return a - b;
|
return a - b;
|
||||||
} else if a.numer < b.numer {
|
} else if a < b {
|
||||||
return b - a;
|
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) {
|
fn add_assign(&mut self, rhs: Self) {
|
||||||
*self = self.clone() + rhs
|
*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;
|
type Output = Self;
|
||||||
|
|
||||||
fn sub(self, rhs: Self) -> Self::Output {
|
fn sub(self, rhs: Self) -> Self::Output {
|
||||||
// Set the larger argument as `a`
|
let a = self;
|
||||||
let a = self;
|
|
||||||
let b = rhs;
|
let b = rhs;
|
||||||
|
|
||||||
|
// @TODO handle sign "overflow" conditions
|
||||||
|
|
||||||
if a.denom != b.denom {
|
if a.denom != b.denom {
|
||||||
let numer = (a.numer * b.denom) - (b.numer * a.denom);
|
let numer = (a.numer * b.denom) - (b.numer * a.denom);
|
||||||
let denom = a.denom * b.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) {
|
fn sub_assign(&mut self, rhs: Self) {
|
||||||
*self = self.clone() - rhs
|
*self = self.clone() - rhs
|
||||||
}
|
}
|
||||||
@ -247,8 +321,8 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn sub_test() {
|
fn sub_test() {
|
||||||
assert_eq!(frac!(1 / 6), frac!(1 / 2) - frac!(1 / 3));
|
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), 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]
|
#[test]
|
||||||
|
Loading…
Reference in New Issue
Block a user