[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