[types] Make math ops macros even more generic -- implement them for cross types too!
Still need to write tests for this though.
This commit is contained in:
parent
9d40cdd995
commit
c07e6aa99b
5 changed files with 33 additions and 18 deletions
|
@ -3,7 +3,7 @@
|
|||
*/
|
||||
|
||||
use std::ops::{Add, Div, Mul, Sub, Rem};
|
||||
use number::{Int, Irr};
|
||||
use number::{Int, Irr, Number};
|
||||
|
||||
pub trait GCD {
|
||||
/// Find the greatest common divisor of `self` and another number.
|
||||
|
@ -17,24 +17,19 @@ pub trait LCM {
|
|||
|
||||
macro_rules! impl_newtype_arith_op {
|
||||
($id:ident, $opt:ident, $opm:ident, $op:tt) => {
|
||||
impl $opt for $id {
|
||||
impl<T> $opt<T> for $id where T: Number + Into<$id> {
|
||||
type Output = $id;
|
||||
#[inline]
|
||||
fn $opm(self, rhs: $id) -> Self::Output {
|
||||
fn $opm(self, rhs: T) -> Self::Output {
|
||||
let rhs: $id = rhs.into();
|
||||
$id(self.0 $op rhs.0)
|
||||
}
|
||||
}
|
||||
impl<'a> $opt<$id> for &'a $id {
|
||||
impl<'a, T> $opt<T> for &'a $id where T: Number + Into<$id> {
|
||||
type Output = $id;
|
||||
#[inline]
|
||||
fn $opm(self, rhs: $id) -> Self::Output {
|
||||
$id(self.0 $op rhs.0)
|
||||
}
|
||||
}
|
||||
impl<'a, 'b> $opt<&'a $id> for &'b $id {
|
||||
type Output = $id;
|
||||
#[inline]
|
||||
fn $opm(self, rhs: &$id) -> Self::Output {
|
||||
fn $opm(self, rhs: T) -> Self::Output {
|
||||
let rhs: $id = rhs.into();
|
||||
$id(self.0 $op rhs.0)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,6 +32,10 @@ impl Frac {
|
|||
Frac::new(Int(p), Int(q))
|
||||
}
|
||||
|
||||
pub fn quotient(&self) -> f64 {
|
||||
self.p.0 as f64 / self.q.0 as f64
|
||||
}
|
||||
|
||||
fn reduced(self) -> Frac {
|
||||
let gcd = self.p.gcd(self.q);
|
||||
Frac { p: self.p / gcd, q: self.q / gcd }
|
||||
|
@ -77,6 +81,12 @@ impl fmt::Display for Frac {
|
|||
}
|
||||
}
|
||||
|
||||
impl From<Int> for Frac {
|
||||
fn from(i: Int) -> Frac {
|
||||
Frac{p: i, q: Int(1)}
|
||||
}
|
||||
}
|
||||
|
||||
impl Mul for Frac {
|
||||
type Output = Frac;
|
||||
fn mul(self, rhs: Self) -> Self::Output {
|
||||
|
|
|
@ -5,8 +5,8 @@
|
|||
use std::any::Any;
|
||||
use std::fmt;
|
||||
use number::arith::{GCD, LCM};
|
||||
use number::{Frac, Number};
|
||||
use object::{Obj, Object};
|
||||
use super::{Frac, Number};
|
||||
|
||||
#[derive(Copy, Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]
|
||||
pub struct Int(pub i64);
|
||||
|
|
|
@ -20,9 +20,14 @@ impl fmt::Display for Irr {
|
|||
}
|
||||
}
|
||||
|
||||
impl Object for Irr {
|
||||
fn as_any(&self) -> &Any { self }
|
||||
fn as_num(&self) -> Option<&Number> { Some(self) }
|
||||
impl From<Int> for Irr {
|
||||
fn from(i: Int) -> Irr { Irr(i.0 as f64) }
|
||||
}
|
||||
|
||||
impl From<Frac> for Irr {
|
||||
fn from(f: Frac) -> Irr {
|
||||
Irr(f.quotient())
|
||||
}
|
||||
}
|
||||
|
||||
impl Number for Irr {
|
||||
|
@ -46,6 +51,11 @@ impl Number for Irr {
|
|||
fn is_zero(&self) -> bool { self.0 == 0.0 }
|
||||
}
|
||||
|
||||
impl Object for Irr {
|
||||
fn as_any(&self) -> &Any { self }
|
||||
fn as_num(&self) -> Option<&Number> { Some(self) }
|
||||
}
|
||||
|
||||
impl PartialEq<Obj> for Irr {
|
||||
fn eq<'a>(&self, rhs: &'a Obj) -> bool {
|
||||
match rhs.obj().and_then(Object::as_num) {
|
||||
|
|
|
@ -11,13 +11,13 @@
|
|||
//! Integer can be cast as a Rational (by putting its value over 1), but a Rational like 1/2 cannot
|
||||
//! be represented as an Integer.
|
||||
|
||||
use object::Object;
|
||||
|
||||
mod arith;
|
||||
mod frac;
|
||||
mod integer;
|
||||
mod irr;
|
||||
|
||||
use object::Object;
|
||||
|
||||
pub use self::frac::Frac;
|
||||
pub use self::integer::Int;
|
||||
pub use self::irr::Irr;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue