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