From c07e6aa99b4f69d43a87b2d6d733baffd4b9df28 Mon Sep 17 00:00:00 2001 From: Eryn Wells Date: Thu, 13 Sep 2018 18:08:14 -0700 Subject: [PATCH] [types] Make math ops macros even more generic -- implement them for cross types too! Still need to write tests for this though. --- types/src/number/arith.rs | 19 +++++++------------ types/src/number/frac.rs | 10 ++++++++++ types/src/number/integer.rs | 2 +- types/src/number/irr.rs | 16 +++++++++++++--- types/src/number/mod.rs | 4 ++-- 5 files changed, 33 insertions(+), 18 deletions(-) diff --git a/types/src/number/arith.rs b/types/src/number/arith.rs index 546901f..f33a6c6 100644 --- a/types/src/number/arith.rs +++ b/types/src/number/arith.rs @@ -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 $opt 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 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) } } diff --git a/types/src/number/frac.rs b/types/src/number/frac.rs index 068c4f6..67aa476 100644 --- a/types/src/number/frac.rs +++ b/types/src/number/frac.rs @@ -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 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 { diff --git a/types/src/number/integer.rs b/types/src/number/integer.rs index 96853ad..72e1fa5 100644 --- a/types/src/number/integer.rs +++ b/types/src/number/integer.rs @@ -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); diff --git a/types/src/number/irr.rs b/types/src/number/irr.rs index be24df0..be19b8a 100644 --- a/types/src/number/irr.rs +++ b/types/src/number/irr.rs @@ -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 for Irr { + fn from(i: Int) -> Irr { Irr(i.0 as f64) } +} + +impl From 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 for Irr { fn eq<'a>(&self, rhs: &'a Obj) -> bool { match rhs.obj().and_then(Object::as_num) { diff --git a/types/src/number/mod.rs b/types/src/number/mod.rs index bc03b72..afacf0f 100644 --- a/types/src/number/mod.rs +++ b/types/src/number/mod.rs @@ -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;