From c84c4d15ba3f0a5f1a7ff8b2bcd58e3b74e03661 Mon Sep 17 00:00:00 2001 From: Michael Lamparski Date: Thu, 21 Jul 2016 20:52:45 -0400 Subject: [PATCH 1/3] Improve Ratio docs Closes #208. Clarifies the rounding behavior of some methods and makes formatting more uniform. --- rational/src/lib.rs | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/rational/src/lib.rs b/rational/src/lib.rs index 47bb0b0..db758bf 100644 --- a/rational/src/lib.rs +++ b/rational/src/lib.rs @@ -56,13 +56,13 @@ pub type Rational64 = Ratio; pub type BigRational = Ratio; impl Ratio { - /// Creates a ratio representing the integer `t`. + /// Creates a `Ratio` representing the integer `t`. #[inline] pub fn from_integer(t: T) -> Ratio { Ratio::new_raw(t, One::one()) } - /// Creates a ratio without checking for `denom == 0` or reducing. + /// Creates a `Ratio` without checking for `denom == 0` or reducing. #[inline] pub fn new_raw(numer: T, denom: T) -> Ratio { Ratio { @@ -71,7 +71,7 @@ impl Ratio { } } - /// Create a new Ratio. Fails if `denom == 0`. + /// Creates a new `Ratio`. Fails if `denom == 0`. #[inline] pub fn new(numer: T, denom: T) -> Ratio { if denom == Zero::zero() { @@ -82,7 +82,7 @@ impl Ratio { ret } - /// Converts to an integer. + /// Converts to an integer, rounding towards zero. #[inline] pub fn to_integer(&self) -> T { self.trunc().numer @@ -106,7 +106,7 @@ impl Ratio { self.denom == One::one() } - /// Put self into lowest terms, with denom > 0. + /// Puts self into lowest terms, with denom > 0. fn reduce(&mut self) { let g: T = self.numer.gcd(&self.denom); @@ -124,7 +124,10 @@ impl Ratio { } } - /// Returns a `reduce`d copy of self. + /// Returns a reduced copy of self. + /// + /// In general, it is not necessary to use this method, as the only + /// method of procuring a non-reduced fraction is through `new_raw`. pub fn reduced(&self) -> Ratio { let mut ret = self.clone(); ret.reduce(); @@ -201,7 +204,9 @@ impl Ratio { Ratio::from_integer(self.numer.clone() / self.denom.clone()) } - /// Returns the fractional part of a number. + /// Returns the fractional part of a number, with division rounded towards zero. + /// + /// Satisfies `self == self.trunc() + self.fract()`. #[inline] pub fn fract(&self) -> Ratio { Ratio::new_raw(self.numer.clone() % self.denom.clone(), self.denom.clone()) @@ -209,7 +214,7 @@ impl Ratio { } impl Ratio { - /// Raises the ratio to the power of an exponent + /// Raises the `Ratio` to the power of an exponent. #[inline] pub fn pow(&self, expon: i32) -> Ratio { match expon.cmp(&0) { From 8c75506f2275c215d45dcccf52340da8717c6fa5 Mon Sep 17 00:00:00 2001 From: Michael Lamparski Date: Thu, 21 Jul 2016 21:35:10 -0400 Subject: [PATCH 2/3] Ratio::recip now corrects sign and fails for zero --- rational/src/lib.rs | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/rational/src/lib.rs b/rational/src/lib.rs index db758bf..ec2ee15 100644 --- a/rational/src/lib.rs +++ b/rational/src/lib.rs @@ -135,9 +135,16 @@ impl Ratio { } /// Returns the reciprocal. + /// + /// Fails if the `Ratio` is zero. #[inline] pub fn recip(&self) -> Ratio { - Ratio::new_raw(self.denom.clone(), self.numer.clone()) + match self.numer.cmp(&T::zero()) { + cmp::Ordering::Equal => panic!("numerator == 0"), + cmp::Ordering::Greater => Ratio::new_raw(self.denom.clone(), self.numer.clone()), + cmp::Ordering::Less => Ratio::new_raw(T::zero() - self.denom.clone(), + T::zero() - self.numer.clone()) + } } /// Rounds towards minus infinity. @@ -669,6 +676,10 @@ mod test { numer: 2, denom: 1, }; + pub const _NEG2: Rational = Ratio { + numer: -2, + denom: 1, + }; pub const _1_2: Rational = Ratio { numer: 1, denom: 2, @@ -1007,6 +1018,16 @@ mod test { assert_eq!(_1_2 * _1_2.recip(), _1); assert_eq!(_3_2 * _3_2.recip(), _1); assert_eq!(_NEG1_2 * _NEG1_2.recip(), _1); + + assert_eq!(_3_2.recip(), _2_3); + assert_eq!(_NEG1_2.recip(), _NEG2); + assert_eq!(_NEG1_2.recip().denom(), &1); + } + + #[test] + #[should_panic = "== 0"] + fn test_recip_fail() { + let _a = Ratio::new(0, 1).recip(); } #[test] From 32dee9a0c8259ee3846a644b3925bf981e261ada Mon Sep 17 00:00:00 2001 From: Michael Lamparski Date: Sun, 24 Jul 2016 14:58:43 -0400 Subject: [PATCH 3/3] rational: small additional tweaks Move `new` to top to make it more visible in the docs. Replace instances of $x == Zero::zero()$ with $x.is_zero()$, partially addressing #11. --- rational/src/lib.rs | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/rational/src/lib.rs b/rational/src/lib.rs index ec2ee15..7aa036f 100644 --- a/rational/src/lib.rs +++ b/rational/src/lib.rs @@ -56,6 +56,17 @@ pub type Rational64 = Ratio; pub type BigRational = Ratio; impl Ratio { + /// Creates a new `Ratio`. Fails if `denom` is zero. + #[inline] + pub fn new(numer: T, denom: T) -> Ratio { + if denom.is_zero() { + panic!("denominator == 0"); + } + let mut ret = Ratio::new_raw(numer, denom); + ret.reduce(); + ret + } + /// Creates a `Ratio` representing the integer `t`. #[inline] pub fn from_integer(t: T) -> Ratio { @@ -71,17 +82,6 @@ impl Ratio { } } - /// Creates a new `Ratio`. Fails if `denom == 0`. - #[inline] - pub fn new(numer: T, denom: T) -> Ratio { - if denom == Zero::zero() { - panic!("denominator == 0"); - } - let mut ret = Ratio::new_raw(numer, denom); - ret.reduce(); - ret - } - /// Converts to an integer, rounding towards zero. #[inline] pub fn to_integer(&self) -> T { @@ -605,7 +605,7 @@ impl serde::Deserialize for Ratio where D: serde::Deserializer { let (numer, denom) = try!(serde::Deserialize::deserialize(deserializer)); - if denom == Zero::zero() { + if denom.is_zero() { Err(serde::de::Error::invalid_value("denominator is zero")) } else { Ok(Ratio::new_raw(numer, denom))