libstd: Rational
requires Integer
as type bounds instead of Num
This commit is contained in:
parent
e3695468b7
commit
41eaa97372
@ -30,7 +30,7 @@ pub type Rational64 = Ratio<i64>;
|
|||||||
/// Alias for arbitrary precision rationals.
|
/// Alias for arbitrary precision rationals.
|
||||||
pub type BigRational = Ratio<BigInt>;
|
pub type BigRational = Ratio<BigInt>;
|
||||||
|
|
||||||
impl<T: Copy + Num + Ord>
|
impl<T: Copy + Integer + Ord>
|
||||||
Ratio<T> {
|
Ratio<T> {
|
||||||
/// Create a ratio representing the integer `t`.
|
/// Create a ratio representing the integer `t`.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
@ -57,7 +57,7 @@ impl<T: Copy + Num + Ord>
|
|||||||
|
|
||||||
/// Put self into lowest terms, with denom > 0.
|
/// Put self into lowest terms, with denom > 0.
|
||||||
fn reduce(&mut self) {
|
fn reduce(&mut self) {
|
||||||
let g : T = gcd(self.numer, self.denom);
|
let g : T = self.numer.gcd(&self.denom);
|
||||||
|
|
||||||
self.numer /= g;
|
self.numer /= g;
|
||||||
self.denom /= g;
|
self.denom /= g;
|
||||||
@ -76,34 +76,6 @@ impl<T: Copy + Num + Ord>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
Compute the greatest common divisor of two numbers, via Euclid's algorithm.
|
|
||||||
|
|
||||||
The result can be negative.
|
|
||||||
*/
|
|
||||||
#[inline]
|
|
||||||
pub fn gcd_raw<T: Num>(n: T, m: T) -> T {
|
|
||||||
let mut m = m, n = n;
|
|
||||||
while m != Zero::zero() {
|
|
||||||
let temp = m;
|
|
||||||
m = n % temp;
|
|
||||||
n = temp;
|
|
||||||
}
|
|
||||||
n
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
Compute the greatest common divisor of two numbers, via Euclid's algorithm.
|
|
||||||
|
|
||||||
The result is always positive.
|
|
||||||
*/
|
|
||||||
#[inline]
|
|
||||||
pub fn gcd<T: Num + Ord>(n: T, m: T) -> T {
|
|
||||||
let g = gcd_raw(n, m);
|
|
||||||
if g < Zero::zero() { -g }
|
|
||||||
else { g }
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Comparisons */
|
/* Comparisons */
|
||||||
|
|
||||||
// comparing a/b and c/d is the same as comparing a*d and b*c, so we
|
// comparing a/b and c/d is the same as comparing a*d and b*c, so we
|
||||||
@ -133,7 +105,7 @@ cmp_impl!(impl TotalOrd, cmp -> cmp::Ordering)
|
|||||||
|
|
||||||
/* Arithmetic */
|
/* Arithmetic */
|
||||||
// a/b * c/d = (a*c)/(b*d)
|
// a/b * c/d = (a*c)/(b*d)
|
||||||
impl<T: Copy + Num + Ord>
|
impl<T: Copy + Integer + Ord>
|
||||||
Mul<Ratio<T>,Ratio<T>> for Ratio<T> {
|
Mul<Ratio<T>,Ratio<T>> for Ratio<T> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn mul(&self, rhs: &Ratio<T>) -> Ratio<T> {
|
fn mul(&self, rhs: &Ratio<T>) -> Ratio<T> {
|
||||||
@ -142,7 +114,7 @@ impl<T: Copy + Num + Ord>
|
|||||||
}
|
}
|
||||||
|
|
||||||
// (a/b) / (c/d) = (a*d)/(b*c)
|
// (a/b) / (c/d) = (a*d)/(b*c)
|
||||||
impl<T: Copy + Num + Ord>
|
impl<T: Copy + Integer + Ord>
|
||||||
Div<Ratio<T>,Ratio<T>> for Ratio<T> {
|
Div<Ratio<T>,Ratio<T>> for Ratio<T> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn div(&self, rhs: &Ratio<T>) -> Ratio<T> {
|
fn div(&self, rhs: &Ratio<T>) -> Ratio<T> {
|
||||||
@ -153,7 +125,7 @@ impl<T: Copy + Num + Ord>
|
|||||||
// Abstracts the a/b `op` c/d = (a*d `op` b*d) / (b*d) pattern
|
// Abstracts the a/b `op` c/d = (a*d `op` b*d) / (b*d) pattern
|
||||||
macro_rules! arith_impl {
|
macro_rules! arith_impl {
|
||||||
(impl $imp:ident, $method:ident) => {
|
(impl $imp:ident, $method:ident) => {
|
||||||
impl<T: Copy + Num + Ord>
|
impl<T: Copy + Integer + Ord>
|
||||||
$imp<Ratio<T>,Ratio<T>> for Ratio<T> {
|
$imp<Ratio<T>,Ratio<T>> for Ratio<T> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn $method(&self, rhs: &Ratio<T>) -> Ratio<T> {
|
fn $method(&self, rhs: &Ratio<T>) -> Ratio<T> {
|
||||||
@ -173,16 +145,16 @@ arith_impl!(impl Sub, sub)
|
|||||||
// a/b % c/d = (a*d % b*c)/(b*d)
|
// a/b % c/d = (a*d % b*c)/(b*d)
|
||||||
arith_impl!(impl Rem, rem)
|
arith_impl!(impl Rem, rem)
|
||||||
|
|
||||||
impl<T: Copy + Num + Ord>
|
impl<T: Copy + Integer + Ord>
|
||||||
Neg<Ratio<T>> for Ratio<T> {
|
Neg<Ratio<T>> for Ratio<T> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn neg(&self) -> Ratio<T> {
|
fn neg(&self) -> Ratio<T> {
|
||||||
Ratio::new_raw(-self.numer, self.denom)
|
Ratio::new_raw(-self.numer, self.denom.clone())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Constants */
|
/* Constants */
|
||||||
impl<T: Copy + Num + Ord>
|
impl<T: Copy + Integer + Ord>
|
||||||
Zero for Ratio<T> {
|
Zero for Ratio<T> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn zero() -> Ratio<T> {
|
fn zero() -> Ratio<T> {
|
||||||
@ -195,7 +167,7 @@ impl<T: Copy + Num + Ord>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Copy + Num + Ord>
|
impl<T: Copy + Integer + Ord>
|
||||||
One for Ratio<T> {
|
One for Ratio<T> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn one() -> Ratio<T> {
|
fn one() -> Ratio<T> {
|
||||||
@ -203,11 +175,11 @@ impl<T: Copy + Num + Ord>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Copy + Num + Ord>
|
impl<T: Copy + Integer + Ord>
|
||||||
Num for Ratio<T> {}
|
Num for Ratio<T> {}
|
||||||
|
|
||||||
/* Utils */
|
/* Utils */
|
||||||
impl<T: Copy + Num + Ord>
|
impl<T: Copy + Integer + Ord>
|
||||||
Round for Ratio<T> {
|
Round for Ratio<T> {
|
||||||
|
|
||||||
fn floor(&self) -> Ratio<T> {
|
fn floor(&self) -> Ratio<T> {
|
||||||
@ -245,7 +217,7 @@ impl<T: Copy + Num + Ord>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Copy + Num + Ord> Fractional for Ratio<T> {
|
impl<T: Copy + Integer + Ord> Fractional for Ratio<T> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn recip(&self) -> Ratio<T> {
|
fn recip(&self) -> Ratio<T> {
|
||||||
Ratio::new_raw(self.denom, self.numer)
|
Ratio::new_raw(self.denom, self.numer)
|
||||||
@ -266,7 +238,7 @@ impl<T: ToStrRadix> ToStrRadix for Ratio<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: FromStr + Copy + Num + Ord>
|
impl<T: FromStr + Copy + Integer + Ord>
|
||||||
FromStr for Ratio<T> {
|
FromStr for Ratio<T> {
|
||||||
/// Parses `numer/denom`.
|
/// Parses `numer/denom`.
|
||||||
fn from_str(s: &str) -> Option<Ratio<T>> {
|
fn from_str(s: &str) -> Option<Ratio<T>> {
|
||||||
@ -283,7 +255,7 @@ impl<T: FromStr + Copy + Num + Ord>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl<T: FromStrRadix + Copy + Num + Ord>
|
impl<T: FromStrRadix + Copy + Integer + Ord>
|
||||||
FromStrRadix for Ratio<T> {
|
FromStrRadix for Ratio<T> {
|
||||||
/// Parses `numer/denom` where the numbers are in base `radix`.
|
/// Parses `numer/denom` where the numbers are in base `radix`.
|
||||||
fn from_str_radix(s: &str, radix: uint) -> Option<Ratio<T>> {
|
fn from_str_radix(s: &str, radix: uint) -> Option<Ratio<T>> {
|
||||||
@ -316,17 +288,6 @@ mod test {
|
|||||||
pub static _3_2: Rational = Ratio { numer: 3, denom: 2};
|
pub static _3_2: Rational = Ratio { numer: 3, denom: 2};
|
||||||
pub static _neg1_2: Rational = Ratio { numer: -1, denom: 2};
|
pub static _neg1_2: Rational = Ratio { numer: -1, denom: 2};
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_gcd() {
|
|
||||||
assert_eq!(gcd(10,2),2);
|
|
||||||
assert_eq!(gcd(10,3),1);
|
|
||||||
assert_eq!(gcd(0,3),3);
|
|
||||||
assert_eq!(gcd(3,3),3);
|
|
||||||
|
|
||||||
assert_eq!(gcd(3,-3), 3);
|
|
||||||
assert_eq!(gcd(-6,3), 3);
|
|
||||||
assert_eq!(gcd(-4,-2), 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_test_constants() {
|
fn test_test_constants() {
|
||||||
|
Loading…
Reference in New Issue
Block a user