1 // Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10 
11 //! Rational numbers
12 //!
13 //! ## Compatibility
14 //!
15 //! The `num-rational` crate is tested for rustc 1.15 and greater.
16 
17 #![doc(html_root_url = "https://docs.rs/num-rational/0.2")]
18 
19 #![no_std]
20 
21 #[cfg(feature = "serde")]
22 extern crate serde;
23 #[cfg(feature = "bigint")]
24 extern crate num_bigint as bigint;
25 
26 extern crate num_traits as traits;
27 extern crate num_integer as integer;
28 
29 #[cfg(feature = "std")]
30 #[cfg_attr(test, macro_use)]
31 extern crate std;
32 
33 use core::cmp;
34 #[cfg(feature = "std")]
35 use std::error::Error;
36 use core::fmt;
37 use core::hash::{Hash, Hasher};
38 use core::ops::{Add, Div, Mul, Neg, Rem, Sub};
39 use core::str::FromStr;
40 
41 #[cfg(feature = "bigint")]
42 use bigint::{BigInt, BigUint, Sign};
43 
44 use integer::Integer;
45 use traits::float::FloatCore;
46 use traits::{Bounded, CheckedAdd, CheckedDiv, CheckedMul, CheckedSub, FromPrimitive, Inv, Num,
47              NumCast, One, Pow, Signed, Zero};
48 
49 /// Represents the ratio between two numbers.
50 #[derive(Copy, Clone, Debug)]
51 #[allow(missing_docs)]
52 pub struct Ratio<T> {
53     /// Numerator.
54     numer: T,
55     /// Denominator.
56     denom: T,
57 }
58 
59 /// Alias for a `Ratio` of machine-sized integers.
60 pub type Rational = Ratio<isize>;
61 /// Alias for a `Ratio` of 32-bit-sized integers.
62 pub type Rational32 = Ratio<i32>;
63 /// Alias for a `Ratio` of 64-bit-sized integers.
64 pub type Rational64 = Ratio<i64>;
65 
66 #[cfg(feature = "bigint")]
67 /// Alias for arbitrary precision rationals.
68 pub type BigRational = Ratio<BigInt>;
69 
70 impl<T: Clone + Integer> Ratio<T> {
71     /// Creates a new `Ratio`. Fails if `denom` is zero.
72     #[inline]
new(numer: T, denom: T) -> Ratio<T>73     pub fn new(numer: T, denom: T) -> Ratio<T> {
74         if denom.is_zero() {
75             panic!("denominator == 0");
76         }
77         let mut ret = Ratio::new_raw(numer, denom);
78         ret.reduce();
79         ret
80     }
81 
82     /// Creates a `Ratio` representing the integer `t`.
83     #[inline]
from_integer(t: T) -> Ratio<T>84     pub fn from_integer(t: T) -> Ratio<T> {
85         Ratio::new_raw(t, One::one())
86     }
87 
88     /// Creates a `Ratio` without checking for `denom == 0` or reducing.
89     #[inline]
new_raw(numer: T, denom: T) -> Ratio<T>90     pub fn new_raw(numer: T, denom: T) -> Ratio<T> {
91         Ratio {
92             numer: numer,
93             denom: denom,
94         }
95     }
96 
97     /// Converts to an integer, rounding towards zero.
98     #[inline]
to_integer(&self) -> T99     pub fn to_integer(&self) -> T {
100         self.trunc().numer
101     }
102 
103     /// Gets an immutable reference to the numerator.
104     #[inline]
numer<'a>(&'a self) -> &'a T105     pub fn numer<'a>(&'a self) -> &'a T {
106         &self.numer
107     }
108 
109     /// Gets an immutable reference to the denominator.
110     #[inline]
denom<'a>(&'a self) -> &'a T111     pub fn denom<'a>(&'a self) -> &'a T {
112         &self.denom
113     }
114 
115     /// Returns true if the rational number is an integer (denominator is 1).
116     #[inline]
is_integer(&self) -> bool117     pub fn is_integer(&self) -> bool {
118         self.denom.is_one()
119     }
120 
121     /// Puts self into lowest terms, with denom > 0.
reduce(&mut self)122     fn reduce(&mut self) {
123         let g: T = self.numer.gcd(&self.denom);
124 
125         // FIXME(#5992): assignment operator overloads
126         // self.numer /= g;
127         // T: Clone + Integer != T: Clone + NumAssign
128         self.numer = self.numer.clone() / g.clone();
129         // FIXME(#5992): assignment operator overloads
130         // self.denom /= g;
131         // T: Clone + Integer != T: Clone + NumAssign
132         self.denom = self.denom.clone() / g;
133 
134         // keep denom positive!
135         if self.denom < T::zero() {
136             self.numer = T::zero() - self.numer.clone();
137             self.denom = T::zero() - self.denom.clone();
138         }
139     }
140 
141     /// Returns a reduced copy of self.
142     ///
143     /// In general, it is not necessary to use this method, as the only
144     /// method of procuring a non-reduced fraction is through `new_raw`.
reduced(&self) -> Ratio<T>145     pub fn reduced(&self) -> Ratio<T> {
146         let mut ret = self.clone();
147         ret.reduce();
148         ret
149     }
150 
151     /// Returns the reciprocal.
152     ///
153     /// Fails if the `Ratio` is zero.
154     #[inline]
recip(&self) -> Ratio<T>155     pub fn recip(&self) -> Ratio<T> {
156         match self.numer.cmp(&T::zero()) {
157             cmp::Ordering::Equal => panic!("numerator == 0"),
158             cmp::Ordering::Greater => Ratio::new_raw(self.denom.clone(), self.numer.clone()),
159             cmp::Ordering::Less => Ratio::new_raw(T::zero() - self.denom.clone(),
160                                                   T::zero() - self.numer.clone())
161         }
162     }
163 
164     /// Rounds towards minus infinity.
165     #[inline]
floor(&self) -> Ratio<T>166     pub fn floor(&self) -> Ratio<T> {
167         if *self < Zero::zero() {
168             let one: T = One::one();
169             Ratio::from_integer((self.numer.clone() - self.denom.clone() + one) /
170                                 self.denom.clone())
171         } else {
172             Ratio::from_integer(self.numer.clone() / self.denom.clone())
173         }
174     }
175 
176     /// Rounds towards plus infinity.
177     #[inline]
ceil(&self) -> Ratio<T>178     pub fn ceil(&self) -> Ratio<T> {
179         if *self < Zero::zero() {
180             Ratio::from_integer(self.numer.clone() / self.denom.clone())
181         } else {
182             let one: T = One::one();
183             Ratio::from_integer((self.numer.clone() + self.denom.clone() - one) /
184                                 self.denom.clone())
185         }
186     }
187 
188     /// Rounds to the nearest integer. Rounds half-way cases away from zero.
189     #[inline]
round(&self) -> Ratio<T>190     pub fn round(&self) -> Ratio<T> {
191         let zero: Ratio<T> = Zero::zero();
192         let one: T = One::one();
193         let two: T = one.clone() + one.clone();
194 
195         // Find unsigned fractional part of rational number
196         let mut fractional = self.fract();
197         if fractional < zero {
198             fractional = zero - fractional
199         };
200 
201         // The algorithm compares the unsigned fractional part with 1/2, that
202         // is, a/b >= 1/2, or a >= b/2. For odd denominators, we use
203         // a >= (b/2)+1. This avoids overflow issues.
204         let half_or_larger = if fractional.denom().is_even() {
205             *fractional.numer() >= fractional.denom().clone() / two.clone()
206         } else {
207             *fractional.numer() >= (fractional.denom().clone() / two.clone()) + one.clone()
208         };
209 
210         if half_or_larger {
211             let one: Ratio<T> = One::one();
212             if *self >= Zero::zero() {
213                 self.trunc() + one
214             } else {
215                 self.trunc() - one
216             }
217         } else {
218             self.trunc()
219         }
220     }
221 
222     /// Rounds towards zero.
223     #[inline]
trunc(&self) -> Ratio<T>224     pub fn trunc(&self) -> Ratio<T> {
225         Ratio::from_integer(self.numer.clone() / self.denom.clone())
226     }
227 
228     /// Returns the fractional part of a number, with division rounded towards zero.
229     ///
230     /// Satisfies `self == self.trunc() + self.fract()`.
231     #[inline]
fract(&self) -> Ratio<T>232     pub fn fract(&self) -> Ratio<T> {
233         Ratio::new_raw(self.numer.clone() % self.denom.clone(), self.denom.clone())
234     }
235 }
236 
237 impl<T: Clone + Integer + Pow<u32, Output = T>> Ratio<T> {
238     /// Raises the `Ratio` to the power of an exponent.
239     #[inline]
pow(&self, expon: i32) -> Ratio<T>240     pub fn pow(&self, expon: i32) -> Ratio<T> {
241         Pow::pow(self, expon)
242     }
243 }
244 
245 macro_rules! pow_impl {
246     ($exp: ty) => {
247         pow_impl!($exp, $exp);
248     };
249     ($exp: ty, $unsigned: ty) => {
250         impl<T: Clone + Integer + Pow<$unsigned, Output = T>> Pow<$exp> for Ratio<T> {
251             type Output = Ratio<T>;
252             #[inline]
253             fn pow(self, expon: $exp) -> Ratio<T> {
254                 match expon.cmp(&0) {
255                     cmp::Ordering::Equal => One::one(),
256                     cmp::Ordering::Less => {
257                         let expon = expon.wrapping_abs() as $unsigned;
258                         Ratio::new_raw(
259                             Pow::pow(self.denom, expon),
260                             Pow::pow(self.numer, expon),
261                         )
262                     },
263                     cmp::Ordering::Greater => {
264                         Ratio::new_raw(
265                             Pow::pow(self.numer, expon as $unsigned),
266                             Pow::pow(self.denom, expon as $unsigned),
267                         )
268                     }
269                 }
270             }
271         }
272         impl<'a, T: Clone + Integer + Pow<$unsigned, Output = T>> Pow<$exp> for &'a Ratio<T> {
273             type Output = Ratio<T>;
274             #[inline]
275             fn pow(self, expon: $exp) -> Ratio<T> {
276                 Pow::pow(self.clone(), expon)
277             }
278         }
279         impl<'a, T: Clone + Integer + Pow<$unsigned, Output = T>> Pow<&'a $exp> for Ratio<T> {
280             type Output = Ratio<T>;
281             #[inline]
282             fn pow(self, expon: &'a $exp) -> Ratio<T> {
283                 Pow::pow(self, *expon)
284             }
285         }
286         impl<'a, 'b, T: Clone + Integer + Pow<$unsigned, Output = T>> Pow<&'a $exp> for &'b Ratio<T> {
287             type Output = Ratio<T>;
288             #[inline]
289             fn pow(self, expon: &'a $exp) -> Ratio<T> {
290                 Pow::pow(self.clone(), *expon)
291             }
292         }
293     };
294 }
295 
296 // this is solely to make `pow_impl!` work
297 trait WrappingAbs: Sized {
wrapping_abs(self) -> Self298     fn wrapping_abs(self) -> Self {
299         self
300     }
301 }
302 impl WrappingAbs for u8 {}
303 impl WrappingAbs for u16 {}
304 impl WrappingAbs for u32 {}
305 impl WrappingAbs for u64 {}
306 impl WrappingAbs for usize {}
307 
308 pow_impl!(i8, u8);
309 pow_impl!(i16, u16);
310 pow_impl!(i32, u32);
311 pow_impl!(i64, u64);
312 pow_impl!(isize, usize);
313 pow_impl!(u8);
314 pow_impl!(u16);
315 pow_impl!(u32);
316 pow_impl!(u64);
317 pow_impl!(usize);
318 
319 // TODO: pow_impl!(BigUint) and pow_impl!(BigInt, BigUint)
320 
321 #[cfg(feature = "bigint")]
322 impl Ratio<BigInt> {
323     /// Converts a float into a rational number.
from_float<T: FloatCore>(f: T) -> Option<BigRational>324     pub fn from_float<T: FloatCore>(f: T) -> Option<BigRational> {
325         if !f.is_finite() {
326             return None;
327         }
328         let (mantissa, exponent, sign) = f.integer_decode();
329         let bigint_sign = if sign == 1 {
330             Sign::Plus
331         } else {
332             Sign::Minus
333         };
334         if exponent < 0 {
335             let one: BigInt = One::one();
336             let denom: BigInt = one << ((-exponent) as usize);
337             let numer: BigUint = FromPrimitive::from_u64(mantissa).unwrap();
338             Some(Ratio::new(BigInt::from_biguint(bigint_sign, numer), denom))
339         } else {
340             let mut numer: BigUint = FromPrimitive::from_u64(mantissa).unwrap();
341             numer = numer << (exponent as usize);
342             Some(Ratio::from_integer(BigInt::from_biguint(bigint_sign, numer)))
343         }
344     }
345 }
346 
347 // From integer
348 impl<T> From<T> for Ratio<T> where T: Clone + Integer {
from(x: T) -> Ratio<T>349     fn from(x: T) -> Ratio<T> {
350         Ratio::from_integer(x)
351     }
352 }
353 
354 // From pair (through the `new` constructor)
355 impl<T> From<(T, T)> for Ratio<T> where T: Clone + Integer {
from(pair: (T, T)) -> Ratio<T>356     fn from(pair: (T, T)) -> Ratio<T> {
357         Ratio::new(pair.0, pair.1)
358     }
359 }
360 
361 // Comparisons
362 
363 // Mathematically, comparing a/b and c/d is the same as comparing a*d and b*c, but it's very easy
364 // for those multiplications to overflow fixed-size integers, so we need to take care.
365 
366 impl<T: Clone + Integer> Ord for Ratio<T> {
367     #[inline]
cmp(&self, other: &Self) -> cmp::Ordering368     fn cmp(&self, other: &Self) -> cmp::Ordering {
369         // With equal denominators, the numerators can be directly compared
370         if self.denom == other.denom {
371             let ord = self.numer.cmp(&other.numer);
372             return if self.denom < T::zero() {
373                 ord.reverse()
374             } else {
375                 ord
376             };
377         }
378 
379         // With equal numerators, the denominators can be inversely compared
380         if self.numer == other.numer {
381             let ord = self.denom.cmp(&other.denom);
382             return if self.numer < T::zero() {
383                 ord
384             } else {
385                 ord.reverse()
386             };
387         }
388 
389         // Unfortunately, we don't have CheckedMul to try.  That could sometimes avoid all the
390         // division below, or even always avoid it for BigInt and BigUint.
391         // FIXME- future breaking change to add Checked* to Integer?
392 
393         // Compare as floored integers and remainders
394         let (self_int, self_rem) = self.numer.div_mod_floor(&self.denom);
395         let (other_int, other_rem) = other.numer.div_mod_floor(&other.denom);
396         match self_int.cmp(&other_int) {
397             cmp::Ordering::Greater => cmp::Ordering::Greater,
398             cmp::Ordering::Less => cmp::Ordering::Less,
399             cmp::Ordering::Equal => {
400                 match (self_rem.is_zero(), other_rem.is_zero()) {
401                     (true, true) => cmp::Ordering::Equal,
402                     (true, false) => cmp::Ordering::Less,
403                     (false, true) => cmp::Ordering::Greater,
404                     (false, false) => {
405                         // Compare the reciprocals of the remaining fractions in reverse
406                         let self_recip = Ratio::new_raw(self.denom.clone(), self_rem);
407                         let other_recip = Ratio::new_raw(other.denom.clone(), other_rem);
408                         self_recip.cmp(&other_recip).reverse()
409                     }
410                 }
411             }
412         }
413     }
414 }
415 
416 impl<T: Clone + Integer> PartialOrd for Ratio<T> {
417     #[inline]
partial_cmp(&self, other: &Self) -> Option<cmp::Ordering>418     fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
419         Some(self.cmp(other))
420     }
421 }
422 
423 impl<T: Clone + Integer> PartialEq for Ratio<T> {
424     #[inline]
eq(&self, other: &Self) -> bool425     fn eq(&self, other: &Self) -> bool {
426         self.cmp(other) == cmp::Ordering::Equal
427     }
428 }
429 
430 impl<T: Clone + Integer> Eq for Ratio<T> {}
431 
432 // NB: We can't just `#[derive(Hash)]`, because it needs to agree
433 // with `Eq` even for non-reduced ratios.
434 impl<T: Clone + Integer + Hash> Hash for Ratio<T> {
hash<H: Hasher>(&self, state: &mut H)435     fn hash<H: Hasher>(&self, state: &mut H) {
436         recurse(&self.numer, &self.denom, state);
437 
438         fn recurse<T: Integer + Hash, H: Hasher>(numer: &T, denom: &T, state: &mut H) {
439             if !denom.is_zero() {
440                 let (int, rem) = numer.div_mod_floor(denom);
441                 int.hash(state);
442                 recurse(denom, &rem, state);
443             } else {
444                 denom.hash(state);
445             }
446         }
447     }
448 }
449 
450 mod iter_sum_product {
451     use ::core::iter::{Sum, Product};
452     use Ratio;
453     use integer::Integer;
454     use traits::{Zero, One};
455 
456     impl<T: Integer + Clone> Sum for Ratio<T> {
sum<I>(iter: I) -> Self where I: Iterator<Item = Ratio<T>>457         fn sum<I>(iter: I) -> Self
458         where
459             I: Iterator<Item = Ratio<T>>
460         {
461             iter.fold(Self::zero(), |sum, num| sum + num)
462         }
463     }
464 
465     impl<'a, T: Integer + Clone> Sum<&'a Ratio<T>> for Ratio<T> {
sum<I>(iter: I) -> Self where I: Iterator<Item = &'a Ratio<T>>466         fn sum<I>(iter: I) -> Self
467         where
468             I: Iterator<Item = &'a Ratio<T>>
469         {
470             iter.fold(Self::zero(), |sum, num| sum + num)
471         }
472     }
473 
474     impl<T: Integer + Clone> Product for Ratio<T> {
product<I>(iter: I) -> Self where I: Iterator<Item = Ratio<T>>475         fn product<I>(iter: I) -> Self
476         where
477             I: Iterator<Item = Ratio<T>>
478         {
479             iter.fold(Self::one(), |prod, num| prod * num)
480         }
481     }
482 
483     impl<'a, T: Integer + Clone> Product<&'a Ratio<T>> for Ratio<T> {
product<I>(iter: I) -> Self where I: Iterator<Item = &'a Ratio<T>>484         fn product<I>(iter: I) -> Self
485         where
486             I: Iterator<Item = &'a Ratio<T>>
487         {
488             iter.fold(Self::one(), |prod, num| prod * num)
489         }
490     }
491 }
492 
493 mod opassign {
494     use core::ops::{AddAssign, SubAssign, MulAssign, DivAssign, RemAssign};
495 
496     use Ratio;
497     use integer::Integer;
498     use traits::NumAssign;
499 
500     impl<T: Clone + Integer + NumAssign> AddAssign for Ratio<T> {
add_assign(&mut self, other: Ratio<T>)501         fn add_assign(&mut self, other: Ratio<T>) {
502             self.numer *= other.denom.clone();
503             self.numer += self.denom.clone() * other.numer;
504             self.denom *= other.denom;
505             self.reduce();
506         }
507     }
508 
509     impl<T: Clone + Integer + NumAssign> DivAssign for Ratio<T> {
div_assign(&mut self, other: Ratio<T>)510         fn div_assign(&mut self, other: Ratio<T>) {
511             self.numer *= other.denom;
512             self.denom *= other.numer;
513             self.reduce();
514         }
515     }
516 
517     impl<T: Clone + Integer + NumAssign> MulAssign for Ratio<T> {
mul_assign(&mut self, other: Ratio<T>)518         fn mul_assign(&mut self, other: Ratio<T>) {
519             self.numer *= other.numer;
520             self.denom *= other.denom;
521             self.reduce();
522         }
523     }
524 
525     impl<T: Clone + Integer + NumAssign> RemAssign for Ratio<T> {
rem_assign(&mut self, other: Ratio<T>)526         fn rem_assign(&mut self, other: Ratio<T>) {
527             self.numer *= other.denom.clone();
528             self.numer %= self.denom.clone() * other.numer;
529             self.denom *= other.denom;
530             self.reduce();
531         }
532     }
533 
534     impl<T: Clone + Integer + NumAssign> SubAssign for Ratio<T> {
sub_assign(&mut self, other: Ratio<T>)535         fn sub_assign(&mut self, other: Ratio<T>) {
536             self.numer *= other.denom.clone();
537             self.numer -= self.denom.clone() * other.numer;
538             self.denom *= other.denom;
539             self.reduce();
540         }
541     }
542 
543     // a/b + c/1 = (a*1 + b*c) / (b*1) = (a + b*c) / b
544     impl<T: Clone + Integer + NumAssign> AddAssign<T> for Ratio<T> {
add_assign(&mut self, other: T)545         fn add_assign(&mut self, other: T) {
546             self.numer += self.denom.clone() * other;
547             self.reduce();
548         }
549     }
550 
551     impl<T: Clone + Integer + NumAssign> DivAssign<T> for Ratio<T> {
div_assign(&mut self, other: T)552         fn div_assign(&mut self, other: T) {
553             self.denom *= other;
554             self.reduce();
555         }
556     }
557 
558     impl<T: Clone + Integer + NumAssign> MulAssign<T> for Ratio<T> {
mul_assign(&mut self, other: T)559         fn mul_assign(&mut self, other: T) {
560             self.numer *= other;
561             self.reduce();
562         }
563     }
564 
565     // a/b % c/1 = (a*1 % b*c) / (b*1) = (a % b*c) / b
566     impl<T: Clone + Integer + NumAssign> RemAssign<T> for Ratio<T> {
rem_assign(&mut self, other: T)567         fn rem_assign(&mut self, other: T) {
568             self.numer %= self.denom.clone() * other;
569             self.reduce();
570         }
571     }
572 
573     // a/b - c/1 = (a*1 - b*c) / (b*1) = (a - b*c) / b
574     impl<T: Clone + Integer + NumAssign> SubAssign<T> for Ratio<T> {
sub_assign(&mut self, other: T)575         fn sub_assign(&mut self, other: T) {
576             self.numer -= self.denom.clone() * other;
577             self.reduce();
578         }
579     }
580 
581     macro_rules! forward_op_assign {
582         (impl $imp:ident, $method:ident) => {
583             impl<'a, T: Clone + Integer + NumAssign> $imp<&'a Ratio<T>> for Ratio<T> {
584                 #[inline]
585                 fn $method(&mut self, other: &Ratio<T>) {
586                     self.$method(other.clone())
587                 }
588             }
589             impl<'a, T: Clone + Integer + NumAssign> $imp<&'a T> for Ratio<T> {
590                 #[inline]
591                 fn $method(&mut self, other: &T) {
592                     self.$method(other.clone())
593                 }
594             }
595         }
596     }
597 
598     forward_op_assign!(impl AddAssign, add_assign);
599     forward_op_assign!(impl DivAssign, div_assign);
600     forward_op_assign!(impl MulAssign, mul_assign);
601     forward_op_assign!(impl RemAssign, rem_assign);
602     forward_op_assign!(impl SubAssign, sub_assign);
603 }
604 
605 macro_rules! forward_ref_ref_binop {
606     (impl $imp:ident, $method:ident) => {
607         impl<'a, 'b, T: Clone + Integer> $imp<&'b Ratio<T>> for &'a Ratio<T> {
608             type Output = Ratio<T>;
609 
610             #[inline]
611             fn $method(self, other: &'b Ratio<T>) -> Ratio<T> {
612                 self.clone().$method(other.clone())
613             }
614         }
615         impl<'a, 'b, T: Clone + Integer> $imp<&'b T> for &'a Ratio<T> {
616             type Output = Ratio<T>;
617 
618             #[inline]
619             fn $method(self, other: &'b T) -> Ratio<T> {
620                 self.clone().$method(other.clone())
621             }
622         }
623     }
624 }
625 
626 macro_rules! forward_ref_val_binop {
627     (impl $imp:ident, $method:ident) => {
628         impl<'a, T> $imp<Ratio<T>> for &'a Ratio<T> where
629             T: Clone + Integer
630         {
631             type Output = Ratio<T>;
632 
633             #[inline]
634             fn $method(self, other: Ratio<T>) -> Ratio<T> {
635                 self.clone().$method(other)
636             }
637         }
638         impl<'a, T> $imp<T> for &'a Ratio<T> where
639             T: Clone + Integer
640         {
641             type Output = Ratio<T>;
642 
643             #[inline]
644             fn $method(self, other: T) -> Ratio<T> {
645                 self.clone().$method(other)
646             }
647         }
648     }
649 }
650 
651 macro_rules! forward_val_ref_binop {
652     (impl $imp:ident, $method:ident) => {
653         impl<'a, T> $imp<&'a Ratio<T>> for Ratio<T> where
654             T: Clone + Integer
655         {
656             type Output = Ratio<T>;
657 
658             #[inline]
659             fn $method(self, other: &Ratio<T>) -> Ratio<T> {
660                 self.$method(other.clone())
661             }
662         }
663         impl<'a, T> $imp<&'a T> for Ratio<T> where
664             T: Clone + Integer
665         {
666             type Output = Ratio<T>;
667 
668             #[inline]
669             fn $method(self, other: &T) -> Ratio<T> {
670                 self.$method(other.clone())
671             }
672         }
673     }
674 }
675 
676 macro_rules! forward_all_binop {
677     (impl $imp:ident, $method:ident) => {
678         forward_ref_ref_binop!(impl $imp, $method);
679         forward_ref_val_binop!(impl $imp, $method);
680         forward_val_ref_binop!(impl $imp, $method);
681     };
682 }
683 
684 // Arithmetic
685 forward_all_binop!(impl Mul, mul);
686 // a/b * c/d = (a*c)/(b*d)
687 impl<T> Mul<Ratio<T>> for Ratio<T>
688     where T: Clone + Integer
689 {
690     type Output = Ratio<T>;
691     #[inline]
mul(self, rhs: Ratio<T>) -> Ratio<T>692     fn mul(self, rhs: Ratio<T>) -> Ratio<T> {
693         Ratio::new(self.numer * rhs.numer,
694                    self.denom * rhs.denom)
695     }
696 }
697 // a/b * c/1 = (a*c) / (b*1) = (a*c) / b
698 impl<T> Mul<T> for Ratio<T>
699     where T: Clone + Integer
700 {
701     type Output = Ratio<T>;
702     #[inline]
mul(self, rhs: T) -> Ratio<T>703     fn mul(self, rhs: T) -> Ratio<T> {
704         Ratio::new(self.numer * rhs,
705                    self.denom)
706     }
707 }
708 
709 forward_all_binop!(impl Div, div);
710 // (a/b) / (c/d) = (a*d) / (b*c)
711 impl<T> Div<Ratio<T>> for Ratio<T>
712     where T: Clone + Integer
713 {
714     type Output = Ratio<T>;
715 
716     #[inline]
div(self, rhs: Ratio<T>) -> Ratio<T>717     fn div(self, rhs: Ratio<T>) -> Ratio<T> {
718         Ratio::new(self.numer * rhs.denom,
719                    self.denom * rhs.numer)
720     }
721 }
722 // (a/b) / (c/1) = (a*1) / (b*c) = a / (b*c)
723 impl<T> Div<T> for Ratio<T>
724     where T: Clone + Integer
725 {
726     type Output = Ratio<T>;
727 
728     #[inline]
div(self, rhs: T) -> Ratio<T>729     fn div(self, rhs: T) -> Ratio<T> {
730         Ratio::new(self.numer,
731                    self.denom * rhs)
732     }
733 }
734 
735 macro_rules! arith_impl {
736     (impl $imp:ident, $method:ident) => {
737         forward_all_binop!(impl $imp, $method);
738         // Abstracts the a/b `op` c/d = (a*d `op` b*c) / (b*d) pattern
739         impl<T: Clone + Integer> $imp<Ratio<T>> for Ratio<T> {
740             type Output = Ratio<T>;
741             #[inline]
742             fn $method(self, rhs: Ratio<T>) -> Ratio<T> {
743                 Ratio::new((self.numer * rhs.denom.clone()).$method(self.denom.clone() * rhs.numer),
744                            self.denom * rhs.denom)
745             }
746         }
747         // Abstracts the a/b `op` c/1 = (a*1 `op` b*c) / (b*1) = (a `op` b*c) / b pattern
748         impl<T: Clone + Integer> $imp<T> for Ratio<T> {
749             type Output = Ratio<T>;
750             #[inline]
751             fn $method(self, rhs: T) -> Ratio<T> {
752                 Ratio::new(self.numer.$method(self.denom.clone() * rhs),
753                            self.denom)
754             }
755         }
756     }
757 }
758 
759 arith_impl!(impl Add, add);
760 arith_impl!(impl Sub, sub);
761 arith_impl!(impl Rem, rem);
762 
763 // Like `std::try!` for Option<T>, unwrap the value or early-return None.
764 // Since Rust 1.22 this can be replaced by the `?` operator.
765 macro_rules! otry {
766     ($expr:expr) => (match $expr {
767         Some(val) => val,
768         None => return None,
769     })
770 }
771 
772 // a/b * c/d = (a*c)/(b*d)
773 impl<T> CheckedMul for Ratio<T>
774     where T: Clone + Integer + CheckedMul
775 {
776     #[inline]
checked_mul(&self, rhs: &Ratio<T>) -> Option<Ratio<T>>777     fn checked_mul(&self, rhs: &Ratio<T>) -> Option<Ratio<T>> {
778         Some(Ratio::new(otry!(self.numer.checked_mul(&rhs.numer)),
779                         otry!(self.denom.checked_mul(&rhs.denom))))
780     }
781 }
782 
783 // (a/b) / (c/d) = (a*d)/(b*c)
784 impl<T> CheckedDiv for Ratio<T>
785     where T: Clone + Integer + CheckedMul
786 {
787     #[inline]
checked_div(&self, rhs: &Ratio<T>) -> Option<Ratio<T>>788     fn checked_div(&self, rhs: &Ratio<T>) -> Option<Ratio<T>> {
789         let bc = otry!(self.denom.checked_mul(&rhs.numer));
790         if bc.is_zero() {
791             None
792         } else {
793             Some(Ratio::new(otry!(self.numer.checked_mul(&rhs.denom)), bc))
794         }
795     }
796 }
797 
798 // As arith_impl! but for Checked{Add,Sub} traits
799 macro_rules! checked_arith_impl {
800     (impl $imp:ident, $method:ident) => {
801         impl<T: Clone + Integer + CheckedMul + $imp> $imp for Ratio<T> {
802             #[inline]
803             fn $method(&self, rhs: &Ratio<T>) -> Option<Ratio<T>> {
804                 let ad = otry!(self.numer.checked_mul(&rhs.denom));
805                 let bc = otry!(self.denom.checked_mul(&rhs.numer));
806                 let bd = otry!(self.denom.checked_mul(&rhs.denom));
807                 Some(Ratio::new(otry!(ad.$method(&bc)), bd))
808             }
809         }
810     }
811 }
812 
813 // a/b + c/d = (a*d + b*c)/(b*d)
814 checked_arith_impl!(impl CheckedAdd, checked_add);
815 
816 // a/b - c/d = (a*d - b*c)/(b*d)
817 checked_arith_impl!(impl CheckedSub, checked_sub);
818 
819 impl<T> Neg for Ratio<T>
820     where T: Clone + Integer + Neg<Output = T>
821 {
822     type Output = Ratio<T>;
823 
824     #[inline]
neg(self) -> Ratio<T>825     fn neg(self) -> Ratio<T> {
826         Ratio::new_raw(-self.numer, self.denom)
827     }
828 }
829 
830 impl<'a, T> Neg for &'a Ratio<T>
831     where T: Clone + Integer + Neg<Output = T>
832 {
833     type Output = Ratio<T>;
834 
835     #[inline]
neg(self) -> Ratio<T>836     fn neg(self) -> Ratio<T> {
837         -self.clone()
838     }
839 }
840 
841 impl<T> Inv for Ratio<T>
842     where T: Clone + Integer
843 {
844     type Output = Ratio<T>;
845 
846     #[inline]
inv(self) -> Ratio<T>847     fn inv(self) -> Ratio<T> {
848         self.recip()
849     }
850 }
851 
852 impl<'a, T> Inv for &'a Ratio<T>
853     where T: Clone + Integer
854 {
855     type Output = Ratio<T>;
856 
857     #[inline]
inv(self) -> Ratio<T>858     fn inv(self) -> Ratio<T> {
859         self.recip()
860     }
861 }
862 
863 // Constants
864 impl<T: Clone + Integer> Zero for Ratio<T> {
865     #[inline]
zero() -> Ratio<T>866     fn zero() -> Ratio<T> {
867         Ratio::new_raw(Zero::zero(), One::one())
868     }
869 
870     #[inline]
is_zero(&self) -> bool871     fn is_zero(&self) -> bool {
872         self.numer.is_zero()
873     }
874 }
875 
876 impl<T: Clone + Integer> One for Ratio<T> {
877     #[inline]
one() -> Ratio<T>878     fn one() -> Ratio<T> {
879         Ratio::new_raw(One::one(), One::one())
880     }
881 
882     #[inline]
is_one(&self) -> bool883     fn is_one(&self) -> bool {
884         self.numer == self.denom
885     }
886 }
887 
888 impl<T: Clone + Integer> Num for Ratio<T> {
889     type FromStrRadixErr = ParseRatioError;
890 
891     /// Parses `numer/denom` where the numbers are in base `radix`.
from_str_radix(s: &str, radix: u32) -> Result<Ratio<T>, ParseRatioError>892     fn from_str_radix(s: &str, radix: u32) -> Result<Ratio<T>, ParseRatioError> {
893         if s.splitn(2, '/').count() == 2 {
894             let mut parts = s.splitn(2, '/').map(|ss| T::from_str_radix(ss, radix).map_err(|_| {
895                 ParseRatioError { kind: RatioErrorKind::ParseError }
896             }));
897             let numer: T = parts.next().unwrap()?;
898             let denom: T = parts.next().unwrap()?;
899             if denom.is_zero() {
900                 Err(ParseRatioError { kind: RatioErrorKind::ZeroDenominator })
901             } else {
902                 Ok(Ratio::new(numer, denom))
903             }
904         } else {
905             Err(ParseRatioError { kind: RatioErrorKind::ParseError })
906         }
907     }
908 }
909 
910 impl<T: Clone + Integer + Signed> Signed for Ratio<T> {
911     #[inline]
abs(&self) -> Ratio<T>912     fn abs(&self) -> Ratio<T> {
913         if self.is_negative() {
914             -self.clone()
915         } else {
916             self.clone()
917         }
918     }
919 
920     #[inline]
abs_sub(&self, other: &Ratio<T>) -> Ratio<T>921     fn abs_sub(&self, other: &Ratio<T>) -> Ratio<T> {
922         if *self <= *other {
923             Zero::zero()
924         } else {
925             self - other
926         }
927     }
928 
929     #[inline]
signum(&self) -> Ratio<T>930     fn signum(&self) -> Ratio<T> {
931         if self.is_positive() {
932             Self::one()
933         } else if self.is_zero() {
934             Self::zero()
935         } else {
936             -Self::one()
937         }
938     }
939 
940     #[inline]
is_positive(&self) -> bool941     fn is_positive(&self) -> bool {
942         (self.numer.is_positive() && self.denom.is_positive()) ||
943         (self.numer.is_negative() && self.denom.is_negative())
944     }
945 
946     #[inline]
is_negative(&self) -> bool947     fn is_negative(&self) -> bool {
948         (self.numer.is_negative() && self.denom.is_positive()) ||
949         (self.numer.is_positive() && self.denom.is_negative())
950     }
951 }
952 
953 // String conversions
954 impl<T> fmt::Display for Ratio<T>
955     where T: fmt::Display + Eq + One
956 {
957     /// Renders as `numer/denom`. If denom=1, renders as numer.
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result958     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
959         if self.denom.is_one() {
960             write!(f, "{}", self.numer)
961         } else {
962             write!(f, "{}/{}", self.numer, self.denom)
963         }
964     }
965 }
966 
967 impl<T: FromStr + Clone + Integer> FromStr for Ratio<T> {
968     type Err = ParseRatioError;
969 
970     /// Parses `numer/denom` or just `numer`.
from_str(s: &str) -> Result<Ratio<T>, ParseRatioError>971     fn from_str(s: &str) -> Result<Ratio<T>, ParseRatioError> {
972         let mut split = s.splitn(2, '/');
973 
974         let n = try!(split.next().ok_or(ParseRatioError { kind: RatioErrorKind::ParseError }));
975         let num = try!(FromStr::from_str(n)
976                            .map_err(|_| ParseRatioError { kind: RatioErrorKind::ParseError }));
977 
978         let d = split.next().unwrap_or("1");
979         let den = try!(FromStr::from_str(d)
980                            .map_err(|_| ParseRatioError { kind: RatioErrorKind::ParseError }));
981 
982         if Zero::is_zero(&den) {
983             Err(ParseRatioError { kind: RatioErrorKind::ZeroDenominator })
984         } else {
985             Ok(Ratio::new(num, den))
986         }
987     }
988 }
989 
990 impl<T> Into<(T, T)> for Ratio<T> {
into(self) -> (T, T)991     fn into(self) -> (T, T) {
992         (self.numer, self.denom)
993     }
994 }
995 
996 #[cfg(feature = "serde")]
997 impl<T> serde::Serialize for Ratio<T>
998     where T: serde::Serialize + Clone + Integer + PartialOrd
999 {
serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: serde::Serializer1000     fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
1001         where S: serde::Serializer
1002     {
1003         (self.numer(), self.denom()).serialize(serializer)
1004     }
1005 }
1006 
1007 #[cfg(feature = "serde")]
1008 impl<'de, T> serde::Deserialize<'de> for Ratio<T>
1009     where T: serde::Deserialize<'de> + Clone + Integer + PartialOrd
1010 {
deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: serde::Deserializer<'de>1011     fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
1012         where D: serde::Deserializer<'de>
1013     {
1014         use serde::de::Unexpected;
1015         use serde::de::Error;
1016         let (numer, denom): (T,T) = try!(serde::Deserialize::deserialize(deserializer));
1017         if denom.is_zero() {
1018             Err(Error::invalid_value(Unexpected::Signed(0), &"a ratio with non-zero denominator"))
1019         } else {
1020             Ok(Ratio::new_raw(numer, denom))
1021         }
1022     }
1023 }
1024 
1025 // FIXME: Bubble up specific errors
1026 #[derive(Copy, Clone, Debug, PartialEq)]
1027 pub struct ParseRatioError {
1028     kind: RatioErrorKind,
1029 }
1030 
1031 #[derive(Copy, Clone, Debug, PartialEq)]
1032 enum RatioErrorKind {
1033     ParseError,
1034     ZeroDenominator,
1035 }
1036 
1037 impl fmt::Display for ParseRatioError {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result1038     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1039         self.kind.description().fmt(f)
1040     }
1041 }
1042 
1043 #[cfg(feature = "std")]
1044 impl Error for ParseRatioError {
description(&self) -> &str1045     fn description(&self) -> &str {
1046         self.kind.description()
1047     }
1048 }
1049 
1050 impl RatioErrorKind {
description(&self) -> &'static str1051     fn description(&self) -> &'static str {
1052         match *self {
1053             RatioErrorKind::ParseError => "failed to parse integer",
1054             RatioErrorKind::ZeroDenominator => "zero value denominator",
1055         }
1056     }
1057 }
1058 
1059 #[cfg(feature = "bigint")]
1060 impl FromPrimitive for Ratio<BigInt> {
from_i64(n: i64) -> Option<Self>1061     fn from_i64(n: i64) -> Option<Self> {
1062         Some(Ratio::from_integer(n.into()))
1063     }
1064 
1065     #[cfg(has_i128)]
from_i128(n: i128) -> Option<Self>1066     fn from_i128(n: i128) -> Option<Self> {
1067         Some(Ratio::from_integer(n.into()))
1068     }
1069 
from_u64(n: u64) -> Option<Self>1070     fn from_u64(n: u64) -> Option<Self> {
1071         Some(Ratio::from_integer(n.into()))
1072     }
1073 
1074     #[cfg(has_i128)]
from_u128(n: u128) -> Option<Self>1075     fn from_u128(n: u128) -> Option<Self> {
1076         Some(Ratio::from_integer(n.into()))
1077     }
1078 
from_f32(n: f32) -> Option<Self>1079     fn from_f32(n: f32) -> Option<Self> {
1080         Ratio::from_float(n)
1081     }
1082 
from_f64(n: f64) -> Option<Self>1083     fn from_f64(n: f64) -> Option<Self> {
1084         Ratio::from_float(n)
1085     }
1086 }
1087 
1088 macro_rules! from_primitive_integer {
1089     ($typ:ty, $approx:ident) => {
1090         impl FromPrimitive for Ratio<$typ> {
1091             fn from_i64(n: i64) -> Option<Self> {
1092                 <$typ as FromPrimitive>::from_i64(n).map(Ratio::from_integer)
1093             }
1094 
1095             #[cfg(has_i128)]
1096             fn from_i128(n: i128) -> Option<Self> {
1097                 <$typ as FromPrimitive>::from_i128(n).map(Ratio::from_integer)
1098             }
1099 
1100             fn from_u64(n: u64) -> Option<Self> {
1101                 <$typ as FromPrimitive>::from_u64(n).map(Ratio::from_integer)
1102             }
1103 
1104             #[cfg(has_i128)]
1105             fn from_u128(n: u128) -> Option<Self> {
1106                 <$typ as FromPrimitive>::from_u128(n).map(Ratio::from_integer)
1107             }
1108 
1109             fn from_f32(n: f32) -> Option<Self> {
1110                 $approx(n, 10e-20, 30)
1111             }
1112 
1113             fn from_f64(n: f64) -> Option<Self> {
1114                 $approx(n, 10e-20, 30)
1115             }
1116         }
1117     }
1118 }
1119 
1120 from_primitive_integer!(i8, approximate_float);
1121 from_primitive_integer!(i16, approximate_float);
1122 from_primitive_integer!(i32, approximate_float);
1123 from_primitive_integer!(i64, approximate_float);
1124 #[cfg(has_i128)]
1125 from_primitive_integer!(i128, approximate_float);
1126 from_primitive_integer!(isize, approximate_float);
1127 
1128 from_primitive_integer!(u8, approximate_float_unsigned);
1129 from_primitive_integer!(u16, approximate_float_unsigned);
1130 from_primitive_integer!(u32, approximate_float_unsigned);
1131 from_primitive_integer!(u64, approximate_float_unsigned);
1132 #[cfg(has_i128)]
1133 from_primitive_integer!(u128, approximate_float_unsigned);
1134 from_primitive_integer!(usize, approximate_float_unsigned);
1135 
1136 impl<T: Integer + Signed + Bounded + NumCast + Clone> Ratio<T> {
approximate_float<F: FloatCore + NumCast>(f: F) -> Option<Ratio<T>>1137     pub fn approximate_float<F: FloatCore + NumCast>(f: F) -> Option<Ratio<T>> {
1138         // 1/10e-20 < 1/2**32 which seems like a good default, and 30 seems
1139         // to work well. Might want to choose something based on the types in the future, e.g.
1140         // T::max().recip() and T::bits() or something similar.
1141         let epsilon = <F as NumCast>::from(10e-20).expect("Can't convert 10e-20");
1142         approximate_float(f, epsilon, 30)
1143     }
1144 }
1145 
approximate_float<T, F>(val: F, max_error: F, max_iterations: usize) -> Option<Ratio<T>> where T: Integer + Signed + Bounded + NumCast + Clone, F: FloatCore + NumCast1146 fn approximate_float<T, F>(val: F, max_error: F, max_iterations: usize) -> Option<Ratio<T>>
1147     where T: Integer + Signed + Bounded + NumCast + Clone,
1148           F: FloatCore + NumCast
1149 {
1150     let negative = val.is_sign_negative();
1151     let abs_val = val.abs();
1152 
1153     let r = approximate_float_unsigned(abs_val, max_error, max_iterations);
1154 
1155     // Make negative again if needed
1156     if negative {
1157         r.map(|r| r.neg())
1158     } else {
1159         r
1160     }
1161 }
1162 
1163 // No Unsigned constraint because this also works on positive integers and is called
1164 // like that, see above
approximate_float_unsigned<T, F>(val: F, max_error: F, max_iterations: usize) -> Option<Ratio<T>> where T: Integer + Bounded + NumCast + Clone, F: FloatCore + NumCast1165 fn approximate_float_unsigned<T, F>(val: F, max_error: F, max_iterations: usize) -> Option<Ratio<T>>
1166     where T: Integer + Bounded + NumCast + Clone,
1167           F: FloatCore + NumCast
1168 {
1169     // Continued fractions algorithm
1170     // http://mathforum.org/dr.math/faq/faq.fractions.html#decfrac
1171 
1172     if val < F::zero() || val.is_nan() {
1173         return None;
1174     }
1175 
1176     let mut q = val;
1177     let mut n0 = T::zero();
1178     let mut d0 = T::one();
1179     let mut n1 = T::one();
1180     let mut d1 = T::zero();
1181 
1182     let t_max = T::max_value();
1183     let t_max_f = match <F as NumCast>::from(t_max.clone()) {
1184         None => return None,
1185         Some(t_max_f) => t_max_f,
1186     };
1187 
1188     // 1/epsilon > T::MAX
1189     let epsilon = t_max_f.recip();
1190 
1191     // Overflow
1192     if q > t_max_f {
1193         return None;
1194     }
1195 
1196     for _ in 0..max_iterations {
1197         let a = match <T as NumCast>::from(q) {
1198             None => break,
1199             Some(a) => a,
1200         };
1201 
1202         let a_f = match <F as NumCast>::from(a.clone()) {
1203             None => break,
1204             Some(a_f) => a_f,
1205         };
1206         let f = q - a_f;
1207 
1208         // Prevent overflow
1209         if !a.is_zero() &&
1210            (n1 > t_max.clone() / a.clone() ||
1211             d1 > t_max.clone() / a.clone() ||
1212             a.clone() * n1.clone() > t_max.clone() - n0.clone() ||
1213             a.clone() * d1.clone() > t_max.clone() - d0.clone()) {
1214             break;
1215         }
1216 
1217         let n = a.clone() * n1.clone() + n0.clone();
1218         let d = a.clone() * d1.clone() + d0.clone();
1219 
1220         n0 = n1;
1221         d0 = d1;
1222         n1 = n.clone();
1223         d1 = d.clone();
1224 
1225         // Simplify fraction. Doing so here instead of at the end
1226         // allows us to get closer to the target value without overflows
1227         let g = Integer::gcd(&n1, &d1);
1228         if !g.is_zero() {
1229             n1 = n1 / g.clone();
1230             d1 = d1 / g.clone();
1231         }
1232 
1233         // Close enough?
1234         let (n_f, d_f) = match (<F as NumCast>::from(n), <F as NumCast>::from(d)) {
1235             (Some(n_f), Some(d_f)) => (n_f, d_f),
1236             _ => break,
1237         };
1238         if (n_f / d_f - val).abs() < max_error {
1239             break;
1240         }
1241 
1242         // Prevent division by ~0
1243         if f < epsilon {
1244             break;
1245         }
1246         q = f.recip();
1247     }
1248 
1249     // Overflow
1250     if d1.is_zero() {
1251         return None;
1252     }
1253 
1254     Some(Ratio::new(n1, d1))
1255 }
1256 
1257 #[cfg(test)]
1258 #[cfg(feature = "std")]
hash<T: Hash>(x: &T) -> u641259 fn hash<T: Hash>(x: &T) -> u64 {
1260     use std::hash::BuildHasher;
1261     use std::collections::hash_map::RandomState;
1262     let mut hasher = <RandomState as BuildHasher>::Hasher::new();
1263     x.hash(&mut hasher);
1264     hasher.finish()
1265 }
1266 
1267 #[cfg(test)]
1268 mod test {
1269     use super::{Ratio, Rational};
1270     #[cfg(feature = "bigint")]
1271     use super::BigRational;
1272 
1273     use core::str::FromStr;
1274     use core::i32;
1275     use core::f64;
1276     use traits::{Zero, One, Signed, FromPrimitive, Pow};
1277     use integer::Integer;
1278 
1279     pub const _0: Rational = Ratio {
1280         numer: 0,
1281         denom: 1,
1282     };
1283     pub const _1: Rational = Ratio {
1284         numer: 1,
1285         denom: 1,
1286     };
1287     pub const _2: Rational = Ratio {
1288         numer: 2,
1289         denom: 1,
1290     };
1291     pub const _NEG2: Rational = Ratio {
1292         numer: -2,
1293         denom: 1,
1294     };
1295     pub const _1_2: Rational = Ratio {
1296         numer: 1,
1297         denom: 2,
1298     };
1299     pub const _3_2: Rational = Ratio {
1300         numer: 3,
1301         denom: 2,
1302     };
1303     pub const _NEG1_2: Rational = Ratio {
1304         numer: -1,
1305         denom: 2,
1306     };
1307     pub const _1_NEG2: Rational = Ratio {
1308         numer: 1,
1309         denom: -2,
1310     };
1311     pub const _NEG1_NEG2: Rational = Ratio {
1312         numer: -1,
1313         denom: -2,
1314     };
1315     pub const _1_3: Rational = Ratio {
1316         numer: 1,
1317         denom: 3,
1318     };
1319     pub const _NEG1_3: Rational = Ratio {
1320         numer: -1,
1321         denom: 3,
1322     };
1323     pub const _2_3: Rational = Ratio {
1324         numer: 2,
1325         denom: 3,
1326     };
1327     pub const _NEG2_3: Rational = Ratio {
1328         numer: -2,
1329         denom: 3,
1330     };
1331 
1332     #[cfg(feature = "bigint")]
to_big(n: Rational) -> BigRational1333     pub fn to_big(n: Rational) -> BigRational {
1334         Ratio::new(FromPrimitive::from_isize(n.numer).unwrap(),
1335                    FromPrimitive::from_isize(n.denom).unwrap())
1336     }
1337     #[cfg(not(feature = "bigint"))]
to_big(n: Rational) -> Rational1338     pub fn to_big(n: Rational) -> Rational {
1339         Ratio::new(FromPrimitive::from_isize(n.numer).unwrap(),
1340                    FromPrimitive::from_isize(n.denom).unwrap())
1341     }
1342 
1343     #[test]
test_test_constants()1344     fn test_test_constants() {
1345         // check our constants are what Ratio::new etc. would make.
1346         assert_eq!(_0, Zero::zero());
1347         assert_eq!(_1, One::one());
1348         assert_eq!(_2, Ratio::from_integer(2));
1349         assert_eq!(_1_2, Ratio::new(1, 2));
1350         assert_eq!(_3_2, Ratio::new(3, 2));
1351         assert_eq!(_NEG1_2, Ratio::new(-1, 2));
1352         assert_eq!(_2, From::from(2));
1353     }
1354 
1355     #[test]
test_new_reduce()1356     fn test_new_reduce() {
1357         let one22 = Ratio::new(2, 2);
1358 
1359         assert_eq!(one22, One::one());
1360     }
1361     #[test]
1362     #[should_panic]
test_new_zero()1363     fn test_new_zero() {
1364         let _a = Ratio::new(1, 0);
1365     }
1366 
1367     #[test]
test_approximate_float()1368     fn test_approximate_float() {
1369         assert_eq!(Ratio::from_f32(0.5f32), Some(Ratio::new(1i64, 2)));
1370         assert_eq!(Ratio::from_f64(0.5f64), Some(Ratio::new(1i32, 2)));
1371         assert_eq!(Ratio::from_f32(5f32), Some(Ratio::new(5i64, 1)));
1372         assert_eq!(Ratio::from_f64(5f64), Some(Ratio::new(5i32, 1)));
1373         assert_eq!(Ratio::from_f32(29.97f32), Some(Ratio::new(2997i64, 100)));
1374         assert_eq!(Ratio::from_f32(-29.97f32), Some(Ratio::new(-2997i64, 100)));
1375 
1376         assert_eq!(Ratio::<i8>::from_f32(63.5f32), Some(Ratio::new(127i8, 2)));
1377         assert_eq!(Ratio::<i8>::from_f32(126.5f32), Some(Ratio::new(126i8, 1)));
1378         assert_eq!(Ratio::<i8>::from_f32(127.0f32), Some(Ratio::new(127i8, 1)));
1379         assert_eq!(Ratio::<i8>::from_f32(127.5f32), None);
1380         assert_eq!(Ratio::<i8>::from_f32(-63.5f32), Some(Ratio::new(-127i8, 2)));
1381         assert_eq!(Ratio::<i8>::from_f32(-126.5f32), Some(Ratio::new(-126i8, 1)));
1382         assert_eq!(Ratio::<i8>::from_f32(-127.0f32), Some(Ratio::new(-127i8, 1)));
1383         assert_eq!(Ratio::<i8>::from_f32(-127.5f32), None);
1384 
1385         assert_eq!(Ratio::<u8>::from_f32(-127f32), None);
1386         assert_eq!(Ratio::<u8>::from_f32(127f32), Some(Ratio::new(127u8, 1)));
1387         assert_eq!(Ratio::<u8>::from_f32(127.5f32), Some(Ratio::new(255u8, 2)));
1388         assert_eq!(Ratio::<u8>::from_f32(256f32), None);
1389 
1390         assert_eq!(Ratio::<i64>::from_f64(-10e200), None);
1391         assert_eq!(Ratio::<i64>::from_f64(10e200), None);
1392         assert_eq!(Ratio::<i64>::from_f64(f64::INFINITY), None);
1393         assert_eq!(Ratio::<i64>::from_f64(f64::NEG_INFINITY), None);
1394         assert_eq!(Ratio::<i64>::from_f64(f64::NAN), None);
1395         assert_eq!(Ratio::<i64>::from_f64(f64::EPSILON), Some(Ratio::new(1, 4503599627370496)));
1396         assert_eq!(Ratio::<i64>::from_f64(0.0), Some(Ratio::new(0, 1)));
1397         assert_eq!(Ratio::<i64>::from_f64(-0.0), Some(Ratio::new(0, 1)));
1398     }
1399 
1400     #[test]
test_cmp()1401     fn test_cmp() {
1402         assert!(_0 == _0 && _1 == _1);
1403         assert!(_0 != _1 && _1 != _0);
1404         assert!(_0 < _1 && !(_1 < _0));
1405         assert!(_1 > _0 && !(_0 > _1));
1406 
1407         assert!(_0 <= _0 && _1 <= _1);
1408         assert!(_0 <= _1 && !(_1 <= _0));
1409 
1410         assert!(_0 >= _0 && _1 >= _1);
1411         assert!(_1 >= _0 && !(_0 >= _1));
1412     }
1413 
1414     #[test]
test_cmp_overflow()1415     fn test_cmp_overflow() {
1416         use core::cmp::Ordering;
1417 
1418         // issue #7 example:
1419         let big = Ratio::new(128u8, 1);
1420         let small = big.recip();
1421         assert!(big > small);
1422 
1423         // try a few that are closer together
1424         // (some matching numer, some matching denom, some neither)
1425         let ratios = [
1426             Ratio::new(125_i8, 127_i8),
1427             Ratio::new(63_i8, 64_i8),
1428             Ratio::new(124_i8, 125_i8),
1429             Ratio::new(125_i8, 126_i8),
1430             Ratio::new(126_i8, 127_i8),
1431             Ratio::new(127_i8, 126_i8),
1432         ];
1433 
1434         fn check_cmp(a: Ratio<i8>, b: Ratio<i8>, ord: Ordering) {
1435             #[cfg(feature = "std")]
1436             println!("comparing {} and {}", a, b);
1437             assert_eq!(a.cmp(&b), ord);
1438             assert_eq!(b.cmp(&a), ord.reverse());
1439         }
1440 
1441         for (i, &a) in ratios.iter().enumerate() {
1442             check_cmp(a, a, Ordering::Equal);
1443             check_cmp(-a, a, Ordering::Less);
1444             for &b in &ratios[i + 1..] {
1445                 check_cmp(a, b, Ordering::Less);
1446                 check_cmp(-a, -b, Ordering::Greater);
1447                 check_cmp(a.recip(), b.recip(), Ordering::Greater);
1448                 check_cmp(-a.recip(), -b.recip(), Ordering::Less);
1449             }
1450         }
1451     }
1452 
1453     #[test]
test_to_integer()1454     fn test_to_integer() {
1455         assert_eq!(_0.to_integer(), 0);
1456         assert_eq!(_1.to_integer(), 1);
1457         assert_eq!(_2.to_integer(), 2);
1458         assert_eq!(_1_2.to_integer(), 0);
1459         assert_eq!(_3_2.to_integer(), 1);
1460         assert_eq!(_NEG1_2.to_integer(), 0);
1461     }
1462 
1463 
1464     #[test]
test_numer()1465     fn test_numer() {
1466         assert_eq!(_0.numer(), &0);
1467         assert_eq!(_1.numer(), &1);
1468         assert_eq!(_2.numer(), &2);
1469         assert_eq!(_1_2.numer(), &1);
1470         assert_eq!(_3_2.numer(), &3);
1471         assert_eq!(_NEG1_2.numer(), &(-1));
1472     }
1473     #[test]
test_denom()1474     fn test_denom() {
1475         assert_eq!(_0.denom(), &1);
1476         assert_eq!(_1.denom(), &1);
1477         assert_eq!(_2.denom(), &1);
1478         assert_eq!(_1_2.denom(), &2);
1479         assert_eq!(_3_2.denom(), &2);
1480         assert_eq!(_NEG1_2.denom(), &2);
1481     }
1482 
1483 
1484     #[test]
test_is_integer()1485     fn test_is_integer() {
1486         assert!(_0.is_integer());
1487         assert!(_1.is_integer());
1488         assert!(_2.is_integer());
1489         assert!(!_1_2.is_integer());
1490         assert!(!_3_2.is_integer());
1491         assert!(!_NEG1_2.is_integer());
1492     }
1493 
1494     #[test]
1495     #[cfg(feature = "std")]
test_show()1496     fn test_show() {
1497         use std::string::ToString;
1498         assert_eq!(format!("{}", _2), "2".to_string());
1499         assert_eq!(format!("{}", _1_2), "1/2".to_string());
1500         assert_eq!(format!("{}", _0), "0".to_string());
1501         assert_eq!(format!("{}", Ratio::from_integer(-2)), "-2".to_string());
1502     }
1503 
1504     mod arith {
1505         use super::{_0, _1, _2, _1_2, _3_2, _NEG1_2, to_big};
1506         use super::super::{Ratio, Rational};
1507         use traits::{CheckedAdd, CheckedSub, CheckedMul, CheckedDiv};
1508 
1509         #[test]
test_add()1510         fn test_add() {
1511             fn test(a: Rational, b: Rational, c: Rational) {
1512                 assert_eq!(a + b, c);
1513                 assert_eq!({ let mut x = a; x += b; x}, c);
1514                 assert_eq!(to_big(a) + to_big(b), to_big(c));
1515                 assert_eq!(a.checked_add(&b), Some(c));
1516                 assert_eq!(to_big(a).checked_add(&to_big(b)), Some(to_big(c)));
1517             }
1518            fn test_assign(a: Rational, b: isize, c: Rational) {
1519                 assert_eq!(a + b, c);
1520                 assert_eq!({ let mut x = a; x += b; x}, c);
1521             }
1522 
1523             test(_1, _1_2, _3_2);
1524             test(_1, _1, _2);
1525             test(_1_2, _3_2, _2);
1526             test(_1_2, _NEG1_2, _0);
1527             test_assign(_1_2, 1, _3_2);
1528         }
1529 
1530         #[test]
test_sub()1531         fn test_sub() {
1532             fn test(a: Rational, b: Rational, c: Rational) {
1533                 assert_eq!(a - b, c);
1534                 assert_eq!({ let mut x = a; x -= b; x}, c);
1535                 assert_eq!(to_big(a) - to_big(b), to_big(c));
1536                 assert_eq!(a.checked_sub(&b), Some(c));
1537                 assert_eq!(to_big(a).checked_sub(&to_big(b)), Some(to_big(c)));
1538             }
1539             fn test_assign(a: Rational, b: isize, c: Rational) {
1540                 assert_eq!(a - b, c);
1541                 assert_eq!({ let mut x = a; x -= b; x}, c);
1542             }
1543 
1544             test(_1, _1_2, _1_2);
1545             test(_3_2, _1_2, _1);
1546             test(_1, _NEG1_2, _3_2);
1547             test_assign(_1_2, 1, _NEG1_2);
1548         }
1549 
1550         #[test]
test_mul()1551         fn test_mul() {
1552             fn test(a: Rational, b: Rational, c: Rational) {
1553                 assert_eq!(a * b, c);
1554                 assert_eq!({ let mut x = a; x *= b; x}, c);
1555                 assert_eq!(to_big(a) * to_big(b), to_big(c));
1556                 assert_eq!(a.checked_mul(&b), Some(c));
1557                 assert_eq!(to_big(a).checked_mul(&to_big(b)), Some(to_big(c)));
1558             }
1559             fn test_assign(a: Rational, b: isize, c: Rational) {
1560                 assert_eq!(a * b, c);
1561                 assert_eq!({ let mut x = a; x *= b; x}, c);
1562             }
1563 
1564             test(_1, _1_2, _1_2);
1565             test(_1_2, _3_2, Ratio::new(3, 4));
1566             test(_1_2, _NEG1_2, Ratio::new(-1, 4));
1567             test_assign(_1_2, 2, _1);
1568         }
1569 
1570         #[test]
test_div()1571         fn test_div() {
1572             fn test(a: Rational, b: Rational, c: Rational) {
1573                 assert_eq!(a / b, c);
1574                 assert_eq!({ let mut x = a; x /= b; x}, c);
1575                 assert_eq!(to_big(a) / to_big(b), to_big(c));
1576                 assert_eq!(a.checked_div(&b), Some(c));
1577                 assert_eq!(to_big(a).checked_div(&to_big(b)), Some(to_big(c)));
1578             }
1579             fn test_assign(a: Rational, b: isize, c: Rational) {
1580                 assert_eq!(a / b, c);
1581                 assert_eq!({ let mut x = a; x /= b; x}, c);
1582             }
1583 
1584             test(_1, _1_2, _2);
1585             test(_3_2, _1_2, _1 + _2);
1586             test(_1, _NEG1_2, _NEG1_2 + _NEG1_2 + _NEG1_2 + _NEG1_2);
1587             test_assign(_1, 2, _1_2);
1588         }
1589 
1590         #[test]
test_rem()1591         fn test_rem() {
1592             fn test(a: Rational, b: Rational, c: Rational) {
1593                 assert_eq!(a % b, c);
1594                 assert_eq!({ let mut x = a; x %= b; x}, c);
1595                 assert_eq!(to_big(a) % to_big(b), to_big(c))
1596             }
1597             fn test_assign(a: Rational, b: isize, c: Rational) {
1598                 assert_eq!(a % b, c);
1599                 assert_eq!({ let mut x = a; x %= b; x}, c);
1600             }
1601 
1602             test(_3_2, _1, _1_2);
1603             test(_2, _NEG1_2, _0);
1604             test(_1_2, _2, _1_2);
1605             test_assign(_3_2, 1, _1_2);
1606         }
1607 
1608         #[test]
test_neg()1609         fn test_neg() {
1610             fn test(a: Rational, b: Rational) {
1611                 assert_eq!(-a, b);
1612                 assert_eq!(-to_big(a), to_big(b))
1613             }
1614 
1615             test(_0, _0);
1616             test(_1_2, _NEG1_2);
1617             test(-_1, _1);
1618         }
1619         #[test]
test_zero()1620         fn test_zero() {
1621             assert_eq!(_0 + _0, _0);
1622             assert_eq!(_0 * _0, _0);
1623             assert_eq!(_0 * _1, _0);
1624             assert_eq!(_0 / _NEG1_2, _0);
1625             assert_eq!(_0 - _0, _0);
1626         }
1627         #[test]
1628         #[should_panic]
test_div_0()1629         fn test_div_0() {
1630             let _a = _1 / _0;
1631         }
1632 
1633         #[test]
test_checked_failures()1634         fn test_checked_failures() {
1635             let big = Ratio::new(128u8, 1);
1636             let small = Ratio::new(1, 128u8);
1637             assert_eq!(big.checked_add(&big), None);
1638             assert_eq!(small.checked_sub(&big), None);
1639             assert_eq!(big.checked_mul(&big), None);
1640             assert_eq!(small.checked_div(&big), None);
1641             assert_eq!(_1.checked_div(&_0), None);
1642         }
1643     }
1644 
1645     #[test]
test_round()1646     fn test_round() {
1647         assert_eq!(_1_3.ceil(), _1);
1648         assert_eq!(_1_3.floor(), _0);
1649         assert_eq!(_1_3.round(), _0);
1650         assert_eq!(_1_3.trunc(), _0);
1651 
1652         assert_eq!(_NEG1_3.ceil(), _0);
1653         assert_eq!(_NEG1_3.floor(), -_1);
1654         assert_eq!(_NEG1_3.round(), _0);
1655         assert_eq!(_NEG1_3.trunc(), _0);
1656 
1657         assert_eq!(_2_3.ceil(), _1);
1658         assert_eq!(_2_3.floor(), _0);
1659         assert_eq!(_2_3.round(), _1);
1660         assert_eq!(_2_3.trunc(), _0);
1661 
1662         assert_eq!(_NEG2_3.ceil(), _0);
1663         assert_eq!(_NEG2_3.floor(), -_1);
1664         assert_eq!(_NEG2_3.round(), -_1);
1665         assert_eq!(_NEG2_3.trunc(), _0);
1666 
1667         assert_eq!(_1_2.ceil(), _1);
1668         assert_eq!(_1_2.floor(), _0);
1669         assert_eq!(_1_2.round(), _1);
1670         assert_eq!(_1_2.trunc(), _0);
1671 
1672         assert_eq!(_NEG1_2.ceil(), _0);
1673         assert_eq!(_NEG1_2.floor(), -_1);
1674         assert_eq!(_NEG1_2.round(), -_1);
1675         assert_eq!(_NEG1_2.trunc(), _0);
1676 
1677         assert_eq!(_1.ceil(), _1);
1678         assert_eq!(_1.floor(), _1);
1679         assert_eq!(_1.round(), _1);
1680         assert_eq!(_1.trunc(), _1);
1681 
1682         // Overflow checks
1683 
1684         let _neg1 = Ratio::from_integer(-1);
1685         let _large_rat1 = Ratio::new(i32::MAX, i32::MAX - 1);
1686         let _large_rat2 = Ratio::new(i32::MAX - 1, i32::MAX);
1687         let _large_rat3 = Ratio::new(i32::MIN + 2, i32::MIN + 1);
1688         let _large_rat4 = Ratio::new(i32::MIN + 1, i32::MIN + 2);
1689         let _large_rat5 = Ratio::new(i32::MIN + 2, i32::MAX);
1690         let _large_rat6 = Ratio::new(i32::MAX, i32::MIN + 2);
1691         let _large_rat7 = Ratio::new(1, i32::MIN + 1);
1692         let _large_rat8 = Ratio::new(1, i32::MAX);
1693 
1694         assert_eq!(_large_rat1.round(), One::one());
1695         assert_eq!(_large_rat2.round(), One::one());
1696         assert_eq!(_large_rat3.round(), One::one());
1697         assert_eq!(_large_rat4.round(), One::one());
1698         assert_eq!(_large_rat5.round(), _neg1);
1699         assert_eq!(_large_rat6.round(), _neg1);
1700         assert_eq!(_large_rat7.round(), Zero::zero());
1701         assert_eq!(_large_rat8.round(), Zero::zero());
1702     }
1703 
1704     #[test]
test_fract()1705     fn test_fract() {
1706         assert_eq!(_1.fract(), _0);
1707         assert_eq!(_NEG1_2.fract(), _NEG1_2);
1708         assert_eq!(_1_2.fract(), _1_2);
1709         assert_eq!(_3_2.fract(), _1_2);
1710     }
1711 
1712     #[test]
test_recip()1713     fn test_recip() {
1714         assert_eq!(_1 * _1.recip(), _1);
1715         assert_eq!(_2 * _2.recip(), _1);
1716         assert_eq!(_1_2 * _1_2.recip(), _1);
1717         assert_eq!(_3_2 * _3_2.recip(), _1);
1718         assert_eq!(_NEG1_2 * _NEG1_2.recip(), _1);
1719 
1720         assert_eq!(_3_2.recip(), _2_3);
1721         assert_eq!(_NEG1_2.recip(), _NEG2);
1722         assert_eq!(_NEG1_2.recip().denom(), &1);
1723     }
1724 
1725     #[test]
1726     #[should_panic(expected = "== 0")]
test_recip_fail()1727     fn test_recip_fail() {
1728         let _a = Ratio::new(0, 1).recip();
1729     }
1730 
1731     #[test]
test_pow()1732     fn test_pow() {
1733         fn test(r: Rational, e: i32, expected: Rational) {
1734             assert_eq!(r.pow(e), expected);
1735             assert_eq!(Pow::pow(r, e), expected);
1736             assert_eq!(Pow::pow(r, &e), expected);
1737             assert_eq!(Pow::pow(&r, e), expected);
1738             assert_eq!(Pow::pow(&r, &e), expected);
1739         }
1740 
1741         test(_1_2, 2, Ratio::new(1, 4));
1742         test(_1_2, -2, Ratio::new(4, 1));
1743         test(_1, 1, _1);
1744         test(_1, i32::MAX, _1);
1745         test(_1, i32::MIN, _1);
1746         test(_NEG1_2, 2, _1_2.pow(2i32));
1747         test(_NEG1_2, 3, -_1_2.pow(3i32));
1748         test(_3_2, 0, _1);
1749         test(_3_2, -1, _3_2.recip());
1750         test(_3_2, 3, Ratio::new(27, 8));
1751     }
1752 
1753     #[test]
1754     #[cfg(feature = "std")]
test_to_from_str()1755     fn test_to_from_str() {
1756         use std::string::{String, ToString};
1757         fn test(r: Rational, s: String) {
1758             assert_eq!(FromStr::from_str(&s), Ok(r));
1759             assert_eq!(r.to_string(), s);
1760         }
1761         test(_1, "1".to_string());
1762         test(_0, "0".to_string());
1763         test(_1_2, "1/2".to_string());
1764         test(_3_2, "3/2".to_string());
1765         test(_2, "2".to_string());
1766         test(_NEG1_2, "-1/2".to_string());
1767     }
1768     #[test]
test_from_str_fail()1769     fn test_from_str_fail() {
1770         fn test(s: &str) {
1771             let rational: Result<Rational, _> = FromStr::from_str(s);
1772             assert!(rational.is_err());
1773         }
1774 
1775         let xs = ["0 /1", "abc", "", "1/", "--1/2", "3/2/1", "1/0"];
1776         for &s in xs.iter() {
1777             test(s);
1778         }
1779     }
1780 
1781     #[cfg(feature = "bigint")]
1782     #[test]
test_from_float()1783     fn test_from_float() {
1784         use traits::float::FloatCore;
1785         fn test<T: FloatCore>(given: T, (numer, denom): (&str, &str)) {
1786             let ratio: BigRational = Ratio::from_float(given).unwrap();
1787             assert_eq!(ratio,
1788                        Ratio::new(FromStr::from_str(numer).unwrap(),
1789                                   FromStr::from_str(denom).unwrap()));
1790         }
1791 
1792         // f32
1793         test(3.14159265359f32, ("13176795", "4194304"));
1794         test(2f32.powf(100.), ("1267650600228229401496703205376", "1"));
1795         test(-2f32.powf(100.), ("-1267650600228229401496703205376", "1"));
1796         test(1.0 / 2f32.powf(100.),
1797              ("1", "1267650600228229401496703205376"));
1798         test(684729.48391f32, ("1369459", "2"));
1799         test(-8573.5918555f32, ("-4389679", "512"));
1800 
1801         // f64
1802         test(3.14159265359f64, ("3537118876014453", "1125899906842624"));
1803         test(2f64.powf(100.), ("1267650600228229401496703205376", "1"));
1804         test(-2f64.powf(100.), ("-1267650600228229401496703205376", "1"));
1805         test(684729.48391f64, ("367611342500051", "536870912"));
1806         test(-8573.5918555f64, ("-4713381968463931", "549755813888"));
1807         test(1.0 / 2f64.powf(100.),
1808              ("1", "1267650600228229401496703205376"));
1809     }
1810 
1811     #[cfg(feature = "bigint")]
1812     #[test]
test_from_float_fail()1813     fn test_from_float_fail() {
1814         use core::{f32, f64};
1815 
1816         assert_eq!(Ratio::from_float(f32::NAN), None);
1817         assert_eq!(Ratio::from_float(f32::INFINITY), None);
1818         assert_eq!(Ratio::from_float(f32::NEG_INFINITY), None);
1819         assert_eq!(Ratio::from_float(f64::NAN), None);
1820         assert_eq!(Ratio::from_float(f64::INFINITY), None);
1821         assert_eq!(Ratio::from_float(f64::NEG_INFINITY), None);
1822     }
1823 
1824     #[test]
test_signed()1825     fn test_signed() {
1826         assert_eq!(_NEG1_2.abs(), _1_2);
1827         assert_eq!(_3_2.abs_sub(&_1_2), _1);
1828         assert_eq!(_1_2.abs_sub(&_3_2), Zero::zero());
1829         assert_eq!(_1_2.signum(), One::one());
1830         assert_eq!(_NEG1_2.signum(), -<Ratio<isize>>::one());
1831         assert_eq!(_0.signum(), Zero::zero());
1832         assert!(_NEG1_2.is_negative());
1833         assert!(_1_NEG2.is_negative());
1834         assert!(!_NEG1_2.is_positive());
1835         assert!(!_1_NEG2.is_positive());
1836         assert!(_1_2.is_positive());
1837         assert!(_NEG1_NEG2.is_positive());
1838         assert!(!_1_2.is_negative());
1839         assert!(!_NEG1_NEG2.is_negative());
1840         assert!(!_0.is_positive());
1841         assert!(!_0.is_negative());
1842     }
1843 
1844     #[test]
1845     #[cfg(feature = "std")]
test_hash()1846     fn test_hash() {
1847         assert!(::hash(&_0) != ::hash(&_1));
1848         assert!(::hash(&_0) != ::hash(&_3_2));
1849 
1850         // a == b -> hash(a) == hash(b)
1851         let a = Rational::new_raw(4, 2);
1852         let b = Rational::new_raw(6, 3);
1853         assert_eq!(a, b);
1854         assert_eq!(::hash(&a), ::hash(&b));
1855 
1856         let a = Rational::new_raw(123456789, 1000);
1857         let b = Rational::new_raw(123456789 * 5, 5000);
1858         assert_eq!(a, b);
1859         assert_eq!(::hash(&a), ::hash(&b));
1860     }
1861 
1862     #[test]
test_into_pair()1863     fn test_into_pair() {
1864         assert_eq! ((0, 1), _0.into());
1865         assert_eq! ((-2, 1), _NEG2.into());
1866         assert_eq! ((1, -2), _1_NEG2.into());
1867     }
1868 
1869     #[test]
test_from_pair()1870     fn test_from_pair() {
1871         assert_eq! (_0, Ratio::from ((0, 1)));
1872         assert_eq! (_1, Ratio::from ((1, 1)));
1873         assert_eq! (_NEG2, Ratio::from ((-2, 1)));
1874         assert_eq! (_1_NEG2, Ratio::from ((1, -2)));
1875     }
1876 
1877     #[test]
ratio_iter_sum()1878     fn ratio_iter_sum() {
1879         // generic function to assure the iter method can be called
1880         // for any Iterator with Item = Ratio<impl Integer> or Ratio<&impl Integer>
1881         fn iter_sums<T: Integer + Clone>(slice: &[Ratio<T>]) -> [Ratio<T>; 3] {
1882             let mut manual_sum = Ratio::new(T::zero(), T::one());
1883             for ratio in slice {
1884                 manual_sum = manual_sum + ratio;
1885             }
1886             [
1887                 manual_sum,
1888                 slice.iter().sum(),
1889                 slice.iter().cloned().sum()
1890             ]
1891         }
1892         // collect into array so test works on no_std
1893         let mut nums = [Ratio::new(0,1); 1000];
1894         for (i, r) in (0..1000).map(|n| Ratio::new(n, 500)).enumerate() {
1895             nums[i] = r;
1896         }
1897         let sums = iter_sums(&nums[..]);
1898         assert_eq!(sums[0], sums[1]);
1899         assert_eq!(sums[0], sums[2]);
1900     }
1901 
1902     #[test]
ratio_iter_product()1903     fn ratio_iter_product() {
1904         // generic function to assure the iter method can be called
1905         // for any Iterator with Item = Ratio<impl Integer> or Ratio<&impl Integer>
1906         fn iter_products<T: Integer + Clone>(slice: &[Ratio<T>]) -> [Ratio<T>; 3] {
1907             let mut manual_prod = Ratio::new(T::one(), T::one());
1908             for ratio in slice {
1909                 manual_prod = manual_prod * ratio;
1910             }
1911             [
1912                 manual_prod,
1913                 slice.iter().product(),
1914                 slice.iter().cloned().product()
1915             ]
1916         }
1917 
1918         // collect into array so test works on no_std
1919         let mut nums = [Ratio::new(0,1); 1000];
1920         for (i, r) in (0..1000).map(|n| Ratio::new(n, 500)).enumerate() {
1921             nums[i] = r;
1922         }
1923         let products = iter_products(&nums[..]);
1924         assert_eq!(products[0], products[1]);
1925         assert_eq!(products[0], products[2]);
1926     }
1927 }
1928