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 #![no_std]
19 
20 #[cfg(feature = "bigint")]
21 extern crate num_bigint as bigint;
22 #[cfg(feature = "serde")]
23 extern crate serde;
24 
25 extern crate num_integer as integer;
26 extern crate num_traits as traits;
27 
28 #[cfg(feature = "std")]
29 #[cfg_attr(test, macro_use)]
30 extern crate std;
31 
32 use core::cmp;
33 use core::fmt;
34 use core::hash::{Hash, Hasher};
35 use core::ops::{Add, Div, Mul, Neg, Rem, Sub};
36 use core::str::FromStr;
37 #[cfg(feature = "std")]
38 use std::error::Error;
39 
40 #[cfg(feature = "bigint")]
41 use bigint::{BigInt, BigUint, Sign};
42 
43 use integer::Integer;
44 use traits::float::FloatCore;
45 use traits::{
46     Bounded, CheckedAdd, CheckedDiv, CheckedMul, CheckedSub, FromPrimitive, Inv, Num, NumCast, One,
47     Pow, Signed, Zero,
48 };
49 
50 /// Represents the ratio between two numbers.
51 #[derive(Copy, Clone, Debug)]
52 #[allow(missing_docs)]
53 pub struct Ratio<T> {
54     /// Numerator.
55     numer: T,
56     /// Denominator.
57     denom: T,
58 }
59 
60 /// Alias for a `Ratio` of machine-sized integers.
61 pub type Rational = Ratio<isize>;
62 /// Alias for a `Ratio` of 32-bit-sized integers.
63 pub type Rational32 = Ratio<i32>;
64 /// Alias for a `Ratio` of 64-bit-sized integers.
65 pub type Rational64 = Ratio<i64>;
66 
67 #[cfg(feature = "bigint")]
68 /// Alias for arbitrary precision rationals.
69 pub type BigRational = Ratio<BigInt>;
70 
71 macro_rules! maybe_const {
72     ($( $(#[$attr:meta])* pub fn $name:ident $args:tt -> $ret:ty $body:block )*) => {$(
73         #[cfg(has_const_fn)]
74         $(#[$attr])* pub const fn $name $args -> $ret $body
75 
76         #[cfg(not(has_const_fn))]
77         $(#[$attr])* pub fn $name $args -> $ret $body
78     )*}
79 }
80 
81 /// These method are `const` for Rust 1.31 and later.
82 impl<T> Ratio<T> {
83     maybe_const! {
84         /// Creates a `Ratio` without checking for `denom == 0` or reducing.
85         #[inline]
86         pub fn new_raw(numer: T, denom: T) -> Ratio<T> {
87             Ratio {
88                 numer: numer,
89                 denom: denom,
90             }
91         }
92 
93         /// Gets an immutable reference to the numerator.
94         #[inline]
95         pub fn numer(&self) -> &T {
96             &self.numer
97         }
98 
99         /// Gets an immutable reference to the denominator.
100         #[inline]
101         pub fn denom(&self) -> &T {
102             &self.denom
103         }
104     }
105 }
106 
107 impl<T: Clone + Integer> Ratio<T> {
108     /// Creates a new `Ratio`. Fails if `denom` is zero.
109     #[inline]
new(numer: T, denom: T) -> Ratio<T>110     pub fn new(numer: T, denom: T) -> Ratio<T> {
111         let mut ret = Ratio::new_raw(numer, denom);
112         ret.reduce();
113         ret
114     }
115 
116     /// Creates a `Ratio` representing the integer `t`.
117     #[inline]
from_integer(t: T) -> Ratio<T>118     pub fn from_integer(t: T) -> Ratio<T> {
119         Ratio::new_raw(t, One::one())
120     }
121 
122     /// Converts to an integer, rounding towards zero.
123     #[inline]
to_integer(&self) -> T124     pub fn to_integer(&self) -> T {
125         self.trunc().numer
126     }
127 
128     /// Returns true if the rational number is an integer (denominator is 1).
129     #[inline]
is_integer(&self) -> bool130     pub fn is_integer(&self) -> bool {
131         self.denom.is_one()
132     }
133 
134     /// Puts self into lowest terms, with denom > 0.
reduce(&mut self)135     fn reduce(&mut self) {
136         if self.denom.is_zero() {
137             panic!("denominator == 0");
138         }
139         if self.numer.is_zero() {
140             self.denom.set_one();
141             return;
142         }
143         if self.numer == self.denom {
144             self.set_one();
145             return;
146         }
147         let g: T = self.numer.gcd(&self.denom);
148 
149         // FIXME(#5992): assignment operator overloads
150         // self.numer /= g;
151         // T: Clone + Integer != T: Clone + NumAssign
152         self.numer = self.numer.clone() / g.clone();
153         // FIXME(#5992): assignment operator overloads
154         // self.denom /= g;
155         // T: Clone + Integer != T: Clone + NumAssign
156         self.denom = self.denom.clone() / g;
157 
158         // keep denom positive!
159         if self.denom < T::zero() {
160             self.numer = T::zero() - self.numer.clone();
161             self.denom = T::zero() - self.denom.clone();
162         }
163     }
164 
165     /// Returns a reduced copy of self.
166     ///
167     /// In general, it is not necessary to use this method, as the only
168     /// method of procuring a non-reduced fraction is through `new_raw`.
reduced(&self) -> Ratio<T>169     pub fn reduced(&self) -> Ratio<T> {
170         let mut ret = self.clone();
171         ret.reduce();
172         ret
173     }
174 
175     /// Returns the reciprocal.
176     ///
177     /// Fails if the `Ratio` is zero.
178     #[inline]
recip(&self) -> Ratio<T>179     pub fn recip(&self) -> Ratio<T> {
180         match self.numer.cmp(&T::zero()) {
181             cmp::Ordering::Equal => panic!("numerator == 0"),
182             cmp::Ordering::Greater => Ratio::new_raw(self.denom.clone(), self.numer.clone()),
183             cmp::Ordering::Less => Ratio::new_raw(
184                 T::zero() - self.denom.clone(),
185                 T::zero() - self.numer.clone(),
186             ),
187         }
188     }
189 
190     /// Rounds towards minus infinity.
191     #[inline]
floor(&self) -> Ratio<T>192     pub fn floor(&self) -> Ratio<T> {
193         if *self < Zero::zero() {
194             let one: T = One::one();
195             Ratio::from_integer(
196                 (self.numer.clone() - self.denom.clone() + one) / self.denom.clone(),
197             )
198         } else {
199             Ratio::from_integer(self.numer.clone() / self.denom.clone())
200         }
201     }
202 
203     /// Rounds towards plus infinity.
204     #[inline]
ceil(&self) -> Ratio<T>205     pub fn ceil(&self) -> Ratio<T> {
206         if *self < Zero::zero() {
207             Ratio::from_integer(self.numer.clone() / self.denom.clone())
208         } else {
209             let one: T = One::one();
210             Ratio::from_integer(
211                 (self.numer.clone() + self.denom.clone() - one) / self.denom.clone(),
212             )
213         }
214     }
215 
216     /// Rounds to the nearest integer. Rounds half-way cases away from zero.
217     #[inline]
round(&self) -> Ratio<T>218     pub fn round(&self) -> Ratio<T> {
219         let zero: Ratio<T> = Zero::zero();
220         let one: T = One::one();
221         let two: T = one.clone() + one.clone();
222 
223         // Find unsigned fractional part of rational number
224         let mut fractional = self.fract();
225         if fractional < zero {
226             fractional = zero - fractional
227         };
228 
229         // The algorithm compares the unsigned fractional part with 1/2, that
230         // is, a/b >= 1/2, or a >= b/2. For odd denominators, we use
231         // a >= (b/2)+1. This avoids overflow issues.
232         let half_or_larger = if fractional.denom().is_even() {
233             *fractional.numer() >= fractional.denom().clone() / two.clone()
234         } else {
235             *fractional.numer() >= (fractional.denom().clone() / two.clone()) + one.clone()
236         };
237 
238         if half_or_larger {
239             let one: Ratio<T> = One::one();
240             if *self >= Zero::zero() {
241                 self.trunc() + one
242             } else {
243                 self.trunc() - one
244             }
245         } else {
246             self.trunc()
247         }
248     }
249 
250     /// Rounds towards zero.
251     #[inline]
trunc(&self) -> Ratio<T>252     pub fn trunc(&self) -> Ratio<T> {
253         Ratio::from_integer(self.numer.clone() / self.denom.clone())
254     }
255 
256     /// Returns the fractional part of a number, with division rounded towards zero.
257     ///
258     /// Satisfies `self == self.trunc() + self.fract()`.
259     #[inline]
fract(&self) -> Ratio<T>260     pub fn fract(&self) -> Ratio<T> {
261         Ratio::new_raw(self.numer.clone() % self.denom.clone(), self.denom.clone())
262     }
263 }
264 
265 impl<T: Clone + Integer + Pow<u32, Output = T>> Ratio<T> {
266     /// Raises the `Ratio` to the power of an exponent.
267     #[inline]
pow(&self, expon: i32) -> Ratio<T>268     pub fn pow(&self, expon: i32) -> Ratio<T> {
269         Pow::pow(self, expon)
270     }
271 }
272 
273 macro_rules! pow_impl {
274     ($exp:ty) => {
275         pow_impl!($exp, $exp);
276     };
277     ($exp:ty, $unsigned:ty) => {
278         impl<T: Clone + Integer + Pow<$unsigned, Output = T>> Pow<$exp> for Ratio<T> {
279             type Output = Ratio<T>;
280             #[inline]
281             fn pow(self, expon: $exp) -> Ratio<T> {
282                 match expon.cmp(&0) {
283                     cmp::Ordering::Equal => One::one(),
284                     cmp::Ordering::Less => {
285                         let expon = expon.wrapping_abs() as $unsigned;
286                         Ratio::new_raw(Pow::pow(self.denom, expon), Pow::pow(self.numer, expon))
287                     }
288                     cmp::Ordering::Greater => Ratio::new_raw(
289                         Pow::pow(self.numer, expon as $unsigned),
290                         Pow::pow(self.denom, expon as $unsigned),
291                     ),
292                 }
293             }
294         }
295         impl<'a, T: Clone + Integer + Pow<$unsigned, Output = T>> Pow<$exp> for &'a Ratio<T> {
296             type Output = Ratio<T>;
297             #[inline]
298             fn pow(self, expon: $exp) -> Ratio<T> {
299                 Pow::pow(self.clone(), expon)
300             }
301         }
302         impl<'a, T: Clone + Integer + Pow<$unsigned, Output = T>> Pow<&'a $exp> for Ratio<T> {
303             type Output = Ratio<T>;
304             #[inline]
305             fn pow(self, expon: &'a $exp) -> Ratio<T> {
306                 Pow::pow(self, *expon)
307             }
308         }
309         impl<'a, 'b, T: Clone + Integer + Pow<$unsigned, Output = T>> Pow<&'a $exp>
310             for &'b Ratio<T>
311         {
312             type Output = Ratio<T>;
313             #[inline]
314             fn pow(self, expon: &'a $exp) -> Ratio<T> {
315                 Pow::pow(self.clone(), *expon)
316             }
317         }
318     };
319 }
320 
321 // this is solely to make `pow_impl!` work
322 trait WrappingAbs: Sized {
wrapping_abs(self) -> Self323     fn wrapping_abs(self) -> Self {
324         self
325     }
326 }
327 impl WrappingAbs for u8 {}
328 impl WrappingAbs for u16 {}
329 impl WrappingAbs for u32 {}
330 impl WrappingAbs for u64 {}
331 impl WrappingAbs for usize {}
332 
333 pow_impl!(i8, u8);
334 pow_impl!(i16, u16);
335 pow_impl!(i32, u32);
336 pow_impl!(i64, u64);
337 pow_impl!(isize, usize);
338 pow_impl!(u8);
339 pow_impl!(u16);
340 pow_impl!(u32);
341 pow_impl!(u64);
342 pow_impl!(usize);
343 
344 // TODO: pow_impl!(BigUint) and pow_impl!(BigInt, BigUint)
345 
346 #[cfg(feature = "bigint")]
347 impl Ratio<BigInt> {
348     /// Converts a float into a rational number.
from_float<T: FloatCore>(f: T) -> Option<BigRational>349     pub fn from_float<T: FloatCore>(f: T) -> Option<BigRational> {
350         if !f.is_finite() {
351             return None;
352         }
353         let (mantissa, exponent, sign) = f.integer_decode();
354         let bigint_sign = if sign == 1 { Sign::Plus } else { Sign::Minus };
355         if exponent < 0 {
356             let one: BigInt = One::one();
357             let denom: BigInt = one << ((-exponent) as usize);
358             let numer: BigUint = FromPrimitive::from_u64(mantissa).unwrap();
359             Some(Ratio::new(BigInt::from_biguint(bigint_sign, numer), denom))
360         } else {
361             let mut numer: BigUint = FromPrimitive::from_u64(mantissa).unwrap();
362             numer = numer << (exponent as usize);
363             Some(Ratio::from_integer(BigInt::from_biguint(
364                 bigint_sign,
365                 numer,
366             )))
367         }
368     }
369 }
370 
371 // From integer
372 impl<T> From<T> for Ratio<T>
373 where
374     T: Clone + Integer,
375 {
from(x: T) -> Ratio<T>376     fn from(x: T) -> Ratio<T> {
377         Ratio::from_integer(x)
378     }
379 }
380 
381 // From pair (through the `new` constructor)
382 impl<T> From<(T, T)> for Ratio<T>
383 where
384     T: Clone + Integer,
385 {
from(pair: (T, T)) -> Ratio<T>386     fn from(pair: (T, T)) -> Ratio<T> {
387         Ratio::new(pair.0, pair.1)
388     }
389 }
390 
391 // Comparisons
392 
393 // Mathematically, comparing a/b and c/d is the same as comparing a*d and b*c, but it's very easy
394 // for those multiplications to overflow fixed-size integers, so we need to take care.
395 
396 impl<T: Clone + Integer> Ord for Ratio<T> {
397     #[inline]
cmp(&self, other: &Self) -> cmp::Ordering398     fn cmp(&self, other: &Self) -> cmp::Ordering {
399         // With equal denominators, the numerators can be directly compared
400         if self.denom == other.denom {
401             let ord = self.numer.cmp(&other.numer);
402             return if self.denom < T::zero() {
403                 ord.reverse()
404             } else {
405                 ord
406             };
407         }
408 
409         // With equal numerators, the denominators can be inversely compared
410         if self.numer == other.numer {
411             if self.numer.is_zero() {
412                 return cmp::Ordering::Equal;
413             }
414             let ord = self.denom.cmp(&other.denom);
415             return if self.numer < T::zero() {
416                 ord
417             } else {
418                 ord.reverse()
419             };
420         }
421 
422         // Unfortunately, we don't have CheckedMul to try.  That could sometimes avoid all the
423         // division below, or even always avoid it for BigInt and BigUint.
424         // FIXME- future breaking change to add Checked* to Integer?
425 
426         // Compare as floored integers and remainders
427         let (self_int, self_rem) = self.numer.div_mod_floor(&self.denom);
428         let (other_int, other_rem) = other.numer.div_mod_floor(&other.denom);
429         match self_int.cmp(&other_int) {
430             cmp::Ordering::Greater => cmp::Ordering::Greater,
431             cmp::Ordering::Less => cmp::Ordering::Less,
432             cmp::Ordering::Equal => {
433                 match (self_rem.is_zero(), other_rem.is_zero()) {
434                     (true, true) => cmp::Ordering::Equal,
435                     (true, false) => cmp::Ordering::Less,
436                     (false, true) => cmp::Ordering::Greater,
437                     (false, false) => {
438                         // Compare the reciprocals of the remaining fractions in reverse
439                         let self_recip = Ratio::new_raw(self.denom.clone(), self_rem);
440                         let other_recip = Ratio::new_raw(other.denom.clone(), other_rem);
441                         self_recip.cmp(&other_recip).reverse()
442                     }
443                 }
444             }
445         }
446     }
447 }
448 
449 impl<T: Clone + Integer> PartialOrd for Ratio<T> {
450     #[inline]
partial_cmp(&self, other: &Self) -> Option<cmp::Ordering>451     fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
452         Some(self.cmp(other))
453     }
454 }
455 
456 impl<T: Clone + Integer> PartialEq for Ratio<T> {
457     #[inline]
eq(&self, other: &Self) -> bool458     fn eq(&self, other: &Self) -> bool {
459         self.cmp(other) == cmp::Ordering::Equal
460     }
461 }
462 
463 impl<T: Clone + Integer> Eq for Ratio<T> {}
464 
465 // NB: We can't just `#[derive(Hash)]`, because it needs to agree
466 // with `Eq` even for non-reduced ratios.
467 impl<T: Clone + Integer + Hash> Hash for Ratio<T> {
hash<H: Hasher>(&self, state: &mut H)468     fn hash<H: Hasher>(&self, state: &mut H) {
469         recurse(&self.numer, &self.denom, state);
470 
471         fn recurse<T: Integer + Hash, H: Hasher>(numer: &T, denom: &T, state: &mut H) {
472             if !denom.is_zero() {
473                 let (int, rem) = numer.div_mod_floor(denom);
474                 int.hash(state);
475                 recurse(denom, &rem, state);
476             } else {
477                 denom.hash(state);
478             }
479         }
480     }
481 }
482 
483 mod iter_sum_product {
484     use core::iter::{Product, Sum};
485     use integer::Integer;
486     use traits::{One, Zero};
487     use Ratio;
488 
489     impl<T: Integer + Clone> Sum for Ratio<T> {
sum<I>(iter: I) -> Self where I: Iterator<Item = Ratio<T>>,490         fn sum<I>(iter: I) -> Self
491         where
492             I: Iterator<Item = Ratio<T>>,
493         {
494             iter.fold(Self::zero(), |sum, num| sum + num)
495         }
496     }
497 
498     impl<'a, T: Integer + Clone> Sum<&'a Ratio<T>> for Ratio<T> {
sum<I>(iter: I) -> Self where I: Iterator<Item = &'a Ratio<T>>,499         fn sum<I>(iter: I) -> Self
500         where
501             I: Iterator<Item = &'a Ratio<T>>,
502         {
503             iter.fold(Self::zero(), |sum, num| sum + num)
504         }
505     }
506 
507     impl<T: Integer + Clone> Product for Ratio<T> {
product<I>(iter: I) -> Self where I: Iterator<Item = Ratio<T>>,508         fn product<I>(iter: I) -> Self
509         where
510             I: Iterator<Item = Ratio<T>>,
511         {
512             iter.fold(Self::one(), |prod, num| prod * num)
513         }
514     }
515 
516     impl<'a, T: Integer + Clone> Product<&'a Ratio<T>> for Ratio<T> {
product<I>(iter: I) -> Self where I: Iterator<Item = &'a Ratio<T>>,517         fn product<I>(iter: I) -> Self
518         where
519             I: Iterator<Item = &'a Ratio<T>>,
520         {
521             iter.fold(Self::one(), |prod, num| prod * num)
522         }
523     }
524 }
525 
526 mod opassign {
527     use core::ops::{AddAssign, DivAssign, MulAssign, RemAssign, SubAssign};
528 
529     use integer::Integer;
530     use traits::NumAssign;
531     use Ratio;
532 
533     impl<T: Clone + Integer + NumAssign> AddAssign for Ratio<T> {
add_assign(&mut self, other: Ratio<T>)534         fn add_assign(&mut self, other: Ratio<T>) {
535             if self.denom == other.denom {
536                 self.numer += other.numer
537             } else {
538                 let lcm = self.denom.lcm(&other.denom);
539                 let lhs_numer = self.numer.clone() * (lcm.clone() / self.denom.clone());
540                 let rhs_numer = other.numer * (lcm.clone() / other.denom);
541                 self.numer = lhs_numer + rhs_numer;
542                 self.denom = lcm;
543             }
544             self.reduce();
545         }
546     }
547 
548     // (a/b) / (c/d) = (a/gcd_ac)*(d/gcd_bd) / ((c/gcd_ac)*(b/gcd_bd))
549     impl<T: Clone + Integer + NumAssign> DivAssign for Ratio<T> {
div_assign(&mut self, other: Ratio<T>)550         fn div_assign(&mut self, other: Ratio<T>) {
551             let gcd_ac = self.numer.gcd(&other.numer);
552             let gcd_bd = self.denom.gcd(&other.denom);
553             self.numer /= gcd_ac.clone();
554             self.numer *= other.denom / gcd_bd.clone();
555             self.denom /= gcd_bd;
556             self.denom *= other.numer / gcd_ac;
557             self.reduce(); //TODO: remove this line. see #8.
558         }
559     }
560 
561     // a/b * c/d = (a/gcd_ad)*(c/gcd_bc) / ((d/gcd_ad)*(b/gcd_bc))
562     impl<T: Clone + Integer + NumAssign> MulAssign for Ratio<T> {
mul_assign(&mut self, other: Ratio<T>)563         fn mul_assign(&mut self, other: Ratio<T>) {
564             let gcd_ad = self.numer.gcd(&other.denom);
565             let gcd_bc = self.denom.gcd(&other.numer);
566             self.numer /= gcd_ad.clone();
567             self.numer *= other.numer / gcd_bc.clone();
568             self.denom /= gcd_bc;
569             self.denom *= other.denom / gcd_ad;
570             self.reduce(); //TODO: remove this line. see #8.
571         }
572     }
573 
574     impl<T: Clone + Integer + NumAssign> RemAssign for Ratio<T> {
rem_assign(&mut self, other: Ratio<T>)575         fn rem_assign(&mut self, other: Ratio<T>) {
576             if self.denom == other.denom {
577                 self.numer %= other.numer
578             } else {
579                 let lcm = self.denom.lcm(&other.denom);
580                 let lhs_numer = self.numer.clone() * (lcm.clone() / self.denom.clone());
581                 let rhs_numer = other.numer * (lcm.clone() / other.denom);
582                 self.numer = lhs_numer % rhs_numer;
583                 self.denom = lcm;
584             }
585             self.reduce();
586         }
587     }
588 
589     impl<T: Clone + Integer + NumAssign> SubAssign for Ratio<T> {
sub_assign(&mut self, other: Ratio<T>)590         fn sub_assign(&mut self, other: Ratio<T>) {
591             if self.denom == other.denom {
592                 self.numer -= other.numer
593             } else {
594                 let lcm = self.denom.lcm(&other.denom);
595                 let lhs_numer = self.numer.clone() * (lcm.clone() / self.denom.clone());
596                 let rhs_numer = other.numer * (lcm.clone() / other.denom);
597                 self.numer = lhs_numer - rhs_numer;
598                 self.denom = lcm;
599             }
600             self.reduce();
601         }
602     }
603 
604     // a/b + c/1 = (a*1 + b*c) / (b*1) = (a + b*c) / b
605     impl<T: Clone + Integer + NumAssign> AddAssign<T> for Ratio<T> {
add_assign(&mut self, other: T)606         fn add_assign(&mut self, other: T) {
607             self.numer += self.denom.clone() * other;
608             self.reduce();
609         }
610     }
611 
612     impl<T: Clone + Integer + NumAssign> DivAssign<T> for Ratio<T> {
div_assign(&mut self, other: T)613         fn div_assign(&mut self, other: T) {
614             let gcd = self.numer.gcd(&other);
615             self.numer /= gcd.clone();
616             self.denom *= other / gcd;
617             self.reduce(); //TODO: remove this line. see #8.
618         }
619     }
620 
621     impl<T: Clone + Integer + NumAssign> MulAssign<T> for Ratio<T> {
mul_assign(&mut self, other: T)622         fn mul_assign(&mut self, other: T) {
623             let gcd = self.denom.gcd(&other);
624             self.denom /= gcd.clone();
625             self.numer *= other / gcd;
626             self.reduce(); //TODO: remove this line. see #8.
627         }
628     }
629 
630     // a/b % c/1 = (a*1 % b*c) / (b*1) = (a % b*c) / b
631     impl<T: Clone + Integer + NumAssign> RemAssign<T> for Ratio<T> {
rem_assign(&mut self, other: T)632         fn rem_assign(&mut self, other: T) {
633             self.numer %= self.denom.clone() * other;
634             self.reduce();
635         }
636     }
637 
638     // a/b - c/1 = (a*1 - b*c) / (b*1) = (a - b*c) / b
639     impl<T: Clone + Integer + NumAssign> SubAssign<T> for Ratio<T> {
sub_assign(&mut self, other: T)640         fn sub_assign(&mut self, other: T) {
641             self.numer -= self.denom.clone() * other;
642             self.reduce();
643         }
644     }
645 
646     macro_rules! forward_op_assign {
647         (impl $imp:ident, $method:ident) => {
648             impl<'a, T: Clone + Integer + NumAssign> $imp<&'a Ratio<T>> for Ratio<T> {
649                 #[inline]
650                 fn $method(&mut self, other: &Ratio<T>) {
651                     self.$method(other.clone())
652                 }
653             }
654             impl<'a, T: Clone + Integer + NumAssign> $imp<&'a T> for Ratio<T> {
655                 #[inline]
656                 fn $method(&mut self, other: &T) {
657                     self.$method(other.clone())
658                 }
659             }
660         };
661     }
662 
663     forward_op_assign!(impl AddAssign, add_assign);
664     forward_op_assign!(impl DivAssign, div_assign);
665     forward_op_assign!(impl MulAssign, mul_assign);
666     forward_op_assign!(impl RemAssign, rem_assign);
667     forward_op_assign!(impl SubAssign, sub_assign);
668 }
669 
670 macro_rules! forward_ref_ref_binop {
671     (impl $imp:ident, $method:ident) => {
672         impl<'a, 'b, T: Clone + Integer> $imp<&'b Ratio<T>> for &'a Ratio<T> {
673             type Output = Ratio<T>;
674 
675             #[inline]
676             fn $method(self, other: &'b Ratio<T>) -> Ratio<T> {
677                 self.clone().$method(other.clone())
678             }
679         }
680         impl<'a, 'b, T: Clone + Integer> $imp<&'b T> for &'a Ratio<T> {
681             type Output = Ratio<T>;
682 
683             #[inline]
684             fn $method(self, other: &'b T) -> Ratio<T> {
685                 self.clone().$method(other.clone())
686             }
687         }
688     };
689 }
690 
691 macro_rules! forward_ref_val_binop {
692     (impl $imp:ident, $method:ident) => {
693         impl<'a, T> $imp<Ratio<T>> for &'a Ratio<T>
694         where
695             T: Clone + Integer,
696         {
697             type Output = Ratio<T>;
698 
699             #[inline]
700             fn $method(self, other: Ratio<T>) -> Ratio<T> {
701                 self.clone().$method(other)
702             }
703         }
704         impl<'a, T> $imp<T> for &'a Ratio<T>
705         where
706             T: Clone + Integer,
707         {
708             type Output = Ratio<T>;
709 
710             #[inline]
711             fn $method(self, other: T) -> Ratio<T> {
712                 self.clone().$method(other)
713             }
714         }
715     };
716 }
717 
718 macro_rules! forward_val_ref_binop {
719     (impl $imp:ident, $method:ident) => {
720         impl<'a, T> $imp<&'a Ratio<T>> for Ratio<T>
721         where
722             T: Clone + Integer,
723         {
724             type Output = Ratio<T>;
725 
726             #[inline]
727             fn $method(self, other: &Ratio<T>) -> Ratio<T> {
728                 self.$method(other.clone())
729             }
730         }
731         impl<'a, T> $imp<&'a T> for Ratio<T>
732         where
733             T: Clone + Integer,
734         {
735             type Output = Ratio<T>;
736 
737             #[inline]
738             fn $method(self, other: &T) -> Ratio<T> {
739                 self.$method(other.clone())
740             }
741         }
742     };
743 }
744 
745 macro_rules! forward_all_binop {
746     (impl $imp:ident, $method:ident) => {
747         forward_ref_ref_binop!(impl $imp, $method);
748         forward_ref_val_binop!(impl $imp, $method);
749         forward_val_ref_binop!(impl $imp, $method);
750     };
751 }
752 
753 // Arithmetic
754 forward_all_binop!(impl Mul, mul);
755 // a/b * c/d = (a/gcd_ad)*(c/gcd_bc) / ((d/gcd_ad)*(b/gcd_bc))
756 impl<T> Mul<Ratio<T>> for Ratio<T>
757 where
758     T: Clone + Integer,
759 {
760     type Output = Ratio<T>;
761     #[inline]
mul(self, rhs: Ratio<T>) -> Ratio<T>762     fn mul(self, rhs: Ratio<T>) -> Ratio<T> {
763         let gcd_ad = self.numer.gcd(&rhs.denom);
764         let gcd_bc = self.denom.gcd(&rhs.numer);
765         Ratio::new(
766             self.numer / gcd_ad.clone() * (rhs.numer / gcd_bc.clone()),
767             self.denom / gcd_bc * (rhs.denom / gcd_ad),
768         )
769     }
770 }
771 // a/b * c/1 = (a*c) / (b*1) = (a*c) / b
772 impl<T> Mul<T> for Ratio<T>
773 where
774     T: Clone + Integer,
775 {
776     type Output = Ratio<T>;
777     #[inline]
mul(self, rhs: T) -> Ratio<T>778     fn mul(self, rhs: T) -> Ratio<T> {
779         let gcd = self.denom.gcd(&rhs);
780         Ratio::new(self.numer * (rhs / gcd.clone()), self.denom / gcd)
781     }
782 }
783 
784 forward_all_binop!(impl Div, div);
785 // (a/b) / (c/d) = (a/gcd_ac)*(d/gcd_bd) / ((c/gcd_ac)*(b/gcd_bd))
786 impl<T> Div<Ratio<T>> for Ratio<T>
787 where
788     T: Clone + Integer,
789 {
790     type Output = Ratio<T>;
791 
792     #[inline]
div(self, rhs: Ratio<T>) -> Ratio<T>793     fn div(self, rhs: Ratio<T>) -> Ratio<T> {
794         let gcd_ac = self.numer.gcd(&rhs.numer);
795         let gcd_bd = self.denom.gcd(&rhs.denom);
796         Ratio::new(
797             self.numer / gcd_ac.clone() * (rhs.denom / gcd_bd.clone()),
798             self.denom / gcd_bd * (rhs.numer / gcd_ac),
799         )
800     }
801 }
802 // (a/b) / (c/1) = (a*1) / (b*c) = a / (b*c)
803 impl<T> Div<T> for Ratio<T>
804 where
805     T: Clone + Integer,
806 {
807     type Output = Ratio<T>;
808 
809     #[inline]
div(self, rhs: T) -> Ratio<T>810     fn div(self, rhs: T) -> Ratio<T> {
811         let gcd = self.numer.gcd(&rhs);
812         Ratio::new(self.numer / gcd.clone(), self.denom * (rhs / gcd))
813     }
814 }
815 
816 macro_rules! arith_impl {
817     (impl $imp:ident, $method:ident) => {
818         forward_all_binop!(impl $imp, $method);
819         // Abstracts a/b `op` c/d = (a*lcm/b `op` c*lcm/d)/lcm where lcm = lcm(b,d)
820         impl<T: Clone + Integer> $imp<Ratio<T>> for Ratio<T> {
821             type Output = Ratio<T>;
822             #[inline]
823             fn $method(self, rhs: Ratio<T>) -> Ratio<T> {
824                 if self.denom == rhs.denom {
825                     return Ratio::new(self.numer.$method(rhs.numer), rhs.denom);
826                 }
827                 let lcm = self.denom.lcm(&rhs.denom);
828                 let lhs_numer = self.numer * (lcm.clone() / self.denom);
829                 let rhs_numer = rhs.numer * (lcm.clone() / rhs.denom);
830                 Ratio::new(lhs_numer.$method(rhs_numer), lcm)
831             }
832         }
833         // Abstracts the a/b `op` c/1 = (a*1 `op` b*c) / (b*1) = (a `op` b*c) / b pattern
834         impl<T: Clone + Integer> $imp<T> for Ratio<T> {
835             type Output = Ratio<T>;
836             #[inline]
837             fn $method(self, rhs: T) -> Ratio<T> {
838                 Ratio::new(self.numer.$method(self.denom.clone() * rhs), self.denom)
839             }
840         }
841     };
842 }
843 
844 arith_impl!(impl Add, add);
845 arith_impl!(impl Sub, sub);
846 arith_impl!(impl Rem, rem);
847 
848 // Like `std::try!` for Option<T>, unwrap the value or early-return None.
849 // Since Rust 1.22 this can be replaced by the `?` operator.
850 macro_rules! otry {
851     ($expr:expr) => {
852         match $expr {
853             Some(val) => val,
854             None => return None,
855         }
856     };
857 }
858 
859 // a/b * c/d = (a*c)/(b*d)
860 impl<T> CheckedMul for Ratio<T>
861 where
862     T: Clone + Integer + CheckedMul,
863 {
864     #[inline]
checked_mul(&self, rhs: &Ratio<T>) -> Option<Ratio<T>>865     fn checked_mul(&self, rhs: &Ratio<T>) -> Option<Ratio<T>> {
866         let gcd_ad = self.numer.gcd(&rhs.denom);
867         let gcd_bc = self.denom.gcd(&rhs.numer);
868         Some(Ratio::new(
869             otry!((self.numer.clone() / gcd_ad.clone())
870                 .checked_mul(&(rhs.numer.clone() / gcd_bc.clone()))),
871             otry!((self.denom.clone() / gcd_bc).checked_mul(&(rhs.denom.clone() / gcd_ad))),
872         ))
873     }
874 }
875 
876 // (a/b) / (c/d) = (a*d)/(b*c)
877 impl<T> CheckedDiv for Ratio<T>
878 where
879     T: Clone + Integer + CheckedMul,
880 {
881     #[inline]
checked_div(&self, rhs: &Ratio<T>) -> Option<Ratio<T>>882     fn checked_div(&self, rhs: &Ratio<T>) -> Option<Ratio<T>> {
883         if rhs.is_zero() {
884             return None;
885         }
886         let (numer, denom) = if self.denom == rhs.denom {
887             (self.numer.clone(), rhs.numer.clone())
888         } else if self.numer == rhs.numer {
889             (rhs.denom.clone(), self.denom.clone())
890         } else {
891             let gcd_ac = self.numer.gcd(&rhs.numer);
892             let gcd_bd = self.denom.gcd(&rhs.denom);
893             let denom = otry!((self.denom.clone() / gcd_bd.clone())
894                 .checked_mul(&(rhs.numer.clone() / gcd_ac.clone())));
895             (
896                 otry!((self.numer.clone() / gcd_ac).checked_mul(&(rhs.denom.clone() / gcd_bd))),
897                 denom,
898             )
899         };
900         // Manual `reduce()`, avoiding sharp edges
901         if denom.is_zero() {
902             None
903         } else if numer.is_zero() {
904             Some(Self::zero())
905         } else if numer == denom {
906             Some(Self::one())
907         } else {
908             let g = numer.gcd(&denom);
909             let numer = numer / g.clone();
910             let denom = denom / g;
911             let raw = if denom < T::zero() {
912                 // We need to keep denom positive, but 2's-complement MIN may
913                 // overflow negation -- instead we can check multiplying -1.
914                 let n1 = T::zero() - T::one();
915                 Ratio::new_raw(otry!(numer.checked_mul(&n1)), otry!(denom.checked_mul(&n1)))
916             } else {
917                 Ratio::new_raw(numer, denom)
918             };
919             Some(raw)
920         }
921     }
922 }
923 
924 // As arith_impl! but for Checked{Add,Sub} traits
925 macro_rules! checked_arith_impl {
926     (impl $imp:ident, $method:ident) => {
927         impl<T: Clone + Integer + CheckedMul + $imp> $imp for Ratio<T> {
928             #[inline]
929             fn $method(&self, rhs: &Ratio<T>) -> Option<Ratio<T>> {
930                 let gcd = self.denom.clone().gcd(&rhs.denom);
931                 let lcm = otry!((self.denom.clone() / gcd.clone()).checked_mul(&rhs.denom));
932                 let lhs_numer = otry!((lcm.clone() / self.denom.clone()).checked_mul(&self.numer));
933                 let rhs_numer = otry!((lcm.clone() / rhs.denom.clone()).checked_mul(&rhs.numer));
934                 Some(Ratio::new(otry!(lhs_numer.$method(&rhs_numer)), lcm))
935             }
936         }
937     };
938 }
939 
940 // a/b + c/d = (lcm/b*a + lcm/d*c)/lcm, where lcm = lcm(b,d)
941 checked_arith_impl!(impl CheckedAdd, checked_add);
942 
943 // a/b - c/d = (lcm/b*a - lcm/d*c)/lcm, where lcm = lcm(b,d)
944 checked_arith_impl!(impl CheckedSub, checked_sub);
945 
946 impl<T> Neg for Ratio<T>
947 where
948     T: Clone + Integer + Neg<Output = T>,
949 {
950     type Output = Ratio<T>;
951 
952     #[inline]
neg(self) -> Ratio<T>953     fn neg(self) -> Ratio<T> {
954         Ratio::new_raw(-self.numer, self.denom)
955     }
956 }
957 
958 impl<'a, T> Neg for &'a Ratio<T>
959 where
960     T: Clone + Integer + Neg<Output = T>,
961 {
962     type Output = Ratio<T>;
963 
964     #[inline]
neg(self) -> Ratio<T>965     fn neg(self) -> Ratio<T> {
966         -self.clone()
967     }
968 }
969 
970 impl<T> Inv for Ratio<T>
971 where
972     T: Clone + Integer,
973 {
974     type Output = Ratio<T>;
975 
976     #[inline]
inv(self) -> Ratio<T>977     fn inv(self) -> Ratio<T> {
978         self.recip()
979     }
980 }
981 
982 impl<'a, T> Inv for &'a Ratio<T>
983 where
984     T: Clone + Integer,
985 {
986     type Output = Ratio<T>;
987 
988     #[inline]
inv(self) -> Ratio<T>989     fn inv(self) -> Ratio<T> {
990         self.recip()
991     }
992 }
993 
994 // Constants
995 impl<T: Clone + Integer> Zero for Ratio<T> {
996     #[inline]
zero() -> Ratio<T>997     fn zero() -> Ratio<T> {
998         Ratio::new_raw(Zero::zero(), One::one())
999     }
1000 
1001     #[inline]
is_zero(&self) -> bool1002     fn is_zero(&self) -> bool {
1003         self.numer.is_zero()
1004     }
1005 
1006     #[inline]
set_zero(&mut self)1007     fn set_zero(&mut self) {
1008         self.numer.set_zero();
1009         self.denom.set_one();
1010     }
1011 }
1012 
1013 impl<T: Clone + Integer> One for Ratio<T> {
1014     #[inline]
one() -> Ratio<T>1015     fn one() -> Ratio<T> {
1016         Ratio::new_raw(One::one(), One::one())
1017     }
1018 
1019     #[inline]
is_one(&self) -> bool1020     fn is_one(&self) -> bool {
1021         self.numer == self.denom
1022     }
1023 
1024     #[inline]
set_one(&mut self)1025     fn set_one(&mut self) {
1026         self.numer.set_one();
1027         self.denom.set_one();
1028     }
1029 }
1030 
1031 impl<T: Clone + Integer> Num for Ratio<T> {
1032     type FromStrRadixErr = ParseRatioError;
1033 
1034     /// Parses `numer/denom` where the numbers are in base `radix`.
from_str_radix(s: &str, radix: u32) -> Result<Ratio<T>, ParseRatioError>1035     fn from_str_radix(s: &str, radix: u32) -> Result<Ratio<T>, ParseRatioError> {
1036         if s.splitn(2, '/').count() == 2 {
1037             let mut parts = s.splitn(2, '/').map(|ss| {
1038                 T::from_str_radix(ss, radix).map_err(|_| ParseRatioError {
1039                     kind: RatioErrorKind::ParseError,
1040                 })
1041             });
1042             let numer: T = parts.next().unwrap()?;
1043             let denom: T = parts.next().unwrap()?;
1044             if denom.is_zero() {
1045                 Err(ParseRatioError {
1046                     kind: RatioErrorKind::ZeroDenominator,
1047                 })
1048             } else {
1049                 Ok(Ratio::new(numer, denom))
1050             }
1051         } else {
1052             Err(ParseRatioError {
1053                 kind: RatioErrorKind::ParseError,
1054             })
1055         }
1056     }
1057 }
1058 
1059 impl<T: Clone + Integer + Signed> Signed for Ratio<T> {
1060     #[inline]
abs(&self) -> Ratio<T>1061     fn abs(&self) -> Ratio<T> {
1062         if self.is_negative() {
1063             -self.clone()
1064         } else {
1065             self.clone()
1066         }
1067     }
1068 
1069     #[inline]
abs_sub(&self, other: &Ratio<T>) -> Ratio<T>1070     fn abs_sub(&self, other: &Ratio<T>) -> Ratio<T> {
1071         if *self <= *other {
1072             Zero::zero()
1073         } else {
1074             self - other
1075         }
1076     }
1077 
1078     #[inline]
signum(&self) -> Ratio<T>1079     fn signum(&self) -> Ratio<T> {
1080         if self.is_positive() {
1081             Self::one()
1082         } else if self.is_zero() {
1083             Self::zero()
1084         } else {
1085             -Self::one()
1086         }
1087     }
1088 
1089     #[inline]
is_positive(&self) -> bool1090     fn is_positive(&self) -> bool {
1091         (self.numer.is_positive() && self.denom.is_positive())
1092             || (self.numer.is_negative() && self.denom.is_negative())
1093     }
1094 
1095     #[inline]
is_negative(&self) -> bool1096     fn is_negative(&self) -> bool {
1097         (self.numer.is_negative() && self.denom.is_positive())
1098             || (self.numer.is_positive() && self.denom.is_negative())
1099     }
1100 }
1101 
1102 // String conversions
1103 impl<T> fmt::Display for Ratio<T>
1104 where
1105     T: fmt::Display + Eq + One,
1106 {
1107     /// Renders as `numer/denom`. If denom=1, renders as numer.
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result1108     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1109         if self.denom.is_one() {
1110             write!(f, "{}", self.numer)
1111         } else {
1112             write!(f, "{}/{}", self.numer, self.denom)
1113         }
1114     }
1115 }
1116 
1117 impl<T: FromStr + Clone + Integer> FromStr for Ratio<T> {
1118     type Err = ParseRatioError;
1119 
1120     /// Parses `numer/denom` or just `numer`.
from_str(s: &str) -> Result<Ratio<T>, ParseRatioError>1121     fn from_str(s: &str) -> Result<Ratio<T>, ParseRatioError> {
1122         let mut split = s.splitn(2, '/');
1123 
1124         let n = split.next().ok_or(ParseRatioError {
1125             kind: RatioErrorKind::ParseError,
1126         })?;
1127         let num = FromStr::from_str(n).map_err(|_| ParseRatioError {
1128             kind: RatioErrorKind::ParseError,
1129         })?;
1130 
1131         let d = split.next().unwrap_or("1");
1132         let den = FromStr::from_str(d).map_err(|_| ParseRatioError {
1133             kind: RatioErrorKind::ParseError,
1134         })?;
1135 
1136         if Zero::is_zero(&den) {
1137             Err(ParseRatioError {
1138                 kind: RatioErrorKind::ZeroDenominator,
1139             })
1140         } else {
1141             Ok(Ratio::new(num, den))
1142         }
1143     }
1144 }
1145 
1146 impl<T> Into<(T, T)> for Ratio<T> {
into(self) -> (T, T)1147     fn into(self) -> (T, T) {
1148         (self.numer, self.denom)
1149     }
1150 }
1151 
1152 #[cfg(feature = "serde")]
1153 impl<T> serde::Serialize for Ratio<T>
1154 where
1155     T: serde::Serialize + Clone + Integer + PartialOrd,
1156 {
serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: serde::Serializer,1157     fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
1158     where
1159         S: serde::Serializer,
1160     {
1161         (self.numer(), self.denom()).serialize(serializer)
1162     }
1163 }
1164 
1165 #[cfg(feature = "serde")]
1166 impl<'de, T> serde::Deserialize<'de> for Ratio<T>
1167 where
1168     T: serde::Deserialize<'de> + Clone + Integer + PartialOrd,
1169 {
deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: serde::Deserializer<'de>,1170     fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
1171     where
1172         D: serde::Deserializer<'de>,
1173     {
1174         use serde::de::Error;
1175         use serde::de::Unexpected;
1176         let (numer, denom): (T, T) = try!(serde::Deserialize::deserialize(deserializer));
1177         if denom.is_zero() {
1178             Err(Error::invalid_value(
1179                 Unexpected::Signed(0),
1180                 &"a ratio with non-zero denominator",
1181             ))
1182         } else {
1183             Ok(Ratio::new_raw(numer, denom))
1184         }
1185     }
1186 }
1187 
1188 // FIXME: Bubble up specific errors
1189 #[derive(Copy, Clone, Debug, PartialEq)]
1190 pub struct ParseRatioError {
1191     kind: RatioErrorKind,
1192 }
1193 
1194 #[derive(Copy, Clone, Debug, PartialEq)]
1195 enum RatioErrorKind {
1196     ParseError,
1197     ZeroDenominator,
1198 }
1199 
1200 impl fmt::Display for ParseRatioError {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result1201     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1202         self.kind.description().fmt(f)
1203     }
1204 }
1205 
1206 #[cfg(feature = "std")]
1207 impl Error for ParseRatioError {
description(&self) -> &str1208     fn description(&self) -> &str {
1209         self.kind.description()
1210     }
1211 }
1212 
1213 impl RatioErrorKind {
description(&self) -> &'static str1214     fn description(&self) -> &'static str {
1215         match *self {
1216             RatioErrorKind::ParseError => "failed to parse integer",
1217             RatioErrorKind::ZeroDenominator => "zero value denominator",
1218         }
1219     }
1220 }
1221 
1222 #[cfg(feature = "bigint")]
1223 impl FromPrimitive for Ratio<BigInt> {
from_i64(n: i64) -> Option<Self>1224     fn from_i64(n: i64) -> Option<Self> {
1225         Some(Ratio::from_integer(n.into()))
1226     }
1227 
1228     #[cfg(has_i128)]
from_i128(n: i128) -> Option<Self>1229     fn from_i128(n: i128) -> Option<Self> {
1230         Some(Ratio::from_integer(n.into()))
1231     }
1232 
from_u64(n: u64) -> Option<Self>1233     fn from_u64(n: u64) -> Option<Self> {
1234         Some(Ratio::from_integer(n.into()))
1235     }
1236 
1237     #[cfg(has_i128)]
from_u128(n: u128) -> Option<Self>1238     fn from_u128(n: u128) -> Option<Self> {
1239         Some(Ratio::from_integer(n.into()))
1240     }
1241 
from_f32(n: f32) -> Option<Self>1242     fn from_f32(n: f32) -> Option<Self> {
1243         Ratio::from_float(n)
1244     }
1245 
from_f64(n: f64) -> Option<Self>1246     fn from_f64(n: f64) -> Option<Self> {
1247         Ratio::from_float(n)
1248     }
1249 }
1250 
1251 macro_rules! from_primitive_integer {
1252     ($typ:ty, $approx:ident) => {
1253         impl FromPrimitive for Ratio<$typ> {
1254             fn from_i64(n: i64) -> Option<Self> {
1255                 <$typ as FromPrimitive>::from_i64(n).map(Ratio::from_integer)
1256             }
1257 
1258             #[cfg(has_i128)]
1259             fn from_i128(n: i128) -> Option<Self> {
1260                 <$typ as FromPrimitive>::from_i128(n).map(Ratio::from_integer)
1261             }
1262 
1263             fn from_u64(n: u64) -> Option<Self> {
1264                 <$typ as FromPrimitive>::from_u64(n).map(Ratio::from_integer)
1265             }
1266 
1267             #[cfg(has_i128)]
1268             fn from_u128(n: u128) -> Option<Self> {
1269                 <$typ as FromPrimitive>::from_u128(n).map(Ratio::from_integer)
1270             }
1271 
1272             fn from_f32(n: f32) -> Option<Self> {
1273                 $approx(n, 10e-20, 30)
1274             }
1275 
1276             fn from_f64(n: f64) -> Option<Self> {
1277                 $approx(n, 10e-20, 30)
1278             }
1279         }
1280     };
1281 }
1282 
1283 from_primitive_integer!(i8, approximate_float);
1284 from_primitive_integer!(i16, approximate_float);
1285 from_primitive_integer!(i32, approximate_float);
1286 from_primitive_integer!(i64, approximate_float);
1287 #[cfg(has_i128)]
1288 from_primitive_integer!(i128, approximate_float);
1289 from_primitive_integer!(isize, approximate_float);
1290 
1291 from_primitive_integer!(u8, approximate_float_unsigned);
1292 from_primitive_integer!(u16, approximate_float_unsigned);
1293 from_primitive_integer!(u32, approximate_float_unsigned);
1294 from_primitive_integer!(u64, approximate_float_unsigned);
1295 #[cfg(has_i128)]
1296 from_primitive_integer!(u128, approximate_float_unsigned);
1297 from_primitive_integer!(usize, approximate_float_unsigned);
1298 
1299 impl<T: Integer + Signed + Bounded + NumCast + Clone> Ratio<T> {
approximate_float<F: FloatCore + NumCast>(f: F) -> Option<Ratio<T>>1300     pub fn approximate_float<F: FloatCore + NumCast>(f: F) -> Option<Ratio<T>> {
1301         // 1/10e-20 < 1/2**32 which seems like a good default, and 30 seems
1302         // to work well. Might want to choose something based on the types in the future, e.g.
1303         // T::max().recip() and T::bits() or something similar.
1304         let epsilon = <F as NumCast>::from(10e-20).expect("Can't convert 10e-20");
1305         approximate_float(f, epsilon, 30)
1306     }
1307 }
1308 
approximate_float<T, F>(val: F, max_error: F, max_iterations: usize) -> Option<Ratio<T>> where T: Integer + Signed + Bounded + NumCast + Clone, F: FloatCore + NumCast,1309 fn approximate_float<T, F>(val: F, max_error: F, max_iterations: usize) -> Option<Ratio<T>>
1310 where
1311     T: Integer + Signed + Bounded + NumCast + Clone,
1312     F: FloatCore + NumCast,
1313 {
1314     let negative = val.is_sign_negative();
1315     let abs_val = val.abs();
1316 
1317     let r = approximate_float_unsigned(abs_val, max_error, max_iterations);
1318 
1319     // Make negative again if needed
1320     if negative {
1321         r.map(|r| r.neg())
1322     } else {
1323         r
1324     }
1325 }
1326 
1327 // No Unsigned constraint because this also works on positive integers and is called
1328 // 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 + NumCast,1329 fn approximate_float_unsigned<T, F>(val: F, max_error: F, max_iterations: usize) -> Option<Ratio<T>>
1330 where
1331     T: Integer + Bounded + NumCast + Clone,
1332     F: FloatCore + NumCast,
1333 {
1334     // Continued fractions algorithm
1335     // http://mathforum.org/dr.math/faq/faq.fractions.html#decfrac
1336 
1337     if val < F::zero() || val.is_nan() {
1338         return None;
1339     }
1340 
1341     let mut q = val;
1342     let mut n0 = T::zero();
1343     let mut d0 = T::one();
1344     let mut n1 = T::one();
1345     let mut d1 = T::zero();
1346 
1347     let t_max = T::max_value();
1348     let t_max_f = match <F as NumCast>::from(t_max.clone()) {
1349         None => return None,
1350         Some(t_max_f) => t_max_f,
1351     };
1352 
1353     // 1/epsilon > T::MAX
1354     let epsilon = t_max_f.recip();
1355 
1356     // Overflow
1357     if q > t_max_f {
1358         return None;
1359     }
1360 
1361     for _ in 0..max_iterations {
1362         let a = match <T as NumCast>::from(q) {
1363             None => break,
1364             Some(a) => a,
1365         };
1366 
1367         let a_f = match <F as NumCast>::from(a.clone()) {
1368             None => break,
1369             Some(a_f) => a_f,
1370         };
1371         let f = q - a_f;
1372 
1373         // Prevent overflow
1374         if !a.is_zero()
1375             && (n1 > t_max.clone() / a.clone()
1376                 || d1 > t_max.clone() / a.clone()
1377                 || a.clone() * n1.clone() > t_max.clone() - n0.clone()
1378                 || a.clone() * d1.clone() > t_max.clone() - d0.clone())
1379         {
1380             break;
1381         }
1382 
1383         let n = a.clone() * n1.clone() + n0.clone();
1384         let d = a.clone() * d1.clone() + d0.clone();
1385 
1386         n0 = n1;
1387         d0 = d1;
1388         n1 = n.clone();
1389         d1 = d.clone();
1390 
1391         // Simplify fraction. Doing so here instead of at the end
1392         // allows us to get closer to the target value without overflows
1393         let g = Integer::gcd(&n1, &d1);
1394         if !g.is_zero() {
1395             n1 = n1 / g.clone();
1396             d1 = d1 / g.clone();
1397         }
1398 
1399         // Close enough?
1400         let (n_f, d_f) = match (<F as NumCast>::from(n), <F as NumCast>::from(d)) {
1401             (Some(n_f), Some(d_f)) => (n_f, d_f),
1402             _ => break,
1403         };
1404         if (n_f / d_f - val).abs() < max_error {
1405             break;
1406         }
1407 
1408         // Prevent division by ~0
1409         if f < epsilon {
1410             break;
1411         }
1412         q = f.recip();
1413     }
1414 
1415     // Overflow
1416     if d1.is_zero() {
1417         return None;
1418     }
1419 
1420     Some(Ratio::new(n1, d1))
1421 }
1422 
1423 #[cfg(test)]
1424 #[cfg(feature = "std")]
hash<T: Hash>(x: &T) -> u641425 fn hash<T: Hash>(x: &T) -> u64 {
1426     use std::collections::hash_map::RandomState;
1427     use std::hash::BuildHasher;
1428     let mut hasher = <RandomState as BuildHasher>::Hasher::new();
1429     x.hash(&mut hasher);
1430     hasher.finish()
1431 }
1432 
1433 #[cfg(test)]
1434 mod test {
1435     #[cfg(feature = "bigint")]
1436     use super::BigRational;
1437     use super::{Ratio, Rational, Rational64};
1438 
1439     use core::f64;
1440     use core::i32;
1441     use core::isize;
1442     use core::str::FromStr;
1443     use integer::Integer;
1444     use traits::{FromPrimitive, One, Pow, Signed, Zero};
1445 
1446     pub const _0: Rational = Ratio { numer: 0, denom: 1 };
1447     pub const _1: Rational = Ratio { numer: 1, denom: 1 };
1448     pub const _2: Rational = Ratio { numer: 2, denom: 1 };
1449     pub const _NEG2: Rational = Ratio {
1450         numer: -2,
1451         denom: 1,
1452     };
1453     pub const _1_2: Rational = Ratio { numer: 1, denom: 2 };
1454     pub const _3_2: Rational = Ratio { numer: 3, denom: 2 };
1455     pub const _5_2: Rational = Ratio { numer: 5, denom: 2 };
1456     pub const _NEG1_2: Rational = Ratio {
1457         numer: -1,
1458         denom: 2,
1459     };
1460     pub const _1_NEG2: Rational = Ratio {
1461         numer: 1,
1462         denom: -2,
1463     };
1464     pub const _NEG1_NEG2: Rational = Ratio {
1465         numer: -1,
1466         denom: -2,
1467     };
1468     pub const _1_3: Rational = Ratio { numer: 1, denom: 3 };
1469     pub const _NEG1_3: Rational = Ratio {
1470         numer: -1,
1471         denom: 3,
1472     };
1473     pub const _2_3: Rational = Ratio { numer: 2, denom: 3 };
1474     pub const _NEG2_3: Rational = Ratio {
1475         numer: -2,
1476         denom: 3,
1477     };
1478     pub const _MIN: Rational = Ratio {
1479         numer: isize::MIN,
1480         denom: 1,
1481     };
1482     pub const _MIN_P1: Rational = Ratio {
1483         numer: isize::MIN + 1,
1484         denom: 1,
1485     };
1486     pub const _MAX: Rational = Ratio {
1487         numer: isize::MAX,
1488         denom: 1,
1489     };
1490     pub const _MAX_M1: Rational = Ratio {
1491         numer: isize::MAX - 1,
1492         denom: 1,
1493     };
1494 
1495     #[cfg(feature = "bigint")]
to_big(n: Rational) -> BigRational1496     pub fn to_big(n: Rational) -> BigRational {
1497         Ratio::new(
1498             FromPrimitive::from_isize(n.numer).unwrap(),
1499             FromPrimitive::from_isize(n.denom).unwrap(),
1500         )
1501     }
1502     #[cfg(not(feature = "bigint"))]
to_big(n: Rational) -> Rational1503     pub fn to_big(n: Rational) -> Rational {
1504         Ratio::new(
1505             FromPrimitive::from_isize(n.numer).unwrap(),
1506             FromPrimitive::from_isize(n.denom).unwrap(),
1507         )
1508     }
1509 
1510     #[test]
test_test_constants()1511     fn test_test_constants() {
1512         // check our constants are what Ratio::new etc. would make.
1513         assert_eq!(_0, Zero::zero());
1514         assert_eq!(_1, One::one());
1515         assert_eq!(_2, Ratio::from_integer(2));
1516         assert_eq!(_1_2, Ratio::new(1, 2));
1517         assert_eq!(_3_2, Ratio::new(3, 2));
1518         assert_eq!(_NEG1_2, Ratio::new(-1, 2));
1519         assert_eq!(_2, From::from(2));
1520     }
1521 
1522     #[test]
test_new_reduce()1523     fn test_new_reduce() {
1524         assert_eq!(Ratio::new(2, 2), One::one());
1525         assert_eq!(Ratio::new(0, i32::MIN), Zero::zero());
1526         assert_eq!(Ratio::new(i32::MIN, i32::MIN), One::one());
1527     }
1528     #[test]
1529     #[should_panic]
test_new_zero()1530     fn test_new_zero() {
1531         let _a = Ratio::new(1, 0);
1532     }
1533 
1534     #[test]
test_approximate_float()1535     fn test_approximate_float() {
1536         assert_eq!(Ratio::from_f32(0.5f32), Some(Ratio::new(1i64, 2)));
1537         assert_eq!(Ratio::from_f64(0.5f64), Some(Ratio::new(1i32, 2)));
1538         assert_eq!(Ratio::from_f32(5f32), Some(Ratio::new(5i64, 1)));
1539         assert_eq!(Ratio::from_f64(5f64), Some(Ratio::new(5i32, 1)));
1540         assert_eq!(Ratio::from_f32(29.97f32), Some(Ratio::new(2997i64, 100)));
1541         assert_eq!(Ratio::from_f32(-29.97f32), Some(Ratio::new(-2997i64, 100)));
1542 
1543         assert_eq!(Ratio::<i8>::from_f32(63.5f32), Some(Ratio::new(127i8, 2)));
1544         assert_eq!(Ratio::<i8>::from_f32(126.5f32), Some(Ratio::new(126i8, 1)));
1545         assert_eq!(Ratio::<i8>::from_f32(127.0f32), Some(Ratio::new(127i8, 1)));
1546         assert_eq!(Ratio::<i8>::from_f32(127.5f32), None);
1547         assert_eq!(Ratio::<i8>::from_f32(-63.5f32), Some(Ratio::new(-127i8, 2)));
1548         assert_eq!(
1549             Ratio::<i8>::from_f32(-126.5f32),
1550             Some(Ratio::new(-126i8, 1))
1551         );
1552         assert_eq!(
1553             Ratio::<i8>::from_f32(-127.0f32),
1554             Some(Ratio::new(-127i8, 1))
1555         );
1556         assert_eq!(Ratio::<i8>::from_f32(-127.5f32), None);
1557 
1558         assert_eq!(Ratio::<u8>::from_f32(-127f32), None);
1559         assert_eq!(Ratio::<u8>::from_f32(127f32), Some(Ratio::new(127u8, 1)));
1560         assert_eq!(Ratio::<u8>::from_f32(127.5f32), Some(Ratio::new(255u8, 2)));
1561         assert_eq!(Ratio::<u8>::from_f32(256f32), None);
1562 
1563         assert_eq!(Ratio::<i64>::from_f64(-10e200), None);
1564         assert_eq!(Ratio::<i64>::from_f64(10e200), None);
1565         assert_eq!(Ratio::<i64>::from_f64(f64::INFINITY), None);
1566         assert_eq!(Ratio::<i64>::from_f64(f64::NEG_INFINITY), None);
1567         assert_eq!(Ratio::<i64>::from_f64(f64::NAN), None);
1568         assert_eq!(
1569             Ratio::<i64>::from_f64(f64::EPSILON),
1570             Some(Ratio::new(1, 4503599627370496))
1571         );
1572         assert_eq!(Ratio::<i64>::from_f64(0.0), Some(Ratio::new(0, 1)));
1573         assert_eq!(Ratio::<i64>::from_f64(-0.0), Some(Ratio::new(0, 1)));
1574     }
1575 
1576     #[test]
test_cmp()1577     fn test_cmp() {
1578         assert!(_0 == _0 && _1 == _1);
1579         assert!(_0 != _1 && _1 != _0);
1580         assert!(_0 < _1 && !(_1 < _0));
1581         assert!(_1 > _0 && !(_0 > _1));
1582 
1583         assert!(_0 <= _0 && _1 <= _1);
1584         assert!(_0 <= _1 && !(_1 <= _0));
1585 
1586         assert!(_0 >= _0 && _1 >= _1);
1587         assert!(_1 >= _0 && !(_0 >= _1));
1588 
1589         let _0_2: Rational = Ratio::new_raw(0, 2);
1590         assert_eq!(_0, _0_2);
1591     }
1592 
1593     #[test]
test_cmp_overflow()1594     fn test_cmp_overflow() {
1595         use core::cmp::Ordering;
1596 
1597         // issue #7 example:
1598         let big = Ratio::new(128u8, 1);
1599         let small = big.recip();
1600         assert!(big > small);
1601 
1602         // try a few that are closer together
1603         // (some matching numer, some matching denom, some neither)
1604         let ratios = [
1605             Ratio::new(125_i8, 127_i8),
1606             Ratio::new(63_i8, 64_i8),
1607             Ratio::new(124_i8, 125_i8),
1608             Ratio::new(125_i8, 126_i8),
1609             Ratio::new(126_i8, 127_i8),
1610             Ratio::new(127_i8, 126_i8),
1611         ];
1612 
1613         fn check_cmp(a: Ratio<i8>, b: Ratio<i8>, ord: Ordering) {
1614             #[cfg(feature = "std")]
1615             println!("comparing {} and {}", a, b);
1616             assert_eq!(a.cmp(&b), ord);
1617             assert_eq!(b.cmp(&a), ord.reverse());
1618         }
1619 
1620         for (i, &a) in ratios.iter().enumerate() {
1621             check_cmp(a, a, Ordering::Equal);
1622             check_cmp(-a, a, Ordering::Less);
1623             for &b in &ratios[i + 1..] {
1624                 check_cmp(a, b, Ordering::Less);
1625                 check_cmp(-a, -b, Ordering::Greater);
1626                 check_cmp(a.recip(), b.recip(), Ordering::Greater);
1627                 check_cmp(-a.recip(), -b.recip(), Ordering::Less);
1628             }
1629         }
1630     }
1631 
1632     #[test]
test_to_integer()1633     fn test_to_integer() {
1634         assert_eq!(_0.to_integer(), 0);
1635         assert_eq!(_1.to_integer(), 1);
1636         assert_eq!(_2.to_integer(), 2);
1637         assert_eq!(_1_2.to_integer(), 0);
1638         assert_eq!(_3_2.to_integer(), 1);
1639         assert_eq!(_NEG1_2.to_integer(), 0);
1640     }
1641 
1642     #[test]
test_numer()1643     fn test_numer() {
1644         assert_eq!(_0.numer(), &0);
1645         assert_eq!(_1.numer(), &1);
1646         assert_eq!(_2.numer(), &2);
1647         assert_eq!(_1_2.numer(), &1);
1648         assert_eq!(_3_2.numer(), &3);
1649         assert_eq!(_NEG1_2.numer(), &(-1));
1650     }
1651     #[test]
test_denom()1652     fn test_denom() {
1653         assert_eq!(_0.denom(), &1);
1654         assert_eq!(_1.denom(), &1);
1655         assert_eq!(_2.denom(), &1);
1656         assert_eq!(_1_2.denom(), &2);
1657         assert_eq!(_3_2.denom(), &2);
1658         assert_eq!(_NEG1_2.denom(), &2);
1659     }
1660 
1661     #[test]
test_is_integer()1662     fn test_is_integer() {
1663         assert!(_0.is_integer());
1664         assert!(_1.is_integer());
1665         assert!(_2.is_integer());
1666         assert!(!_1_2.is_integer());
1667         assert!(!_3_2.is_integer());
1668         assert!(!_NEG1_2.is_integer());
1669     }
1670 
1671     #[test]
1672     #[cfg(feature = "std")]
test_show()1673     fn test_show() {
1674         use std::string::ToString;
1675         assert_eq!(format!("{}", _2), "2".to_string());
1676         assert_eq!(format!("{}", _1_2), "1/2".to_string());
1677         assert_eq!(format!("{}", _0), "0".to_string());
1678         assert_eq!(format!("{}", Ratio::from_integer(-2)), "-2".to_string());
1679     }
1680 
1681     mod arith {
1682         use super::super::{Ratio, Rational};
1683         use super::{to_big, _0, _1, _1_2, _2, _3_2, _5_2, _MAX, _MAX_M1, _MIN, _MIN_P1, _NEG1_2};
1684         use core::fmt::Debug;
1685         use integer::Integer;
1686         use traits::{Bounded, CheckedAdd, CheckedDiv, CheckedMul, CheckedSub, NumAssign};
1687 
1688         #[test]
test_add()1689         fn test_add() {
1690             fn test(a: Rational, b: Rational, c: Rational) {
1691                 assert_eq!(a + b, c);
1692                 assert_eq!(
1693                     {
1694                         let mut x = a;
1695                         x += b;
1696                         x
1697                     },
1698                     c
1699                 );
1700                 assert_eq!(to_big(a) + to_big(b), to_big(c));
1701                 assert_eq!(a.checked_add(&b), Some(c));
1702                 assert_eq!(to_big(a).checked_add(&to_big(b)), Some(to_big(c)));
1703             }
1704             fn test_assign(a: Rational, b: isize, c: Rational) {
1705                 assert_eq!(a + b, c);
1706                 assert_eq!(
1707                     {
1708                         let mut x = a;
1709                         x += b;
1710                         x
1711                     },
1712                     c
1713                 );
1714             }
1715 
1716             test(_1, _1_2, _3_2);
1717             test(_1, _1, _2);
1718             test(_1_2, _3_2, _2);
1719             test(_1_2, _NEG1_2, _0);
1720             test_assign(_1_2, 1, _3_2);
1721         }
1722 
1723         #[test]
test_add_overflow()1724         fn test_add_overflow() {
1725             // compares Ratio(1, T::max_value()) + Ratio(1, T::max_value())
1726             // to Ratio(1+1, T::max_value()) for each integer type.
1727             // Previously, this calculation would overflow.
1728             fn test_add_typed_overflow<T>()
1729             where
1730                 T: Integer + Bounded + Clone + Debug + NumAssign,
1731             {
1732                 let _1_max = Ratio::new(T::one(), T::max_value());
1733                 let _2_max = Ratio::new(T::one() + T::one(), T::max_value());
1734                 assert_eq!(_1_max.clone() + _1_max.clone(), _2_max);
1735                 assert_eq!(
1736                     {
1737                         let mut tmp = _1_max.clone();
1738                         tmp += _1_max.clone();
1739                         tmp
1740                     },
1741                     _2_max.clone()
1742                 );
1743             }
1744             test_add_typed_overflow::<u8>();
1745             test_add_typed_overflow::<u16>();
1746             test_add_typed_overflow::<u32>();
1747             test_add_typed_overflow::<u64>();
1748             test_add_typed_overflow::<usize>();
1749             #[cfg(has_u128)]
1750             test_add_typed_overflow::<u128>();
1751 
1752             test_add_typed_overflow::<i8>();
1753             test_add_typed_overflow::<i16>();
1754             test_add_typed_overflow::<i32>();
1755             test_add_typed_overflow::<i64>();
1756             test_add_typed_overflow::<isize>();
1757             #[cfg(has_i128)]
1758             test_add_typed_overflow::<i128>();
1759         }
1760 
1761         #[test]
test_sub()1762         fn test_sub() {
1763             fn test(a: Rational, b: Rational, c: Rational) {
1764                 assert_eq!(a - b, c);
1765                 assert_eq!(
1766                     {
1767                         let mut x = a;
1768                         x -= b;
1769                         x
1770                     },
1771                     c
1772                 );
1773                 assert_eq!(to_big(a) - to_big(b), to_big(c));
1774                 assert_eq!(a.checked_sub(&b), Some(c));
1775                 assert_eq!(to_big(a).checked_sub(&to_big(b)), Some(to_big(c)));
1776             }
1777             fn test_assign(a: Rational, b: isize, c: Rational) {
1778                 assert_eq!(a - b, c);
1779                 assert_eq!(
1780                     {
1781                         let mut x = a;
1782                         x -= b;
1783                         x
1784                     },
1785                     c
1786                 );
1787             }
1788 
1789             test(_1, _1_2, _1_2);
1790             test(_3_2, _1_2, _1);
1791             test(_1, _NEG1_2, _3_2);
1792             test_assign(_1_2, 1, _NEG1_2);
1793         }
1794 
1795         #[test]
test_sub_overflow()1796         fn test_sub_overflow() {
1797             // compares Ratio(1, T::max_value()) - Ratio(1, T::max_value()) to T::zero()
1798             // for each integer type. Previously, this calculation would overflow.
1799             fn test_sub_typed_overflow<T>()
1800             where
1801                 T: Integer + Bounded + Clone + Debug + NumAssign,
1802             {
1803                 let _1_max: Ratio<T> = Ratio::new(T::one(), T::max_value());
1804                 assert!(T::is_zero(&(_1_max.clone() - _1_max.clone()).numer));
1805                 {
1806                     let mut tmp: Ratio<T> = _1_max.clone();
1807                     tmp -= _1_max.clone();
1808                     assert!(T::is_zero(&tmp.numer));
1809                 }
1810             }
1811             test_sub_typed_overflow::<u8>();
1812             test_sub_typed_overflow::<u16>();
1813             test_sub_typed_overflow::<u32>();
1814             test_sub_typed_overflow::<u64>();
1815             test_sub_typed_overflow::<usize>();
1816             #[cfg(has_u128)]
1817             test_sub_typed_overflow::<u128>();
1818 
1819             test_sub_typed_overflow::<i8>();
1820             test_sub_typed_overflow::<i16>();
1821             test_sub_typed_overflow::<i32>();
1822             test_sub_typed_overflow::<i64>();
1823             test_sub_typed_overflow::<isize>();
1824             #[cfg(has_i128)]
1825             test_sub_typed_overflow::<i128>();
1826         }
1827 
1828         #[test]
test_mul()1829         fn test_mul() {
1830             fn test(a: Rational, b: Rational, c: Rational) {
1831                 assert_eq!(a * b, c);
1832                 assert_eq!(
1833                     {
1834                         let mut x = a;
1835                         x *= b;
1836                         x
1837                     },
1838                     c
1839                 );
1840                 assert_eq!(to_big(a) * to_big(b), to_big(c));
1841                 assert_eq!(a.checked_mul(&b), Some(c));
1842                 assert_eq!(to_big(a).checked_mul(&to_big(b)), Some(to_big(c)));
1843             }
1844             fn test_assign(a: Rational, b: isize, c: Rational) {
1845                 assert_eq!(a * b, c);
1846                 assert_eq!(
1847                     {
1848                         let mut x = a;
1849                         x *= b;
1850                         x
1851                     },
1852                     c
1853                 );
1854             }
1855 
1856             test(_1, _1_2, _1_2);
1857             test(_1_2, _3_2, Ratio::new(3, 4));
1858             test(_1_2, _NEG1_2, Ratio::new(-1, 4));
1859             test_assign(_1_2, 2, _1);
1860         }
1861 
1862         #[test]
test_mul_overflow()1863         fn test_mul_overflow() {
1864             fn test_mul_typed_overflow<T>()
1865             where
1866                 T: Integer + Bounded + Clone + Debug + NumAssign + CheckedMul,
1867             {
1868                 let two = T::one() + T::one();
1869                 let _3 = T::one() + T::one() + T::one();
1870 
1871                 // 1/big * 2/3 = 1/(max/4*3), where big is max/2
1872                 // make big = max/2, but also divisible by 2
1873                 let big = T::max_value() / two.clone() / two.clone() * two.clone();
1874                 let _1_big: Ratio<T> = Ratio::new(T::one(), big.clone());
1875                 let _2_3: Ratio<T> = Ratio::new(two.clone(), _3.clone());
1876                 assert_eq!(None, big.clone().checked_mul(&_3.clone()));
1877                 let expected = Ratio::new(T::one(), big / two.clone() * _3.clone());
1878                 assert_eq!(expected.clone(), _1_big.clone() * _2_3.clone());
1879                 assert_eq!(
1880                     Some(expected.clone()),
1881                     _1_big.clone().checked_mul(&_2_3.clone())
1882                 );
1883                 assert_eq!(expected, {
1884                     let mut tmp = _1_big.clone();
1885                     tmp *= _2_3;
1886                     tmp
1887                 });
1888 
1889                 // big/3 * 3 = big/1
1890                 // make big = max/2, but make it indivisible by 3
1891                 let big = T::max_value() / two.clone() / _3.clone() * _3.clone() + T::one();
1892                 assert_eq!(None, big.clone().checked_mul(&_3.clone()));
1893                 let big_3 = Ratio::new(big.clone(), _3.clone());
1894                 let expected = Ratio::new(big.clone(), T::one());
1895                 assert_eq!(expected, big_3.clone() * _3.clone());
1896                 assert_eq!(expected, {
1897                     let mut tmp = big_3.clone();
1898                     tmp *= _3.clone();
1899                     tmp
1900                 });
1901             }
1902             test_mul_typed_overflow::<u16>();
1903             test_mul_typed_overflow::<u8>();
1904             test_mul_typed_overflow::<u32>();
1905             test_mul_typed_overflow::<u64>();
1906             test_mul_typed_overflow::<usize>();
1907             #[cfg(has_u128)]
1908             test_mul_typed_overflow::<u128>();
1909 
1910             test_mul_typed_overflow::<i8>();
1911             test_mul_typed_overflow::<i16>();
1912             test_mul_typed_overflow::<i32>();
1913             test_mul_typed_overflow::<i64>();
1914             test_mul_typed_overflow::<isize>();
1915             #[cfg(has_i128)]
1916             test_mul_typed_overflow::<i128>();
1917         }
1918 
1919         #[test]
test_div()1920         fn test_div() {
1921             fn test(a: Rational, b: Rational, c: Rational) {
1922                 assert_eq!(a / b, c);
1923                 assert_eq!(
1924                     {
1925                         let mut x = a;
1926                         x /= b;
1927                         x
1928                     },
1929                     c
1930                 );
1931                 assert_eq!(to_big(a) / to_big(b), to_big(c));
1932                 assert_eq!(a.checked_div(&b), Some(c));
1933                 assert_eq!(to_big(a).checked_div(&to_big(b)), Some(to_big(c)));
1934             }
1935             fn test_assign(a: Rational, b: isize, c: Rational) {
1936                 assert_eq!(a / b, c);
1937                 assert_eq!(
1938                     {
1939                         let mut x = a;
1940                         x /= b;
1941                         x
1942                     },
1943                     c
1944                 );
1945             }
1946 
1947             test(_1, _1_2, _2);
1948             test(_3_2, _1_2, _1 + _2);
1949             test(_1, _NEG1_2, _NEG1_2 + _NEG1_2 + _NEG1_2 + _NEG1_2);
1950             test_assign(_1, 2, _1_2);
1951         }
1952 
1953         #[test]
test_div_overflow()1954         fn test_div_overflow() {
1955             fn test_div_typed_overflow<T>()
1956             where
1957                 T: Integer + Bounded + Clone + Debug + NumAssign + CheckedMul,
1958             {
1959                 let two = T::one() + T::one();
1960                 let _3 = T::one() + T::one() + T::one();
1961 
1962                 // 1/big / 3/2 = 1/(max/4*3), where big is max/2
1963                 // big ~ max/2, and big is divisible by 2
1964                 let big = T::max_value() / two.clone() / two.clone() * two.clone();
1965                 assert_eq!(None, big.clone().checked_mul(&_3.clone()));
1966                 let _1_big: Ratio<T> = Ratio::new(T::one(), big.clone());
1967                 let _3_two: Ratio<T> = Ratio::new(_3.clone(), two.clone());
1968                 let expected = Ratio::new(T::one(), big.clone() / two.clone() * _3.clone());
1969                 assert_eq!(expected.clone(), _1_big.clone() / _3_two.clone());
1970                 assert_eq!(
1971                     Some(expected.clone()),
1972                     _1_big.clone().checked_div(&_3_two.clone())
1973                 );
1974                 assert_eq!(expected, {
1975                     let mut tmp = _1_big.clone();
1976                     tmp /= _3_two;
1977                     tmp
1978                 });
1979 
1980                 // 3/big / 3 = 1/big where big is max/2
1981                 // big ~ max/2, and big is not divisible by 3
1982                 let big = T::max_value() / two.clone() / _3.clone() * _3.clone() + T::one();
1983                 assert_eq!(None, big.clone().checked_mul(&_3.clone()));
1984                 let _3_big = Ratio::new(_3.clone(), big.clone());
1985                 let expected = Ratio::new(T::one(), big.clone());
1986                 assert_eq!(expected, _3_big.clone() / _3.clone());
1987                 assert_eq!(expected, {
1988                     let mut tmp = _3_big.clone();
1989                     tmp /= _3.clone();
1990                     tmp
1991                 });
1992             }
1993             test_div_typed_overflow::<u8>();
1994             test_div_typed_overflow::<u16>();
1995             test_div_typed_overflow::<u32>();
1996             test_div_typed_overflow::<u64>();
1997             test_div_typed_overflow::<usize>();
1998             #[cfg(has_u128)]
1999             test_div_typed_overflow::<u128>();
2000 
2001             test_div_typed_overflow::<i8>();
2002             test_div_typed_overflow::<i16>();
2003             test_div_typed_overflow::<i32>();
2004             test_div_typed_overflow::<i64>();
2005             test_div_typed_overflow::<isize>();
2006             #[cfg(has_i128)]
2007             test_div_typed_overflow::<i128>();
2008         }
2009 
2010         #[test]
test_rem()2011         fn test_rem() {
2012             fn test(a: Rational, b: Rational, c: Rational) {
2013                 assert_eq!(a % b, c);
2014                 assert_eq!(
2015                     {
2016                         let mut x = a;
2017                         x %= b;
2018                         x
2019                     },
2020                     c
2021                 );
2022                 assert_eq!(to_big(a) % to_big(b), to_big(c))
2023             }
2024             fn test_assign(a: Rational, b: isize, c: Rational) {
2025                 assert_eq!(a % b, c);
2026                 assert_eq!(
2027                     {
2028                         let mut x = a;
2029                         x %= b;
2030                         x
2031                     },
2032                     c
2033                 );
2034             }
2035 
2036             test(_3_2, _1, _1_2);
2037             test(_3_2, _1_2, _0);
2038             test(_5_2, _3_2, _1);
2039             test(_2, _NEG1_2, _0);
2040             test(_1_2, _2, _1_2);
2041             test_assign(_3_2, 1, _1_2);
2042         }
2043 
2044         #[test]
test_rem_overflow()2045         fn test_rem_overflow() {
2046             // tests that Ratio(1,2) % Ratio(1, T::max_value()) equals 0
2047             // for each integer type. Previously, this calculation would overflow.
2048             fn test_rem_typed_overflow<T>()
2049             where
2050                 T: Integer + Bounded + Clone + Debug + NumAssign,
2051             {
2052                 let two = T::one() + T::one();
2053                 //value near to maximum, but divisible by two
2054                 let max_div2 = T::max_value() / two.clone() * two.clone();
2055                 let _1_max: Ratio<T> = Ratio::new(T::one(), max_div2.clone());
2056                 let _1_two: Ratio<T> = Ratio::new(T::one(), two);
2057                 assert!(T::is_zero(&(_1_two.clone() % _1_max.clone()).numer));
2058                 {
2059                     let mut tmp: Ratio<T> = _1_two.clone();
2060                     tmp %= _1_max.clone();
2061                     assert!(T::is_zero(&tmp.numer));
2062                 }
2063             }
2064             test_rem_typed_overflow::<u8>();
2065             test_rem_typed_overflow::<u16>();
2066             test_rem_typed_overflow::<u32>();
2067             test_rem_typed_overflow::<u64>();
2068             test_rem_typed_overflow::<usize>();
2069             #[cfg(has_u128)]
2070             test_rem_typed_overflow::<u128>();
2071 
2072             test_rem_typed_overflow::<i8>();
2073             test_rem_typed_overflow::<i16>();
2074             test_rem_typed_overflow::<i32>();
2075             test_rem_typed_overflow::<i64>();
2076             test_rem_typed_overflow::<isize>();
2077             #[cfg(has_i128)]
2078             test_rem_typed_overflow::<i128>();
2079         }
2080 
2081         #[test]
test_neg()2082         fn test_neg() {
2083             fn test(a: Rational, b: Rational) {
2084                 assert_eq!(-a, b);
2085                 assert_eq!(-to_big(a), to_big(b))
2086             }
2087 
2088             test(_0, _0);
2089             test(_1_2, _NEG1_2);
2090             test(-_1, _1);
2091         }
2092         #[test]
test_zero()2093         fn test_zero() {
2094             assert_eq!(_0 + _0, _0);
2095             assert_eq!(_0 * _0, _0);
2096             assert_eq!(_0 * _1, _0);
2097             assert_eq!(_0 / _NEG1_2, _0);
2098             assert_eq!(_0 - _0, _0);
2099         }
2100         #[test]
2101         #[should_panic]
test_div_0()2102         fn test_div_0() {
2103             let _a = _1 / _0;
2104         }
2105 
2106         #[test]
test_checked_failures()2107         fn test_checked_failures() {
2108             let big = Ratio::new(128u8, 1);
2109             let small = Ratio::new(1, 128u8);
2110             assert_eq!(big.checked_add(&big), None);
2111             assert_eq!(small.checked_sub(&big), None);
2112             assert_eq!(big.checked_mul(&big), None);
2113             assert_eq!(small.checked_div(&big), None);
2114             assert_eq!(_1.checked_div(&_0), None);
2115         }
2116 
2117         #[test]
test_checked_zeros()2118         fn test_checked_zeros() {
2119             assert_eq!(_0.checked_add(&_0), Some(_0));
2120             assert_eq!(_0.checked_sub(&_0), Some(_0));
2121             assert_eq!(_0.checked_mul(&_0), Some(_0));
2122             assert_eq!(_0.checked_div(&_0), None);
2123         }
2124 
2125         #[test]
test_checked_min()2126         fn test_checked_min() {
2127             assert_eq!(_MIN.checked_add(&_MIN), None);
2128             assert_eq!(_MIN.checked_sub(&_MIN), Some(_0));
2129             assert_eq!(_MIN.checked_mul(&_MIN), None);
2130             assert_eq!(_MIN.checked_div(&_MIN), Some(_1));
2131             assert_eq!(_0.checked_add(&_MIN), Some(_MIN));
2132             assert_eq!(_0.checked_sub(&_MIN), None);
2133             assert_eq!(_0.checked_mul(&_MIN), Some(_0));
2134             assert_eq!(_0.checked_div(&_MIN), Some(_0));
2135             assert_eq!(_1.checked_add(&_MIN), Some(_MIN_P1));
2136             assert_eq!(_1.checked_sub(&_MIN), None);
2137             assert_eq!(_1.checked_mul(&_MIN), Some(_MIN));
2138             assert_eq!(_1.checked_div(&_MIN), None);
2139             assert_eq!(_MIN.checked_add(&_0), Some(_MIN));
2140             assert_eq!(_MIN.checked_sub(&_0), Some(_MIN));
2141             assert_eq!(_MIN.checked_mul(&_0), Some(_0));
2142             assert_eq!(_MIN.checked_div(&_0), None);
2143             assert_eq!(_MIN.checked_add(&_1), Some(_MIN_P1));
2144             assert_eq!(_MIN.checked_sub(&_1), None);
2145             assert_eq!(_MIN.checked_mul(&_1), Some(_MIN));
2146             assert_eq!(_MIN.checked_div(&_1), Some(_MIN));
2147         }
2148 
2149         #[test]
test_checked_max()2150         fn test_checked_max() {
2151             assert_eq!(_MAX.checked_add(&_MAX), None);
2152             assert_eq!(_MAX.checked_sub(&_MAX), Some(_0));
2153             assert_eq!(_MAX.checked_mul(&_MAX), None);
2154             assert_eq!(_MAX.checked_div(&_MAX), Some(_1));
2155             assert_eq!(_0.checked_add(&_MAX), Some(_MAX));
2156             assert_eq!(_0.checked_sub(&_MAX), Some(_MIN_P1));
2157             assert_eq!(_0.checked_mul(&_MAX), Some(_0));
2158             assert_eq!(_0.checked_div(&_MAX), Some(_0));
2159             assert_eq!(_1.checked_add(&_MAX), None);
2160             assert_eq!(_1.checked_sub(&_MAX), Some(-_MAX_M1));
2161             assert_eq!(_1.checked_mul(&_MAX), Some(_MAX));
2162             assert_eq!(_1.checked_div(&_MAX), Some(_MAX.recip()));
2163             assert_eq!(_MAX.checked_add(&_0), Some(_MAX));
2164             assert_eq!(_MAX.checked_sub(&_0), Some(_MAX));
2165             assert_eq!(_MAX.checked_mul(&_0), Some(_0));
2166             assert_eq!(_MAX.checked_div(&_0), None);
2167             assert_eq!(_MAX.checked_add(&_1), None);
2168             assert_eq!(_MAX.checked_sub(&_1), Some(_MAX_M1));
2169             assert_eq!(_MAX.checked_mul(&_1), Some(_MAX));
2170             assert_eq!(_MAX.checked_div(&_1), Some(_MAX));
2171         }
2172 
2173         #[test]
test_checked_min_max()2174         fn test_checked_min_max() {
2175             assert_eq!(_MIN.checked_add(&_MAX), Some(-_1));
2176             assert_eq!(_MIN.checked_sub(&_MAX), None);
2177             assert_eq!(_MIN.checked_mul(&_MAX), None);
2178             assert_eq!(
2179                 _MIN.checked_div(&_MAX),
2180                 Some(Ratio::new(_MIN.numer, _MAX.numer))
2181             );
2182             assert_eq!(_MAX.checked_add(&_MIN), Some(-_1));
2183             assert_eq!(_MAX.checked_sub(&_MIN), None);
2184             assert_eq!(_MAX.checked_mul(&_MIN), None);
2185             assert_eq!(_MAX.checked_div(&_MIN), None);
2186         }
2187     }
2188 
2189     #[test]
test_round()2190     fn test_round() {
2191         assert_eq!(_1_3.ceil(), _1);
2192         assert_eq!(_1_3.floor(), _0);
2193         assert_eq!(_1_3.round(), _0);
2194         assert_eq!(_1_3.trunc(), _0);
2195 
2196         assert_eq!(_NEG1_3.ceil(), _0);
2197         assert_eq!(_NEG1_3.floor(), -_1);
2198         assert_eq!(_NEG1_3.round(), _0);
2199         assert_eq!(_NEG1_3.trunc(), _0);
2200 
2201         assert_eq!(_2_3.ceil(), _1);
2202         assert_eq!(_2_3.floor(), _0);
2203         assert_eq!(_2_3.round(), _1);
2204         assert_eq!(_2_3.trunc(), _0);
2205 
2206         assert_eq!(_NEG2_3.ceil(), _0);
2207         assert_eq!(_NEG2_3.floor(), -_1);
2208         assert_eq!(_NEG2_3.round(), -_1);
2209         assert_eq!(_NEG2_3.trunc(), _0);
2210 
2211         assert_eq!(_1_2.ceil(), _1);
2212         assert_eq!(_1_2.floor(), _0);
2213         assert_eq!(_1_2.round(), _1);
2214         assert_eq!(_1_2.trunc(), _0);
2215 
2216         assert_eq!(_NEG1_2.ceil(), _0);
2217         assert_eq!(_NEG1_2.floor(), -_1);
2218         assert_eq!(_NEG1_2.round(), -_1);
2219         assert_eq!(_NEG1_2.trunc(), _0);
2220 
2221         assert_eq!(_1.ceil(), _1);
2222         assert_eq!(_1.floor(), _1);
2223         assert_eq!(_1.round(), _1);
2224         assert_eq!(_1.trunc(), _1);
2225 
2226         // Overflow checks
2227 
2228         let _neg1 = Ratio::from_integer(-1);
2229         let _large_rat1 = Ratio::new(i32::MAX, i32::MAX - 1);
2230         let _large_rat2 = Ratio::new(i32::MAX - 1, i32::MAX);
2231         let _large_rat3 = Ratio::new(i32::MIN + 2, i32::MIN + 1);
2232         let _large_rat4 = Ratio::new(i32::MIN + 1, i32::MIN + 2);
2233         let _large_rat5 = Ratio::new(i32::MIN + 2, i32::MAX);
2234         let _large_rat6 = Ratio::new(i32::MAX, i32::MIN + 2);
2235         let _large_rat7 = Ratio::new(1, i32::MIN + 1);
2236         let _large_rat8 = Ratio::new(1, i32::MAX);
2237 
2238         assert_eq!(_large_rat1.round(), One::one());
2239         assert_eq!(_large_rat2.round(), One::one());
2240         assert_eq!(_large_rat3.round(), One::one());
2241         assert_eq!(_large_rat4.round(), One::one());
2242         assert_eq!(_large_rat5.round(), _neg1);
2243         assert_eq!(_large_rat6.round(), _neg1);
2244         assert_eq!(_large_rat7.round(), Zero::zero());
2245         assert_eq!(_large_rat8.round(), Zero::zero());
2246     }
2247 
2248     #[test]
test_fract()2249     fn test_fract() {
2250         assert_eq!(_1.fract(), _0);
2251         assert_eq!(_NEG1_2.fract(), _NEG1_2);
2252         assert_eq!(_1_2.fract(), _1_2);
2253         assert_eq!(_3_2.fract(), _1_2);
2254     }
2255 
2256     #[test]
test_recip()2257     fn test_recip() {
2258         assert_eq!(_1 * _1.recip(), _1);
2259         assert_eq!(_2 * _2.recip(), _1);
2260         assert_eq!(_1_2 * _1_2.recip(), _1);
2261         assert_eq!(_3_2 * _3_2.recip(), _1);
2262         assert_eq!(_NEG1_2 * _NEG1_2.recip(), _1);
2263 
2264         assert_eq!(_3_2.recip(), _2_3);
2265         assert_eq!(_NEG1_2.recip(), _NEG2);
2266         assert_eq!(_NEG1_2.recip().denom(), &1);
2267     }
2268 
2269     #[test]
2270     #[should_panic(expected = "== 0")]
test_recip_fail()2271     fn test_recip_fail() {
2272         let _a = Ratio::new(0, 1).recip();
2273     }
2274 
2275     #[test]
test_pow()2276     fn test_pow() {
2277         fn test(r: Rational, e: i32, expected: Rational) {
2278             assert_eq!(r.pow(e), expected);
2279             assert_eq!(Pow::pow(r, e), expected);
2280             assert_eq!(Pow::pow(r, &e), expected);
2281             assert_eq!(Pow::pow(&r, e), expected);
2282             assert_eq!(Pow::pow(&r, &e), expected);
2283         }
2284 
2285         test(_1_2, 2, Ratio::new(1, 4));
2286         test(_1_2, -2, Ratio::new(4, 1));
2287         test(_1, 1, _1);
2288         test(_1, i32::MAX, _1);
2289         test(_1, i32::MIN, _1);
2290         test(_NEG1_2, 2, _1_2.pow(2i32));
2291         test(_NEG1_2, 3, -_1_2.pow(3i32));
2292         test(_3_2, 0, _1);
2293         test(_3_2, -1, _3_2.recip());
2294         test(_3_2, 3, Ratio::new(27, 8));
2295     }
2296 
2297     #[test]
2298     #[cfg(feature = "std")]
test_to_from_str()2299     fn test_to_from_str() {
2300         use std::string::{String, ToString};
2301         fn test(r: Rational, s: String) {
2302             assert_eq!(FromStr::from_str(&s), Ok(r));
2303             assert_eq!(r.to_string(), s);
2304         }
2305         test(_1, "1".to_string());
2306         test(_0, "0".to_string());
2307         test(_1_2, "1/2".to_string());
2308         test(_3_2, "3/2".to_string());
2309         test(_2, "2".to_string());
2310         test(_NEG1_2, "-1/2".to_string());
2311     }
2312     #[test]
test_from_str_fail()2313     fn test_from_str_fail() {
2314         fn test(s: &str) {
2315             let rational: Result<Rational, _> = FromStr::from_str(s);
2316             assert!(rational.is_err());
2317         }
2318 
2319         let xs = ["0 /1", "abc", "", "1/", "--1/2", "3/2/1", "1/0"];
2320         for &s in xs.iter() {
2321             test(s);
2322         }
2323     }
2324 
2325     #[cfg(feature = "bigint")]
2326     #[test]
test_from_float()2327     fn test_from_float() {
2328         use traits::float::FloatCore;
2329         fn test<T: FloatCore>(given: T, (numer, denom): (&str, &str)) {
2330             let ratio: BigRational = Ratio::from_float(given).unwrap();
2331             assert_eq!(
2332                 ratio,
2333                 Ratio::new(
2334                     FromStr::from_str(numer).unwrap(),
2335                     FromStr::from_str(denom).unwrap()
2336                 )
2337             );
2338         }
2339 
2340         // f32
2341         test(3.14159265359f32, ("13176795", "4194304"));
2342         test(2f32.powf(100.), ("1267650600228229401496703205376", "1"));
2343         test(-2f32.powf(100.), ("-1267650600228229401496703205376", "1"));
2344         test(
2345             1.0 / 2f32.powf(100.),
2346             ("1", "1267650600228229401496703205376"),
2347         );
2348         test(684729.48391f32, ("1369459", "2"));
2349         test(-8573.5918555f32, ("-4389679", "512"));
2350 
2351         // f64
2352         test(3.14159265359f64, ("3537118876014453", "1125899906842624"));
2353         test(2f64.powf(100.), ("1267650600228229401496703205376", "1"));
2354         test(-2f64.powf(100.), ("-1267650600228229401496703205376", "1"));
2355         test(684729.48391f64, ("367611342500051", "536870912"));
2356         test(-8573.5918555f64, ("-4713381968463931", "549755813888"));
2357         test(
2358             1.0 / 2f64.powf(100.),
2359             ("1", "1267650600228229401496703205376"),
2360         );
2361     }
2362 
2363     #[cfg(feature = "bigint")]
2364     #[test]
test_from_float_fail()2365     fn test_from_float_fail() {
2366         use core::{f32, f64};
2367 
2368         assert_eq!(Ratio::from_float(f32::NAN), None);
2369         assert_eq!(Ratio::from_float(f32::INFINITY), None);
2370         assert_eq!(Ratio::from_float(f32::NEG_INFINITY), None);
2371         assert_eq!(Ratio::from_float(f64::NAN), None);
2372         assert_eq!(Ratio::from_float(f64::INFINITY), None);
2373         assert_eq!(Ratio::from_float(f64::NEG_INFINITY), None);
2374     }
2375 
2376     #[test]
test_signed()2377     fn test_signed() {
2378         assert_eq!(_NEG1_2.abs(), _1_2);
2379         assert_eq!(_3_2.abs_sub(&_1_2), _1);
2380         assert_eq!(_1_2.abs_sub(&_3_2), Zero::zero());
2381         assert_eq!(_1_2.signum(), One::one());
2382         assert_eq!(_NEG1_2.signum(), -<Ratio<isize>>::one());
2383         assert_eq!(_0.signum(), Zero::zero());
2384         assert!(_NEG1_2.is_negative());
2385         assert!(_1_NEG2.is_negative());
2386         assert!(!_NEG1_2.is_positive());
2387         assert!(!_1_NEG2.is_positive());
2388         assert!(_1_2.is_positive());
2389         assert!(_NEG1_NEG2.is_positive());
2390         assert!(!_1_2.is_negative());
2391         assert!(!_NEG1_NEG2.is_negative());
2392         assert!(!_0.is_positive());
2393         assert!(!_0.is_negative());
2394     }
2395 
2396     #[test]
2397     #[cfg(feature = "std")]
test_hash()2398     fn test_hash() {
2399         assert!(::hash(&_0) != ::hash(&_1));
2400         assert!(::hash(&_0) != ::hash(&_3_2));
2401 
2402         // a == b -> hash(a) == hash(b)
2403         let a = Rational::new_raw(4, 2);
2404         let b = Rational::new_raw(6, 3);
2405         assert_eq!(a, b);
2406         assert_eq!(::hash(&a), ::hash(&b));
2407 
2408         let a = Rational::new_raw(123456789, 1000);
2409         let b = Rational::new_raw(123456789 * 5, 5000);
2410         assert_eq!(a, b);
2411         assert_eq!(::hash(&a), ::hash(&b));
2412     }
2413 
2414     #[test]
test_into_pair()2415     fn test_into_pair() {
2416         assert_eq!((0, 1), _0.into());
2417         assert_eq!((-2, 1), _NEG2.into());
2418         assert_eq!((1, -2), _1_NEG2.into());
2419     }
2420 
2421     #[test]
test_from_pair()2422     fn test_from_pair() {
2423         assert_eq!(_0, Ratio::from((0, 1)));
2424         assert_eq!(_1, Ratio::from((1, 1)));
2425         assert_eq!(_NEG2, Ratio::from((-2, 1)));
2426         assert_eq!(_1_NEG2, Ratio::from((1, -2)));
2427     }
2428 
2429     #[test]
ratio_iter_sum()2430     fn ratio_iter_sum() {
2431         // generic function to assure the iter method can be called
2432         // for any Iterator with Item = Ratio<impl Integer> or Ratio<&impl Integer>
2433         fn iter_sums<T: Integer + Clone>(slice: &[Ratio<T>]) -> [Ratio<T>; 3] {
2434             let mut manual_sum = Ratio::new(T::zero(), T::one());
2435             for ratio in slice {
2436                 manual_sum = manual_sum + ratio;
2437             }
2438             [manual_sum, slice.iter().sum(), slice.iter().cloned().sum()]
2439         }
2440         // collect into array so test works on no_std
2441         let mut nums = [Ratio::new(0, 1); 1000];
2442         for (i, r) in (0..1000).map(|n| Ratio::new(n, 500)).enumerate() {
2443             nums[i] = r;
2444         }
2445         let sums = iter_sums(&nums[..]);
2446         assert_eq!(sums[0], sums[1]);
2447         assert_eq!(sums[0], sums[2]);
2448     }
2449 
2450     #[test]
ratio_iter_product()2451     fn ratio_iter_product() {
2452         // generic function to assure the iter method can be called
2453         // for any Iterator with Item = Ratio<impl Integer> or Ratio<&impl Integer>
2454         fn iter_products<T: Integer + Clone>(slice: &[Ratio<T>]) -> [Ratio<T>; 3] {
2455             let mut manual_prod = Ratio::new(T::one(), T::one());
2456             for ratio in slice {
2457                 manual_prod = manual_prod * ratio;
2458             }
2459             [
2460                 manual_prod,
2461                 slice.iter().product(),
2462                 slice.iter().cloned().product(),
2463             ]
2464         }
2465 
2466         // collect into array so test works on no_std
2467         let mut nums = [Ratio::new(0, 1); 1000];
2468         for (i, r) in (0..1000).map(|n| Ratio::new(n, 500)).enumerate() {
2469             nums[i] = r;
2470         }
2471         let products = iter_products(&nums[..]);
2472         assert_eq!(products[0], products[1]);
2473         assert_eq!(products[0], products[2]);
2474     }
2475 
2476     #[test]
test_num_zero()2477     fn test_num_zero() {
2478         let zero = Rational64::zero();
2479         assert!(zero.is_zero());
2480 
2481         let mut r = Rational64::new(123, 456);
2482         assert!(!r.is_zero());
2483         assert_eq!(&r + &zero, r);
2484 
2485         r.set_zero();
2486         assert!(r.is_zero());
2487     }
2488 
2489     #[test]
test_num_one()2490     fn test_num_one() {
2491         let one = Rational64::one();
2492         assert!(one.is_one());
2493 
2494         let mut r = Rational64::new(123, 456);
2495         assert!(!r.is_one());
2496         assert_eq!(&r * &one, r);
2497 
2498         r.set_one();
2499         assert!(r.is_one());
2500     }
2501 
2502     #[cfg(has_const_fn)]
2503     #[test]
test_const()2504     fn test_const() {
2505         const N: Ratio<i32> = Ratio::new_raw(123, 456);
2506         const N_NUMER: &i32 = N.numer();
2507         const N_DENOM: &i32 = N.denom();
2508 
2509         assert_eq!(N_NUMER, &123);
2510         assert_eq!(N_DENOM, &456);
2511 
2512         let r = N.reduced();
2513         assert_eq!(r.numer(), &(123 / 3));
2514         assert_eq!(r.denom(), &(456 / 3));
2515     }
2516 }
2517