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.31 and greater.
16 
17 #![doc(html_root_url = "https://docs.rs/num-rational/0.4")]
18 #![no_std]
19 // Ratio ops often use other "suspicious" ops
20 #![allow(clippy::suspicious_arithmetic_impl)]
21 #![allow(clippy::suspicious_op_assign_impl)]
22 
23 #[cfg(feature = "std")]
24 #[macro_use]
25 extern crate std;
26 
27 use core::cmp;
28 use core::fmt;
29 use core::fmt::{Binary, Display, Formatter, LowerExp, LowerHex, Octal, UpperExp, UpperHex};
30 use core::hash::{Hash, Hasher};
31 use core::ops::{Add, Div, Mul, Neg, Rem, ShlAssign, Sub};
32 use core::str::FromStr;
33 #[cfg(feature = "std")]
34 use std::error::Error;
35 
36 #[cfg(feature = "num-bigint")]
37 use num_bigint::{BigInt, BigUint, Sign, ToBigInt};
38 
39 use num_integer::Integer;
40 use num_traits::float::FloatCore;
41 use num_traits::ToPrimitive;
42 use num_traits::{
43     Bounded, CheckedAdd, CheckedDiv, CheckedMul, CheckedSub, FromPrimitive, Inv, Num, NumCast, One,
44     Pow, Signed, Zero,
45 };
46 
47 mod pow;
48 
49 /// Represents the ratio between two numbers.
50 #[derive(Copy, Clone, Debug)]
51 #[allow(missing_docs)]
52 pub struct Ratio<T> {
53     /// Numerator.
54     numer: T,
55     /// Denominator.
56     denom: T,
57 }
58 
59 /// Alias for a `Ratio` of machine-sized integers.
60 #[deprecated(
61     since = "0.4.0",
62     note = "it's better to use a specific size, like `Rational32` or `Rational64`"
63 )]
64 pub type Rational = Ratio<isize>;
65 /// Alias for a `Ratio` of 32-bit-sized integers.
66 pub type Rational32 = Ratio<i32>;
67 /// Alias for a `Ratio` of 64-bit-sized integers.
68 pub type Rational64 = Ratio<i64>;
69 
70 #[cfg(feature = "num-bigint")]
71 /// Alias for arbitrary precision rationals.
72 pub type BigRational = Ratio<BigInt>;
73 
74 /// These method are `const` for Rust 1.31 and later.
75 impl<T> Ratio<T> {
76     /// Creates a `Ratio` without checking for `denom == 0` or reducing.
77     ///
78     /// **There are several methods that will panic if used on a `Ratio` with
79     /// `denom == 0`.**
80     #[inline]
new_raw(numer: T, denom: T) -> Ratio<T>81     pub const fn new_raw(numer: T, denom: T) -> Ratio<T> {
82         Ratio { numer, denom }
83     }
84 
85     /// Gets an immutable reference to the numerator.
86     #[inline]
numer(&self) -> &T87     pub const fn numer(&self) -> &T {
88         &self.numer
89     }
90 
91     /// Gets an immutable reference to the denominator.
92     #[inline]
denom(&self) -> &T93     pub const fn denom(&self) -> &T {
94         &self.denom
95     }
96 }
97 
98 impl<T: Clone + Integer> Ratio<T> {
99     /// Creates a new `Ratio`.
100     ///
101     /// **Panics if `denom` is zero.**
102     #[inline]
new(numer: T, denom: T) -> Ratio<T>103     pub fn new(numer: T, denom: T) -> Ratio<T> {
104         let mut ret = Ratio::new_raw(numer, denom);
105         ret.reduce();
106         ret
107     }
108 
109     /// Creates a `Ratio` representing the integer `t`.
110     #[inline]
from_integer(t: T) -> Ratio<T>111     pub fn from_integer(t: T) -> Ratio<T> {
112         Ratio::new_raw(t, One::one())
113     }
114 
115     /// Converts to an integer, rounding towards zero.
116     #[inline]
to_integer(&self) -> T117     pub fn to_integer(&self) -> T {
118         self.trunc().numer
119     }
120 
121     /// Returns true if the rational number is an integer (denominator is 1).
122     #[inline]
is_integer(&self) -> bool123     pub fn is_integer(&self) -> bool {
124         self.denom.is_one()
125     }
126 
127     /// Puts self into lowest terms, with `denom` > 0.
128     ///
129     /// **Panics if `denom` is zero.**
reduce(&mut self)130     fn reduce(&mut self) {
131         if self.denom.is_zero() {
132             panic!("denominator == 0");
133         }
134         if self.numer.is_zero() {
135             self.denom.set_one();
136             return;
137         }
138         if self.numer == self.denom {
139             self.set_one();
140             return;
141         }
142         let g: T = self.numer.gcd(&self.denom);
143 
144         // FIXME(#5992): assignment operator overloads
145         // self.numer /= g;
146         // T: Clone + Integer != T: Clone + NumAssign
147         self.numer = self.numer.clone() / g.clone();
148         // FIXME(#5992): assignment operator overloads
149         // self.denom /= g;
150         // T: Clone + Integer != T: Clone + NumAssign
151         self.denom = self.denom.clone() / g;
152 
153         // keep denom positive!
154         if self.denom < T::zero() {
155             self.numer = T::zero() - self.numer.clone();
156             self.denom = T::zero() - self.denom.clone();
157         }
158     }
159 
160     /// Returns a reduced copy of self.
161     ///
162     /// In general, it is not necessary to use this method, as the only
163     /// method of procuring a non-reduced fraction is through `new_raw`.
164     ///
165     /// **Panics if `denom` is zero.**
reduced(&self) -> Ratio<T>166     pub fn reduced(&self) -> Ratio<T> {
167         let mut ret = self.clone();
168         ret.reduce();
169         ret
170     }
171 
172     /// Returns the reciprocal.
173     ///
174     /// **Panics if the `Ratio` is zero.**
175     #[inline]
recip(&self) -> Ratio<T>176     pub fn recip(&self) -> Ratio<T> {
177         self.clone().into_recip()
178     }
179 
180     #[inline]
into_recip(self) -> Ratio<T>181     fn into_recip(self) -> Ratio<T> {
182         match self.numer.cmp(&T::zero()) {
183             cmp::Ordering::Equal => panic!("division by zero"),
184             cmp::Ordering::Greater => Ratio::new_raw(self.denom, self.numer),
185             cmp::Ordering::Less => Ratio::new_raw(T::zero() - self.denom, T::zero() - self.numer),
186         }
187     }
188 
189     /// Rounds towards minus infinity.
190     #[inline]
floor(&self) -> Ratio<T>191     pub fn floor(&self) -> Ratio<T> {
192         if *self < Zero::zero() {
193             let one: T = One::one();
194             Ratio::from_integer(
195                 (self.numer.clone() - self.denom.clone() + one) / self.denom.clone(),
196             )
197         } else {
198             Ratio::from_integer(self.numer.clone() / self.denom.clone())
199         }
200     }
201 
202     /// Rounds towards plus infinity.
203     #[inline]
ceil(&self) -> Ratio<T>204     pub fn ceil(&self) -> Ratio<T> {
205         if *self < Zero::zero() {
206             Ratio::from_integer(self.numer.clone() / self.denom.clone())
207         } else {
208             let one: T = One::one();
209             Ratio::from_integer(
210                 (self.numer.clone() + self.denom.clone() - one) / self.denom.clone(),
211             )
212         }
213     }
214 
215     /// Rounds to the nearest integer. Rounds half-way cases away from zero.
216     #[inline]
round(&self) -> Ratio<T>217     pub fn round(&self) -> Ratio<T> {
218         let zero: Ratio<T> = Zero::zero();
219         let one: T = One::one();
220         let two: T = one.clone() + one.clone();
221 
222         // Find unsigned fractional part of rational number
223         let mut fractional = self.fract();
224         if fractional < zero {
225             fractional = zero - fractional
226         };
227 
228         // The algorithm compares the unsigned fractional part with 1/2, that
229         // is, a/b >= 1/2, or a >= b/2. For odd denominators, we use
230         // a >= (b/2)+1. This avoids overflow issues.
231         let half_or_larger = if fractional.denom.is_even() {
232             fractional.numer >= fractional.denom / two
233         } else {
234             fractional.numer >= (fractional.denom / two) + one
235         };
236 
237         if half_or_larger {
238             let one: Ratio<T> = One::one();
239             if *self >= Zero::zero() {
240                 self.trunc() + one
241             } else {
242                 self.trunc() - one
243             }
244         } else {
245             self.trunc()
246         }
247     }
248 
249     /// Rounds towards zero.
250     #[inline]
trunc(&self) -> Ratio<T>251     pub fn trunc(&self) -> Ratio<T> {
252         Ratio::from_integer(self.numer.clone() / self.denom.clone())
253     }
254 
255     /// Returns the fractional part of a number, with division rounded towards zero.
256     ///
257     /// Satisfies `self == self.trunc() + self.fract()`.
258     #[inline]
fract(&self) -> Ratio<T>259     pub fn fract(&self) -> Ratio<T> {
260         Ratio::new_raw(self.numer.clone() % self.denom.clone(), self.denom.clone())
261     }
262 
263     /// Raises the `Ratio` to the power of an exponent.
264     #[inline]
pow(&self, expon: i32) -> Ratio<T> where for<'a> &'a T: Pow<u32, Output = T>,265     pub fn pow(&self, expon: i32) -> Ratio<T>
266     where
267         for<'a> &'a T: Pow<u32, Output = T>,
268     {
269         Pow::pow(self, expon)
270     }
271 }
272 
273 #[cfg(feature = "num-bigint")]
274 impl Ratio<BigInt> {
275     /// Converts a float into a rational number.
from_float<T: FloatCore>(f: T) -> Option<BigRational>276     pub fn from_float<T: FloatCore>(f: T) -> Option<BigRational> {
277         if !f.is_finite() {
278             return None;
279         }
280         let (mantissa, exponent, sign) = f.integer_decode();
281         let bigint_sign = if sign == 1 { Sign::Plus } else { Sign::Minus };
282         if exponent < 0 {
283             let one: BigInt = One::one();
284             let denom: BigInt = one << ((-exponent) as usize);
285             let numer: BigUint = FromPrimitive::from_u64(mantissa).unwrap();
286             Some(Ratio::new(BigInt::from_biguint(bigint_sign, numer), denom))
287         } else {
288             let mut numer: BigUint = FromPrimitive::from_u64(mantissa).unwrap();
289             numer <<= exponent as usize;
290             Some(Ratio::from_integer(BigInt::from_biguint(
291                 bigint_sign,
292                 numer,
293             )))
294         }
295     }
296 }
297 
298 // From integer
299 impl<T> From<T> for Ratio<T>
300 where
301     T: Clone + Integer,
302 {
from(x: T) -> Ratio<T>303     fn from(x: T) -> Ratio<T> {
304         Ratio::from_integer(x)
305     }
306 }
307 
308 // From pair (through the `new` constructor)
309 impl<T> From<(T, T)> for Ratio<T>
310 where
311     T: Clone + Integer,
312 {
from(pair: (T, T)) -> Ratio<T>313     fn from(pair: (T, T)) -> Ratio<T> {
314         Ratio::new(pair.0, pair.1)
315     }
316 }
317 
318 // Comparisons
319 
320 // Mathematically, comparing a/b and c/d is the same as comparing a*d and b*c, but it's very easy
321 // for those multiplications to overflow fixed-size integers, so we need to take care.
322 
323 impl<T: Clone + Integer> Ord for Ratio<T> {
324     #[inline]
cmp(&self, other: &Self) -> cmp::Ordering325     fn cmp(&self, other: &Self) -> cmp::Ordering {
326         // With equal denominators, the numerators can be directly compared
327         if self.denom == other.denom {
328             let ord = self.numer.cmp(&other.numer);
329             return if self.denom < T::zero() {
330                 ord.reverse()
331             } else {
332                 ord
333             };
334         }
335 
336         // With equal numerators, the denominators can be inversely compared
337         if self.numer == other.numer {
338             if self.numer.is_zero() {
339                 return cmp::Ordering::Equal;
340             }
341             let ord = self.denom.cmp(&other.denom);
342             return if self.numer < T::zero() {
343                 ord
344             } else {
345                 ord.reverse()
346             };
347         }
348 
349         // Unfortunately, we don't have CheckedMul to try.  That could sometimes avoid all the
350         // division below, or even always avoid it for BigInt and BigUint.
351         // FIXME- future breaking change to add Checked* to Integer?
352 
353         // Compare as floored integers and remainders
354         let (self_int, self_rem) = self.numer.div_mod_floor(&self.denom);
355         let (other_int, other_rem) = other.numer.div_mod_floor(&other.denom);
356         match self_int.cmp(&other_int) {
357             cmp::Ordering::Greater => cmp::Ordering::Greater,
358             cmp::Ordering::Less => cmp::Ordering::Less,
359             cmp::Ordering::Equal => {
360                 match (self_rem.is_zero(), other_rem.is_zero()) {
361                     (true, true) => cmp::Ordering::Equal,
362                     (true, false) => cmp::Ordering::Less,
363                     (false, true) => cmp::Ordering::Greater,
364                     (false, false) => {
365                         // Compare the reciprocals of the remaining fractions in reverse
366                         let self_recip = Ratio::new_raw(self.denom.clone(), self_rem);
367                         let other_recip = Ratio::new_raw(other.denom.clone(), other_rem);
368                         self_recip.cmp(&other_recip).reverse()
369                     }
370                 }
371             }
372         }
373     }
374 }
375 
376 impl<T: Clone + Integer> PartialOrd for Ratio<T> {
377     #[inline]
partial_cmp(&self, other: &Self) -> Option<cmp::Ordering>378     fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
379         Some(self.cmp(other))
380     }
381 }
382 
383 impl<T: Clone + Integer> PartialEq for Ratio<T> {
384     #[inline]
eq(&self, other: &Self) -> bool385     fn eq(&self, other: &Self) -> bool {
386         self.cmp(other) == cmp::Ordering::Equal
387     }
388 }
389 
390 impl<T: Clone + Integer> Eq for Ratio<T> {}
391 
392 // NB: We can't just `#[derive(Hash)]`, because it needs to agree
393 // with `Eq` even for non-reduced ratios.
394 impl<T: Clone + Integer + Hash> Hash for Ratio<T> {
hash<H: Hasher>(&self, state: &mut H)395     fn hash<H: Hasher>(&self, state: &mut H) {
396         recurse(&self.numer, &self.denom, state);
397 
398         fn recurse<T: Integer + Hash, H: Hasher>(numer: &T, denom: &T, state: &mut H) {
399             if !denom.is_zero() {
400                 let (int, rem) = numer.div_mod_floor(denom);
401                 int.hash(state);
402                 recurse(denom, &rem, state);
403             } else {
404                 denom.hash(state);
405             }
406         }
407     }
408 }
409 
410 mod iter_sum_product {
411     use crate::Ratio;
412     use core::iter::{Product, Sum};
413     use num_integer::Integer;
414     use num_traits::{One, Zero};
415 
416     impl<T: Integer + Clone> Sum for Ratio<T> {
sum<I>(iter: I) -> Self where I: Iterator<Item = Ratio<T>>,417         fn sum<I>(iter: I) -> Self
418         where
419             I: Iterator<Item = Ratio<T>>,
420         {
421             iter.fold(Self::zero(), |sum, num| sum + num)
422         }
423     }
424 
425     impl<'a, T: Integer + Clone> Sum<&'a Ratio<T>> for Ratio<T> {
sum<I>(iter: I) -> Self where I: Iterator<Item = &'a Ratio<T>>,426         fn sum<I>(iter: I) -> Self
427         where
428             I: Iterator<Item = &'a Ratio<T>>,
429         {
430             iter.fold(Self::zero(), |sum, num| sum + num)
431         }
432     }
433 
434     impl<T: Integer + Clone> Product for Ratio<T> {
product<I>(iter: I) -> Self where I: Iterator<Item = Ratio<T>>,435         fn product<I>(iter: I) -> Self
436         where
437             I: Iterator<Item = Ratio<T>>,
438         {
439             iter.fold(Self::one(), |prod, num| prod * num)
440         }
441     }
442 
443     impl<'a, T: Integer + Clone> Product<&'a Ratio<T>> for Ratio<T> {
product<I>(iter: I) -> Self where I: Iterator<Item = &'a Ratio<T>>,444         fn product<I>(iter: I) -> Self
445         where
446             I: Iterator<Item = &'a Ratio<T>>,
447         {
448             iter.fold(Self::one(), |prod, num| prod * num)
449         }
450     }
451 }
452 
453 mod opassign {
454     use core::ops::{AddAssign, DivAssign, MulAssign, RemAssign, SubAssign};
455 
456     use crate::Ratio;
457     use num_integer::Integer;
458     use num_traits::NumAssign;
459 
460     impl<T: Clone + Integer + NumAssign> AddAssign for Ratio<T> {
add_assign(&mut self, other: Ratio<T>)461         fn add_assign(&mut self, other: Ratio<T>) {
462             if self.denom == other.denom {
463                 self.numer += other.numer
464             } else {
465                 let lcm = self.denom.lcm(&other.denom);
466                 let lhs_numer = self.numer.clone() * (lcm.clone() / self.denom.clone());
467                 let rhs_numer = other.numer * (lcm.clone() / other.denom);
468                 self.numer = lhs_numer + rhs_numer;
469                 self.denom = lcm;
470             }
471             self.reduce();
472         }
473     }
474 
475     // (a/b) / (c/d) = (a/gcd_ac)*(d/gcd_bd) / ((c/gcd_ac)*(b/gcd_bd))
476     impl<T: Clone + Integer + NumAssign> DivAssign for Ratio<T> {
div_assign(&mut self, other: Ratio<T>)477         fn div_assign(&mut self, other: Ratio<T>) {
478             let gcd_ac = self.numer.gcd(&other.numer);
479             let gcd_bd = self.denom.gcd(&other.denom);
480             self.numer /= gcd_ac.clone();
481             self.numer *= other.denom / gcd_bd.clone();
482             self.denom /= gcd_bd;
483             self.denom *= other.numer / gcd_ac;
484             self.reduce(); // TODO: remove this line. see #8.
485         }
486     }
487 
488     // a/b * c/d = (a/gcd_ad)*(c/gcd_bc) / ((d/gcd_ad)*(b/gcd_bc))
489     impl<T: Clone + Integer + NumAssign> MulAssign for Ratio<T> {
mul_assign(&mut self, other: Ratio<T>)490         fn mul_assign(&mut self, other: Ratio<T>) {
491             let gcd_ad = self.numer.gcd(&other.denom);
492             let gcd_bc = self.denom.gcd(&other.numer);
493             self.numer /= gcd_ad.clone();
494             self.numer *= other.numer / gcd_bc.clone();
495             self.denom /= gcd_bc;
496             self.denom *= other.denom / gcd_ad;
497             self.reduce(); // TODO: remove this line. see #8.
498         }
499     }
500 
501     impl<T: Clone + Integer + NumAssign> RemAssign for Ratio<T> {
rem_assign(&mut self, other: Ratio<T>)502         fn rem_assign(&mut self, other: Ratio<T>) {
503             if self.denom == other.denom {
504                 self.numer %= other.numer
505             } else {
506                 let lcm = self.denom.lcm(&other.denom);
507                 let lhs_numer = self.numer.clone() * (lcm.clone() / self.denom.clone());
508                 let rhs_numer = other.numer * (lcm.clone() / other.denom);
509                 self.numer = lhs_numer % rhs_numer;
510                 self.denom = lcm;
511             }
512             self.reduce();
513         }
514     }
515 
516     impl<T: Clone + Integer + NumAssign> SubAssign for Ratio<T> {
sub_assign(&mut self, other: Ratio<T>)517         fn sub_assign(&mut self, other: Ratio<T>) {
518             if self.denom == other.denom {
519                 self.numer -= other.numer
520             } else {
521                 let lcm = self.denom.lcm(&other.denom);
522                 let lhs_numer = self.numer.clone() * (lcm.clone() / self.denom.clone());
523                 let rhs_numer = other.numer * (lcm.clone() / other.denom);
524                 self.numer = lhs_numer - rhs_numer;
525                 self.denom = lcm;
526             }
527             self.reduce();
528         }
529     }
530 
531     // a/b + c/1 = (a*1 + b*c) / (b*1) = (a + b*c) / b
532     impl<T: Clone + Integer + NumAssign> AddAssign<T> for Ratio<T> {
add_assign(&mut self, other: T)533         fn add_assign(&mut self, other: T) {
534             self.numer += self.denom.clone() * other;
535             self.reduce();
536         }
537     }
538 
539     impl<T: Clone + Integer + NumAssign> DivAssign<T> for Ratio<T> {
div_assign(&mut self, other: T)540         fn div_assign(&mut self, other: T) {
541             let gcd = self.numer.gcd(&other);
542             self.numer /= gcd.clone();
543             self.denom *= other / gcd;
544             self.reduce(); // TODO: remove this line. see #8.
545         }
546     }
547 
548     impl<T: Clone + Integer + NumAssign> MulAssign<T> for Ratio<T> {
mul_assign(&mut self, other: T)549         fn mul_assign(&mut self, other: T) {
550             let gcd = self.denom.gcd(&other);
551             self.denom /= gcd.clone();
552             self.numer *= other / gcd;
553             self.reduce(); // TODO: remove this line. see #8.
554         }
555     }
556 
557     // a/b % c/1 = (a*1 % b*c) / (b*1) = (a % b*c) / b
558     impl<T: Clone + Integer + NumAssign> RemAssign<T> for Ratio<T> {
rem_assign(&mut self, other: T)559         fn rem_assign(&mut self, other: T) {
560             self.numer %= self.denom.clone() * other;
561             self.reduce();
562         }
563     }
564 
565     // a/b - c/1 = (a*1 - b*c) / (b*1) = (a - b*c) / b
566     impl<T: Clone + Integer + NumAssign> SubAssign<T> for Ratio<T> {
sub_assign(&mut self, other: T)567         fn sub_assign(&mut self, other: T) {
568             self.numer -= self.denom.clone() * other;
569             self.reduce();
570         }
571     }
572 
573     macro_rules! forward_op_assign {
574         (impl $imp:ident, $method:ident) => {
575             impl<'a, T: Clone + Integer + NumAssign> $imp<&'a Ratio<T>> for Ratio<T> {
576                 #[inline]
577                 fn $method(&mut self, other: &Ratio<T>) {
578                     self.$method(other.clone())
579                 }
580             }
581             impl<'a, T: Clone + Integer + NumAssign> $imp<&'a T> for Ratio<T> {
582                 #[inline]
583                 fn $method(&mut self, other: &T) {
584                     self.$method(other.clone())
585                 }
586             }
587         };
588     }
589 
590     forward_op_assign!(impl AddAssign, add_assign);
591     forward_op_assign!(impl DivAssign, div_assign);
592     forward_op_assign!(impl MulAssign, mul_assign);
593     forward_op_assign!(impl RemAssign, rem_assign);
594     forward_op_assign!(impl SubAssign, sub_assign);
595 }
596 
597 macro_rules! forward_ref_ref_binop {
598     (impl $imp:ident, $method:ident) => {
599         impl<'a, 'b, T: Clone + Integer> $imp<&'b Ratio<T>> for &'a Ratio<T> {
600             type Output = Ratio<T>;
601 
602             #[inline]
603             fn $method(self, other: &'b Ratio<T>) -> Ratio<T> {
604                 self.clone().$method(other.clone())
605             }
606         }
607         impl<'a, 'b, T: Clone + Integer> $imp<&'b T> for &'a Ratio<T> {
608             type Output = Ratio<T>;
609 
610             #[inline]
611             fn $method(self, other: &'b T) -> Ratio<T> {
612                 self.clone().$method(other.clone())
613             }
614         }
615     };
616 }
617 
618 macro_rules! forward_ref_val_binop {
619     (impl $imp:ident, $method:ident) => {
620         impl<'a, T> $imp<Ratio<T>> for &'a Ratio<T>
621         where
622             T: Clone + Integer,
623         {
624             type Output = Ratio<T>;
625 
626             #[inline]
627             fn $method(self, other: Ratio<T>) -> Ratio<T> {
628                 self.clone().$method(other)
629             }
630         }
631         impl<'a, T> $imp<T> for &'a Ratio<T>
632         where
633             T: Clone + Integer,
634         {
635             type Output = Ratio<T>;
636 
637             #[inline]
638             fn $method(self, other: T) -> Ratio<T> {
639                 self.clone().$method(other)
640             }
641         }
642     };
643 }
644 
645 macro_rules! forward_val_ref_binop {
646     (impl $imp:ident, $method:ident) => {
647         impl<'a, T> $imp<&'a Ratio<T>> for Ratio<T>
648         where
649             T: Clone + Integer,
650         {
651             type Output = Ratio<T>;
652 
653             #[inline]
654             fn $method(self, other: &Ratio<T>) -> Ratio<T> {
655                 self.$method(other.clone())
656             }
657         }
658         impl<'a, T> $imp<&'a T> for Ratio<T>
659         where
660             T: Clone + Integer,
661         {
662             type Output = Ratio<T>;
663 
664             #[inline]
665             fn $method(self, other: &T) -> Ratio<T> {
666                 self.$method(other.clone())
667             }
668         }
669     };
670 }
671 
672 macro_rules! forward_all_binop {
673     (impl $imp:ident, $method:ident) => {
674         forward_ref_ref_binop!(impl $imp, $method);
675         forward_ref_val_binop!(impl $imp, $method);
676         forward_val_ref_binop!(impl $imp, $method);
677     };
678 }
679 
680 // Arithmetic
681 forward_all_binop!(impl Mul, mul);
682 // a/b * c/d = (a/gcd_ad)*(c/gcd_bc) / ((d/gcd_ad)*(b/gcd_bc))
683 impl<T> Mul<Ratio<T>> for Ratio<T>
684 where
685     T: Clone + Integer,
686 {
687     type Output = Ratio<T>;
688     #[inline]
mul(self, rhs: Ratio<T>) -> Ratio<T>689     fn mul(self, rhs: Ratio<T>) -> Ratio<T> {
690         let gcd_ad = self.numer.gcd(&rhs.denom);
691         let gcd_bc = self.denom.gcd(&rhs.numer);
692         Ratio::new(
693             self.numer / gcd_ad.clone() * (rhs.numer / gcd_bc.clone()),
694             self.denom / gcd_bc * (rhs.denom / gcd_ad),
695         )
696     }
697 }
698 // a/b * c/1 = (a*c) / (b*1) = (a*c) / b
699 impl<T> Mul<T> for Ratio<T>
700 where
701     T: Clone + Integer,
702 {
703     type Output = Ratio<T>;
704     #[inline]
mul(self, rhs: T) -> Ratio<T>705     fn mul(self, rhs: T) -> Ratio<T> {
706         let gcd = self.denom.gcd(&rhs);
707         Ratio::new(self.numer * (rhs / gcd.clone()), self.denom / gcd)
708     }
709 }
710 
711 forward_all_binop!(impl Div, div);
712 // (a/b) / (c/d) = (a/gcd_ac)*(d/gcd_bd) / ((c/gcd_ac)*(b/gcd_bd))
713 impl<T> Div<Ratio<T>> for Ratio<T>
714 where
715     T: Clone + Integer,
716 {
717     type Output = Ratio<T>;
718 
719     #[inline]
div(self, rhs: Ratio<T>) -> Ratio<T>720     fn div(self, rhs: Ratio<T>) -> Ratio<T> {
721         let gcd_ac = self.numer.gcd(&rhs.numer);
722         let gcd_bd = self.denom.gcd(&rhs.denom);
723         Ratio::new(
724             self.numer / gcd_ac.clone() * (rhs.denom / gcd_bd.clone()),
725             self.denom / gcd_bd * (rhs.numer / gcd_ac),
726         )
727     }
728 }
729 // (a/b) / (c/1) = (a*1) / (b*c) = a / (b*c)
730 impl<T> Div<T> for Ratio<T>
731 where
732     T: Clone + Integer,
733 {
734     type Output = Ratio<T>;
735 
736     #[inline]
div(self, rhs: T) -> Ratio<T>737     fn div(self, rhs: T) -> Ratio<T> {
738         let gcd = self.numer.gcd(&rhs);
739         Ratio::new(self.numer / gcd.clone(), self.denom * (rhs / gcd))
740     }
741 }
742 
743 macro_rules! arith_impl {
744     (impl $imp:ident, $method:ident) => {
745         forward_all_binop!(impl $imp, $method);
746         // Abstracts a/b `op` c/d = (a*lcm/b `op` c*lcm/d)/lcm where lcm = lcm(b,d)
747         impl<T: Clone + Integer> $imp<Ratio<T>> for Ratio<T> {
748             type Output = Ratio<T>;
749             #[inline]
750             fn $method(self, rhs: Ratio<T>) -> Ratio<T> {
751                 if self.denom == rhs.denom {
752                     return Ratio::new(self.numer.$method(rhs.numer), rhs.denom);
753                 }
754                 let lcm = self.denom.lcm(&rhs.denom);
755                 let lhs_numer = self.numer * (lcm.clone() / self.denom);
756                 let rhs_numer = rhs.numer * (lcm.clone() / rhs.denom);
757                 Ratio::new(lhs_numer.$method(rhs_numer), lcm)
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 // a/b * c/d = (a*c)/(b*d)
776 impl<T> CheckedMul for Ratio<T>
777 where
778     T: Clone + Integer + CheckedMul,
779 {
780     #[inline]
checked_mul(&self, rhs: &Ratio<T>) -> Option<Ratio<T>>781     fn checked_mul(&self, rhs: &Ratio<T>) -> Option<Ratio<T>> {
782         let gcd_ad = self.numer.gcd(&rhs.denom);
783         let gcd_bc = self.denom.gcd(&rhs.numer);
784         Some(Ratio::new(
785             (self.numer.clone() / gcd_ad.clone())
786                 .checked_mul(&(rhs.numer.clone() / gcd_bc.clone()))?,
787             (self.denom.clone() / gcd_bc).checked_mul(&(rhs.denom.clone() / gcd_ad))?,
788         ))
789     }
790 }
791 
792 // (a/b) / (c/d) = (a*d)/(b*c)
793 impl<T> CheckedDiv for Ratio<T>
794 where
795     T: Clone + Integer + CheckedMul,
796 {
797     #[inline]
checked_div(&self, rhs: &Ratio<T>) -> Option<Ratio<T>>798     fn checked_div(&self, rhs: &Ratio<T>) -> Option<Ratio<T>> {
799         if rhs.is_zero() {
800             return None;
801         }
802         let (numer, denom) = if self.denom == rhs.denom {
803             (self.numer.clone(), rhs.numer.clone())
804         } else if self.numer == rhs.numer {
805             (rhs.denom.clone(), self.denom.clone())
806         } else {
807             let gcd_ac = self.numer.gcd(&rhs.numer);
808             let gcd_bd = self.denom.gcd(&rhs.denom);
809             (
810                 (self.numer.clone() / gcd_ac.clone())
811                     .checked_mul(&(rhs.denom.clone() / gcd_bd.clone()))?,
812                 (self.denom.clone() / gcd_bd).checked_mul(&(rhs.numer.clone() / gcd_ac))?,
813             )
814         };
815         // Manual `reduce()`, avoiding sharp edges
816         if denom.is_zero() {
817             None
818         } else if numer.is_zero() {
819             Some(Self::zero())
820         } else if numer == denom {
821             Some(Self::one())
822         } else {
823             let g = numer.gcd(&denom);
824             let numer = numer / g.clone();
825             let denom = denom / g;
826             let raw = if denom < T::zero() {
827                 // We need to keep denom positive, but 2's-complement MIN may
828                 // overflow negation -- instead we can check multiplying -1.
829                 let n1 = T::zero() - T::one();
830                 Ratio::new_raw(numer.checked_mul(&n1)?, denom.checked_mul(&n1)?)
831             } else {
832                 Ratio::new_raw(numer, denom)
833             };
834             Some(raw)
835         }
836     }
837 }
838 
839 // As arith_impl! but for Checked{Add,Sub} traits
840 macro_rules! checked_arith_impl {
841     (impl $imp:ident, $method:ident) => {
842         impl<T: Clone + Integer + CheckedMul + $imp> $imp for Ratio<T> {
843             #[inline]
844             fn $method(&self, rhs: &Ratio<T>) -> Option<Ratio<T>> {
845                 let gcd = self.denom.clone().gcd(&rhs.denom);
846                 let lcm = (self.denom.clone() / gcd.clone()).checked_mul(&rhs.denom)?;
847                 let lhs_numer = (lcm.clone() / self.denom.clone()).checked_mul(&self.numer)?;
848                 let rhs_numer = (lcm.clone() / rhs.denom.clone()).checked_mul(&rhs.numer)?;
849                 Some(Ratio::new(lhs_numer.$method(&rhs_numer)?, lcm))
850             }
851         }
852     };
853 }
854 
855 // a/b + c/d = (lcm/b*a + lcm/d*c)/lcm, where lcm = lcm(b,d)
856 checked_arith_impl!(impl CheckedAdd, checked_add);
857 
858 // a/b - c/d = (lcm/b*a - lcm/d*c)/lcm, where lcm = lcm(b,d)
859 checked_arith_impl!(impl CheckedSub, checked_sub);
860 
861 impl<T> Neg for Ratio<T>
862 where
863     T: Clone + Integer + Neg<Output = T>,
864 {
865     type Output = Ratio<T>;
866 
867     #[inline]
neg(self) -> Ratio<T>868     fn neg(self) -> Ratio<T> {
869         Ratio::new_raw(-self.numer, self.denom)
870     }
871 }
872 
873 impl<'a, T> Neg for &'a Ratio<T>
874 where
875     T: Clone + Integer + Neg<Output = T>,
876 {
877     type Output = Ratio<T>;
878 
879     #[inline]
neg(self) -> Ratio<T>880     fn neg(self) -> Ratio<T> {
881         -self.clone()
882     }
883 }
884 
885 impl<T> Inv for Ratio<T>
886 where
887     T: Clone + Integer,
888 {
889     type Output = Ratio<T>;
890 
891     #[inline]
inv(self) -> Ratio<T>892     fn inv(self) -> Ratio<T> {
893         self.recip()
894     }
895 }
896 
897 impl<'a, T> Inv for &'a Ratio<T>
898 where
899     T: Clone + Integer,
900 {
901     type Output = Ratio<T>;
902 
903     #[inline]
inv(self) -> Ratio<T>904     fn inv(self) -> Ratio<T> {
905         self.recip()
906     }
907 }
908 
909 // Constants
910 impl<T: Clone + Integer> Zero for Ratio<T> {
911     #[inline]
zero() -> Ratio<T>912     fn zero() -> Ratio<T> {
913         Ratio::new_raw(Zero::zero(), One::one())
914     }
915 
916     #[inline]
is_zero(&self) -> bool917     fn is_zero(&self) -> bool {
918         self.numer.is_zero()
919     }
920 
921     #[inline]
set_zero(&mut self)922     fn set_zero(&mut self) {
923         self.numer.set_zero();
924         self.denom.set_one();
925     }
926 }
927 
928 impl<T: Clone + Integer> One for Ratio<T> {
929     #[inline]
one() -> Ratio<T>930     fn one() -> Ratio<T> {
931         Ratio::new_raw(One::one(), One::one())
932     }
933 
934     #[inline]
is_one(&self) -> bool935     fn is_one(&self) -> bool {
936         self.numer == self.denom
937     }
938 
939     #[inline]
set_one(&mut self)940     fn set_one(&mut self) {
941         self.numer.set_one();
942         self.denom.set_one();
943     }
944 }
945 
946 impl<T: Clone + Integer> Num for Ratio<T> {
947     type FromStrRadixErr = ParseRatioError;
948 
949     /// Parses `numer/denom` where the numbers are in base `radix`.
from_str_radix(s: &str, radix: u32) -> Result<Ratio<T>, ParseRatioError>950     fn from_str_radix(s: &str, radix: u32) -> Result<Ratio<T>, ParseRatioError> {
951         if s.splitn(2, '/').count() == 2 {
952             let mut parts = s.splitn(2, '/').map(|ss| {
953                 T::from_str_radix(ss, radix).map_err(|_| ParseRatioError {
954                     kind: RatioErrorKind::ParseError,
955                 })
956             });
957             let numer: T = parts.next().unwrap()?;
958             let denom: T = parts.next().unwrap()?;
959             if denom.is_zero() {
960                 Err(ParseRatioError {
961                     kind: RatioErrorKind::ZeroDenominator,
962                 })
963             } else {
964                 Ok(Ratio::new(numer, denom))
965             }
966         } else {
967             Err(ParseRatioError {
968                 kind: RatioErrorKind::ParseError,
969             })
970         }
971     }
972 }
973 
974 impl<T: Clone + Integer + Signed> Signed for Ratio<T> {
975     #[inline]
abs(&self) -> Ratio<T>976     fn abs(&self) -> Ratio<T> {
977         if self.is_negative() {
978             -self.clone()
979         } else {
980             self.clone()
981         }
982     }
983 
984     #[inline]
abs_sub(&self, other: &Ratio<T>) -> Ratio<T>985     fn abs_sub(&self, other: &Ratio<T>) -> Ratio<T> {
986         if *self <= *other {
987             Zero::zero()
988         } else {
989             self - other
990         }
991     }
992 
993     #[inline]
signum(&self) -> Ratio<T>994     fn signum(&self) -> Ratio<T> {
995         if self.is_positive() {
996             Self::one()
997         } else if self.is_zero() {
998             Self::zero()
999         } else {
1000             -Self::one()
1001         }
1002     }
1003 
1004     #[inline]
is_positive(&self) -> bool1005     fn is_positive(&self) -> bool {
1006         (self.numer.is_positive() && self.denom.is_positive())
1007             || (self.numer.is_negative() && self.denom.is_negative())
1008     }
1009 
1010     #[inline]
is_negative(&self) -> bool1011     fn is_negative(&self) -> bool {
1012         (self.numer.is_negative() && self.denom.is_positive())
1013             || (self.numer.is_positive() && self.denom.is_negative())
1014     }
1015 }
1016 
1017 // String conversions
1018 macro_rules! impl_formatting {
1019     ($fmt_trait:ident, $prefix:expr, $fmt_str:expr, $fmt_alt:expr) => {
1020         impl<T: $fmt_trait + Clone + Integer> $fmt_trait for Ratio<T> {
1021             #[cfg(feature = "std")]
1022             fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1023                 let pre_pad = if self.denom.is_one() {
1024                     format!($fmt_str, self.numer)
1025                 } else {
1026                     if f.alternate() {
1027                         format!(concat!($fmt_str, "/", $fmt_alt), self.numer, self.denom)
1028                     } else {
1029                         format!(concat!($fmt_str, "/", $fmt_str), self.numer, self.denom)
1030                     }
1031                 };
1032                 // TODO: replace with strip_prefix, when stabalized
1033                 let (pre_pad, non_negative) = {
1034                     if pre_pad.starts_with("-") {
1035                         (&pre_pad[1..], false)
1036                     } else {
1037                         (&pre_pad[..], true)
1038                     }
1039                 };
1040                 f.pad_integral(non_negative, $prefix, pre_pad)
1041             }
1042             #[cfg(not(feature = "std"))]
1043             fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1044                 let plus = if f.sign_plus() && self.numer >= T::zero() {
1045                     "+"
1046                 } else {
1047                     ""
1048                 };
1049                 if self.denom.is_one() {
1050                     if f.alternate() {
1051                         write!(f, concat!("{}", $fmt_alt), plus, self.numer)
1052                     } else {
1053                         write!(f, concat!("{}", $fmt_str), plus, self.numer)
1054                     }
1055                 } else {
1056                     if f.alternate() {
1057                         write!(
1058                             f,
1059                             concat!("{}", $fmt_alt, "/", $fmt_alt),
1060                             plus, self.numer, self.denom
1061                         )
1062                     } else {
1063                         write!(
1064                             f,
1065                             concat!("{}", $fmt_str, "/", $fmt_str),
1066                             plus, self.numer, self.denom
1067                         )
1068                     }
1069                 }
1070             }
1071         }
1072     };
1073 }
1074 
1075 impl_formatting!(Display, "", "{}", "{:#}");
1076 impl_formatting!(Octal, "0o", "{:o}", "{:#o}");
1077 impl_formatting!(Binary, "0b", "{:b}", "{:#b}");
1078 impl_formatting!(LowerHex, "0x", "{:x}", "{:#x}");
1079 impl_formatting!(UpperHex, "0x", "{:X}", "{:#X}");
1080 impl_formatting!(LowerExp, "", "{:e}", "{:#e}");
1081 impl_formatting!(UpperExp, "", "{:E}", "{:#E}");
1082 
1083 impl<T: FromStr + Clone + Integer> FromStr for Ratio<T> {
1084     type Err = ParseRatioError;
1085 
1086     /// Parses `numer/denom` or just `numer`.
from_str(s: &str) -> Result<Ratio<T>, ParseRatioError>1087     fn from_str(s: &str) -> Result<Ratio<T>, ParseRatioError> {
1088         let mut split = s.splitn(2, '/');
1089 
1090         let n = split.next().ok_or(ParseRatioError {
1091             kind: RatioErrorKind::ParseError,
1092         })?;
1093         let num = FromStr::from_str(n).map_err(|_| ParseRatioError {
1094             kind: RatioErrorKind::ParseError,
1095         })?;
1096 
1097         let d = split.next().unwrap_or("1");
1098         let den = FromStr::from_str(d).map_err(|_| ParseRatioError {
1099             kind: RatioErrorKind::ParseError,
1100         })?;
1101 
1102         if Zero::is_zero(&den) {
1103             Err(ParseRatioError {
1104                 kind: RatioErrorKind::ZeroDenominator,
1105             })
1106         } else {
1107             Ok(Ratio::new(num, den))
1108         }
1109     }
1110 }
1111 
1112 impl<T> Into<(T, T)> for Ratio<T> {
into(self) -> (T, T)1113     fn into(self) -> (T, T) {
1114         (self.numer, self.denom)
1115     }
1116 }
1117 
1118 #[cfg(feature = "serde")]
1119 impl<T> serde::Serialize for Ratio<T>
1120 where
1121     T: serde::Serialize + Clone + Integer + PartialOrd,
1122 {
serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: serde::Serializer,1123     fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
1124     where
1125         S: serde::Serializer,
1126     {
1127         (self.numer(), self.denom()).serialize(serializer)
1128     }
1129 }
1130 
1131 #[cfg(feature = "serde")]
1132 impl<'de, T> serde::Deserialize<'de> for Ratio<T>
1133 where
1134     T: serde::Deserialize<'de> + Clone + Integer + PartialOrd,
1135 {
deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: serde::Deserializer<'de>,1136     fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
1137     where
1138         D: serde::Deserializer<'de>,
1139     {
1140         use serde::de::Error;
1141         use serde::de::Unexpected;
1142         let (numer, denom): (T, T) = serde::Deserialize::deserialize(deserializer)?;
1143         if denom.is_zero() {
1144             Err(Error::invalid_value(
1145                 Unexpected::Signed(0),
1146                 &"a ratio with non-zero denominator",
1147             ))
1148         } else {
1149             Ok(Ratio::new_raw(numer, denom))
1150         }
1151     }
1152 }
1153 
1154 // FIXME: Bubble up specific errors
1155 #[derive(Copy, Clone, Debug, PartialEq)]
1156 pub struct ParseRatioError {
1157     kind: RatioErrorKind,
1158 }
1159 
1160 #[derive(Copy, Clone, Debug, PartialEq)]
1161 enum RatioErrorKind {
1162     ParseError,
1163     ZeroDenominator,
1164 }
1165 
1166 impl fmt::Display for ParseRatioError {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result1167     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1168         self.kind.description().fmt(f)
1169     }
1170 }
1171 
1172 #[cfg(feature = "std")]
1173 impl Error for ParseRatioError {
1174     #[allow(deprecated)]
description(&self) -> &str1175     fn description(&self) -> &str {
1176         self.kind.description()
1177     }
1178 }
1179 
1180 impl RatioErrorKind {
description(&self) -> &'static str1181     fn description(&self) -> &'static str {
1182         match *self {
1183             RatioErrorKind::ParseError => "failed to parse integer",
1184             RatioErrorKind::ZeroDenominator => "zero value denominator",
1185         }
1186     }
1187 }
1188 
1189 #[cfg(feature = "num-bigint")]
1190 impl FromPrimitive for Ratio<BigInt> {
from_i64(n: i64) -> Option<Self>1191     fn from_i64(n: i64) -> Option<Self> {
1192         Some(Ratio::from_integer(n.into()))
1193     }
1194 
from_i128(n: i128) -> Option<Self>1195     fn from_i128(n: i128) -> Option<Self> {
1196         Some(Ratio::from_integer(n.into()))
1197     }
1198 
from_u64(n: u64) -> Option<Self>1199     fn from_u64(n: u64) -> Option<Self> {
1200         Some(Ratio::from_integer(n.into()))
1201     }
1202 
from_u128(n: u128) -> Option<Self>1203     fn from_u128(n: u128) -> Option<Self> {
1204         Some(Ratio::from_integer(n.into()))
1205     }
1206 
from_f32(n: f32) -> Option<Self>1207     fn from_f32(n: f32) -> Option<Self> {
1208         Ratio::from_float(n)
1209     }
1210 
from_f64(n: f64) -> Option<Self>1211     fn from_f64(n: f64) -> Option<Self> {
1212         Ratio::from_float(n)
1213     }
1214 }
1215 
1216 macro_rules! from_primitive_integer {
1217     ($typ:ty, $approx:ident) => {
1218         impl FromPrimitive for Ratio<$typ> {
1219             fn from_i64(n: i64) -> Option<Self> {
1220                 <$typ as FromPrimitive>::from_i64(n).map(Ratio::from_integer)
1221             }
1222 
1223             fn from_i128(n: i128) -> Option<Self> {
1224                 <$typ as FromPrimitive>::from_i128(n).map(Ratio::from_integer)
1225             }
1226 
1227             fn from_u64(n: u64) -> Option<Self> {
1228                 <$typ as FromPrimitive>::from_u64(n).map(Ratio::from_integer)
1229             }
1230 
1231             fn from_u128(n: u128) -> Option<Self> {
1232                 <$typ as FromPrimitive>::from_u128(n).map(Ratio::from_integer)
1233             }
1234 
1235             fn from_f32(n: f32) -> Option<Self> {
1236                 $approx(n, 10e-20, 30)
1237             }
1238 
1239             fn from_f64(n: f64) -> Option<Self> {
1240                 $approx(n, 10e-20, 30)
1241             }
1242         }
1243     };
1244 }
1245 
1246 from_primitive_integer!(i8, approximate_float);
1247 from_primitive_integer!(i16, approximate_float);
1248 from_primitive_integer!(i32, approximate_float);
1249 from_primitive_integer!(i64, approximate_float);
1250 from_primitive_integer!(i128, approximate_float);
1251 from_primitive_integer!(isize, approximate_float);
1252 
1253 from_primitive_integer!(u8, approximate_float_unsigned);
1254 from_primitive_integer!(u16, approximate_float_unsigned);
1255 from_primitive_integer!(u32, approximate_float_unsigned);
1256 from_primitive_integer!(u64, approximate_float_unsigned);
1257 from_primitive_integer!(u128, approximate_float_unsigned);
1258 from_primitive_integer!(usize, approximate_float_unsigned);
1259 
1260 impl<T: Integer + Signed + Bounded + NumCast + Clone> Ratio<T> {
approximate_float<F: FloatCore + NumCast>(f: F) -> Option<Ratio<T>>1261     pub fn approximate_float<F: FloatCore + NumCast>(f: F) -> Option<Ratio<T>> {
1262         // 1/10e-20 < 1/2**32 which seems like a good default, and 30 seems
1263         // to work well. Might want to choose something based on the types in the future, e.g.
1264         // T::max().recip() and T::bits() or something similar.
1265         let epsilon = <F as NumCast>::from(10e-20).expect("Can't convert 10e-20");
1266         approximate_float(f, epsilon, 30)
1267     }
1268 }
1269 
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,1270 fn approximate_float<T, F>(val: F, max_error: F, max_iterations: usize) -> Option<Ratio<T>>
1271 where
1272     T: Integer + Signed + Bounded + NumCast + Clone,
1273     F: FloatCore + NumCast,
1274 {
1275     let negative = val.is_sign_negative();
1276     let abs_val = val.abs();
1277 
1278     let r = approximate_float_unsigned(abs_val, max_error, max_iterations)?;
1279 
1280     // Make negative again if needed
1281     Some(if negative { r.neg() } else { r })
1282 }
1283 
1284 // No Unsigned constraint because this also works on positive integers and is called
1285 // 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,1286 fn approximate_float_unsigned<T, F>(val: F, max_error: F, max_iterations: usize) -> Option<Ratio<T>>
1287 where
1288     T: Integer + Bounded + NumCast + Clone,
1289     F: FloatCore + NumCast,
1290 {
1291     // Continued fractions algorithm
1292     // http://mathforum.org/dr.math/faq/faq.fractions.html#decfrac
1293 
1294     if val < F::zero() || val.is_nan() {
1295         return None;
1296     }
1297 
1298     let mut q = val;
1299     let mut n0 = T::zero();
1300     let mut d0 = T::one();
1301     let mut n1 = T::one();
1302     let mut d1 = T::zero();
1303 
1304     let t_max = T::max_value();
1305     let t_max_f = <F as NumCast>::from(t_max.clone())?;
1306 
1307     // 1/epsilon > T::MAX
1308     let epsilon = t_max_f.recip();
1309 
1310     // Overflow
1311     if q > t_max_f {
1312         return None;
1313     }
1314 
1315     for _ in 0..max_iterations {
1316         let a = match <T as NumCast>::from(q) {
1317             None => break,
1318             Some(a) => a,
1319         };
1320 
1321         let a_f = match <F as NumCast>::from(a.clone()) {
1322             None => break,
1323             Some(a_f) => a_f,
1324         };
1325         let f = q - a_f;
1326 
1327         // Prevent overflow
1328         if !a.is_zero()
1329             && (n1 > t_max.clone() / a.clone()
1330                 || d1 > t_max.clone() / a.clone()
1331                 || a.clone() * n1.clone() > t_max.clone() - n0.clone()
1332                 || a.clone() * d1.clone() > t_max.clone() - d0.clone())
1333         {
1334             break;
1335         }
1336 
1337         let n = a.clone() * n1.clone() + n0.clone();
1338         let d = a.clone() * d1.clone() + d0.clone();
1339 
1340         n0 = n1;
1341         d0 = d1;
1342         n1 = n.clone();
1343         d1 = d.clone();
1344 
1345         // Simplify fraction. Doing so here instead of at the end
1346         // allows us to get closer to the target value without overflows
1347         let g = Integer::gcd(&n1, &d1);
1348         if !g.is_zero() {
1349             n1 = n1 / g.clone();
1350             d1 = d1 / g.clone();
1351         }
1352 
1353         // Close enough?
1354         let (n_f, d_f) = match (<F as NumCast>::from(n), <F as NumCast>::from(d)) {
1355             (Some(n_f), Some(d_f)) => (n_f, d_f),
1356             _ => break,
1357         };
1358         if (n_f / d_f - val).abs() < max_error {
1359             break;
1360         }
1361 
1362         // Prevent division by ~0
1363         if f < epsilon {
1364             break;
1365         }
1366         q = f.recip();
1367     }
1368 
1369     // Overflow
1370     if d1.is_zero() {
1371         return None;
1372     }
1373 
1374     Some(Ratio::new(n1, d1))
1375 }
1376 
1377 #[cfg(not(feature = "num-bigint"))]
1378 macro_rules! to_primitive_small {
1379     ($($type_name:ty)*) => ($(
1380         impl ToPrimitive for Ratio<$type_name> {
1381             fn to_i64(&self) -> Option<i64> {
1382                 self.to_integer().to_i64()
1383             }
1384 
1385             fn to_i128(&self) -> Option<i128> {
1386                 self.to_integer().to_i128()
1387             }
1388 
1389             fn to_u64(&self) -> Option<u64> {
1390                 self.to_integer().to_u64()
1391             }
1392 
1393             fn to_u128(&self) -> Option<u128> {
1394                 self.to_integer().to_u128()
1395             }
1396 
1397             fn to_f64(&self) -> Option<f64> {
1398                 let float = self.numer.to_f64().unwrap() / self.denom.to_f64().unwrap();
1399                 if float.is_nan() {
1400                     None
1401                 } else {
1402                     Some(float)
1403                 }
1404             }
1405         }
1406     )*)
1407 }
1408 
1409 #[cfg(not(feature = "num-bigint"))]
1410 to_primitive_small!(u8 i8 u16 i16 u32 i32);
1411 
1412 #[cfg(all(target_pointer_width = "32", not(feature = "num-bigint")))]
1413 to_primitive_small!(usize isize);
1414 
1415 #[cfg(not(feature = "num-bigint"))]
1416 macro_rules! to_primitive_64 {
1417     ($($type_name:ty)*) => ($(
1418         impl ToPrimitive for Ratio<$type_name> {
1419             fn to_i64(&self) -> Option<i64> {
1420                 self.to_integer().to_i64()
1421             }
1422 
1423             fn to_i128(&self) -> Option<i128> {
1424                 self.to_integer().to_i128()
1425             }
1426 
1427             fn to_u64(&self) -> Option<u64> {
1428                 self.to_integer().to_u64()
1429             }
1430 
1431             fn to_u128(&self) -> Option<u128> {
1432                 self.to_integer().to_u128()
1433             }
1434 
1435             fn to_f64(&self) -> Option<f64> {
1436                 let float = ratio_to_f64(
1437                     self.numer as i128,
1438                     self.denom as i128
1439                 );
1440                 if float.is_nan() {
1441                     None
1442                 } else {
1443                     Some(float)
1444                 }
1445             }
1446         }
1447     )*)
1448 }
1449 
1450 #[cfg(not(feature = "num-bigint"))]
1451 to_primitive_64!(u64 i64);
1452 
1453 #[cfg(all(target_pointer_width = "64", not(feature = "num-bigint")))]
1454 to_primitive_64!(usize isize);
1455 
1456 #[cfg(feature = "num-bigint")]
1457 impl<T: Clone + Integer + ToPrimitive + ToBigInt> ToPrimitive for Ratio<T> {
to_i64(&self) -> Option<i64>1458     fn to_i64(&self) -> Option<i64> {
1459         self.to_integer().to_i64()
1460     }
1461 
to_i128(&self) -> Option<i128>1462     fn to_i128(&self) -> Option<i128> {
1463         self.to_integer().to_i128()
1464     }
1465 
to_u64(&self) -> Option<u64>1466     fn to_u64(&self) -> Option<u64> {
1467         self.to_integer().to_u64()
1468     }
1469 
to_u128(&self) -> Option<u128>1470     fn to_u128(&self) -> Option<u128> {
1471         self.to_integer().to_u128()
1472     }
1473 
to_f64(&self) -> Option<f64>1474     fn to_f64(&self) -> Option<f64> {
1475         let float = match (self.numer.to_i64(), self.denom.to_i64()) {
1476             (Some(numer), Some(denom)) => ratio_to_f64(
1477                 <i128 as From<_>>::from(numer),
1478                 <i128 as From<_>>::from(denom),
1479             ),
1480             _ => {
1481                 let numer: BigInt = self.numer.to_bigint()?;
1482                 let denom: BigInt = self.denom.to_bigint()?;
1483                 ratio_to_f64(numer, denom)
1484             }
1485         };
1486         if float.is_nan() {
1487             None
1488         } else {
1489             Some(float)
1490         }
1491     }
1492 }
1493 
1494 trait Bits {
bits(&self) -> u641495     fn bits(&self) -> u64;
1496 }
1497 
1498 #[cfg(feature = "num-bigint")]
1499 impl Bits for BigInt {
bits(&self) -> u641500     fn bits(&self) -> u64 {
1501         self.bits()
1502     }
1503 }
1504 
1505 impl Bits for i128 {
bits(&self) -> u641506     fn bits(&self) -> u64 {
1507         (128 - self.wrapping_abs().leading_zeros()).into()
1508     }
1509 }
1510 
1511 /// Converts a ratio of `T` to an f64.
1512 ///
1513 /// In addition to stated trait bounds, `T` must be able to hold numbers 56 bits larger than
1514 /// the largest of `numer` and `denom`. This is automatically true if `T` is `BigInt`.
ratio_to_f64<T: Bits + Clone + Integer + Signed + ShlAssign<usize> + ToPrimitive>( numer: T, denom: T, ) -> f641515 fn ratio_to_f64<T: Bits + Clone + Integer + Signed + ShlAssign<usize> + ToPrimitive>(
1516     numer: T,
1517     denom: T,
1518 ) -> f64 {
1519     assert_eq!(
1520         core::f64::RADIX,
1521         2,
1522         "only floating point implementations with radix 2 are supported"
1523     );
1524 
1525     // Inclusive upper and lower bounds to the range of exactly-representable ints in an f64.
1526     const MAX_EXACT_INT: i64 = 1i64 << core::f64::MANTISSA_DIGITS;
1527     const MIN_EXACT_INT: i64 = -MAX_EXACT_INT;
1528 
1529     let flo_sign = numer.signum().to_f64().unwrap() / denom.signum().to_f64().unwrap();
1530     if !flo_sign.is_normal() {
1531         return flo_sign;
1532     }
1533 
1534     // Fast track: both sides can losslessly be converted to f64s. In this case, letting the
1535     // FPU do the job is faster and easier. In any other case, converting to f64s may lead
1536     // to an inexact result: https://stackoverflow.com/questions/56641441/.
1537     if let (Some(n), Some(d)) = (numer.to_i64(), denom.to_i64()) {
1538         if MIN_EXACT_INT <= n && n <= MAX_EXACT_INT && MIN_EXACT_INT <= d && d <= MAX_EXACT_INT {
1539             return n.to_f64().unwrap() / d.to_f64().unwrap();
1540         }
1541     }
1542 
1543     // Otherwise, the goal is to obtain a quotient with at least 55 bits. 53 of these bits will
1544     // be used as the mantissa of the resulting float, and the remaining two are for rounding.
1545     // There's an error of up to 1 on the number of resulting bits, so we may get either 55 or
1546     // 56 bits.
1547     let mut numer = numer.abs();
1548     let mut denom = denom.abs();
1549     let (is_diff_positive, absolute_diff) = match numer.bits().checked_sub(denom.bits()) {
1550         Some(diff) => (true, diff),
1551         None => (false, denom.bits() - numer.bits()),
1552     };
1553 
1554     // Filter out overflows and underflows. After this step, the signed difference fits in an
1555     // isize.
1556     if is_diff_positive && absolute_diff > core::f64::MAX_EXP as u64 {
1557         return core::f64::INFINITY * flo_sign;
1558     }
1559     if !is_diff_positive
1560         && absolute_diff > -core::f64::MIN_EXP as u64 + core::f64::MANTISSA_DIGITS as u64 + 1
1561     {
1562         return 0.0 * flo_sign;
1563     }
1564     let diff = if is_diff_positive {
1565         absolute_diff.to_isize().unwrap()
1566     } else {
1567         -absolute_diff.to_isize().unwrap()
1568     };
1569 
1570     // Shift is chosen so that the quotient will have 55 or 56 bits. The exception is if the
1571     // quotient is going to be subnormal, in which case it may have fewer bits.
1572     let shift: isize =
1573         diff.max(core::f64::MIN_EXP as isize) - core::f64::MANTISSA_DIGITS as isize - 2;
1574     if shift >= 0 {
1575         denom <<= shift as usize
1576     } else {
1577         numer <<= -shift as usize
1578     };
1579 
1580     let (quotient, remainder) = numer.div_rem(&denom);
1581 
1582     // This is guaranteed to fit since we've set up quotient to be at most 56 bits.
1583     let mut quotient = quotient.to_u64().unwrap();
1584     let n_rounding_bits = {
1585         let quotient_bits = 64 - quotient.leading_zeros() as isize;
1586         let subnormal_bits = core::f64::MIN_EXP as isize - shift;
1587         quotient_bits.max(subnormal_bits) - core::f64::MANTISSA_DIGITS as isize
1588     } as usize;
1589     debug_assert!(n_rounding_bits == 2 || n_rounding_bits == 3);
1590     let rounding_bit_mask = (1u64 << n_rounding_bits) - 1;
1591 
1592     // Round to 53 bits with round-to-even. For rounding, we need to take into account both
1593     // our rounding bits and the division's remainder.
1594     let ls_bit = quotient & (1u64 << n_rounding_bits) != 0;
1595     let ms_rounding_bit = quotient & (1u64 << (n_rounding_bits - 1)) != 0;
1596     let ls_rounding_bits = quotient & (rounding_bit_mask >> 1) != 0;
1597     if ms_rounding_bit && (ls_bit || ls_rounding_bits || !remainder.is_zero()) {
1598         quotient += 1u64 << n_rounding_bits;
1599     }
1600     quotient &= !rounding_bit_mask;
1601 
1602     // The quotient is guaranteed to be exactly representable as it's now 53 bits + 2 or 3
1603     // trailing zeros, so there is no risk of a rounding error here.
1604     let q_float = quotient as f64;
1605     q_float * 2f64.powi(shift as i32) * flo_sign
1606 }
1607 
1608 #[cfg(test)]
1609 #[cfg(feature = "std")]
hash<T: Hash>(x: &T) -> u641610 fn hash<T: Hash>(x: &T) -> u64 {
1611     use std::collections::hash_map::RandomState;
1612     use std::hash::BuildHasher;
1613     let mut hasher = <RandomState as BuildHasher>::Hasher::new();
1614     x.hash(&mut hasher);
1615     hasher.finish()
1616 }
1617 
1618 #[cfg(test)]
1619 mod test {
1620     #[cfg(all(feature = "num-bigint"))]
1621     use super::BigInt;
1622     #[cfg(feature = "num-bigint")]
1623     use super::BigRational;
1624     use super::{Ratio, Rational64};
1625 
1626     use core::f64;
1627     use core::i32;
1628     use core::i64;
1629     use core::str::FromStr;
1630     use num_integer::Integer;
1631     use num_traits::ToPrimitive;
1632     use num_traits::{FromPrimitive, One, Pow, Signed, Zero};
1633 
1634     pub const _0: Rational64 = Ratio { numer: 0, denom: 1 };
1635     pub const _1: Rational64 = Ratio { numer: 1, denom: 1 };
1636     pub const _2: Rational64 = Ratio { numer: 2, denom: 1 };
1637     pub const _NEG2: Rational64 = Ratio {
1638         numer: -2,
1639         denom: 1,
1640     };
1641     pub const _8: Rational64 = Ratio { numer: 8, denom: 1 };
1642     pub const _15: Rational64 = Ratio {
1643         numer: 15,
1644         denom: 1,
1645     };
1646     pub const _16: Rational64 = Ratio {
1647         numer: 16,
1648         denom: 1,
1649     };
1650 
1651     pub const _1_2: Rational64 = Ratio { numer: 1, denom: 2 };
1652     pub const _1_8: Rational64 = Ratio { numer: 1, denom: 8 };
1653     pub const _1_15: Rational64 = Ratio {
1654         numer: 1,
1655         denom: 15,
1656     };
1657     pub const _1_16: Rational64 = Ratio {
1658         numer: 1,
1659         denom: 16,
1660     };
1661     pub const _3_2: Rational64 = Ratio { numer: 3, denom: 2 };
1662     pub const _5_2: Rational64 = Ratio { numer: 5, denom: 2 };
1663     pub const _NEG1_2: Rational64 = Ratio {
1664         numer: -1,
1665         denom: 2,
1666     };
1667     pub const _1_NEG2: Rational64 = Ratio {
1668         numer: 1,
1669         denom: -2,
1670     };
1671     pub const _NEG1_NEG2: Rational64 = Ratio {
1672         numer: -1,
1673         denom: -2,
1674     };
1675     pub const _1_3: Rational64 = Ratio { numer: 1, denom: 3 };
1676     pub const _NEG1_3: Rational64 = Ratio {
1677         numer: -1,
1678         denom: 3,
1679     };
1680     pub const _2_3: Rational64 = Ratio { numer: 2, denom: 3 };
1681     pub const _NEG2_3: Rational64 = Ratio {
1682         numer: -2,
1683         denom: 3,
1684     };
1685     pub const _MIN: Rational64 = Ratio {
1686         numer: i64::MIN,
1687         denom: 1,
1688     };
1689     pub const _MIN_P1: Rational64 = Ratio {
1690         numer: i64::MIN + 1,
1691         denom: 1,
1692     };
1693     pub const _MAX: Rational64 = Ratio {
1694         numer: i64::MAX,
1695         denom: 1,
1696     };
1697     pub const _MAX_M1: Rational64 = Ratio {
1698         numer: i64::MAX - 1,
1699         denom: 1,
1700     };
1701     pub const _BILLION: Rational64 = Ratio {
1702         numer: 1_000_000_000,
1703         denom: 1,
1704     };
1705 
1706     #[cfg(feature = "num-bigint")]
to_big(n: Rational64) -> BigRational1707     pub fn to_big(n: Rational64) -> BigRational {
1708         Ratio::new(
1709             FromPrimitive::from_i64(n.numer).unwrap(),
1710             FromPrimitive::from_i64(n.denom).unwrap(),
1711         )
1712     }
1713     #[cfg(not(feature = "num-bigint"))]
to_big(n: Rational64) -> Rational641714     pub fn to_big(n: Rational64) -> Rational64 {
1715         Ratio::new(
1716             FromPrimitive::from_i64(n.numer).unwrap(),
1717             FromPrimitive::from_i64(n.denom).unwrap(),
1718         )
1719     }
1720 
1721     #[test]
test_test_constants()1722     fn test_test_constants() {
1723         // check our constants are what Ratio::new etc. would make.
1724         assert_eq!(_0, Zero::zero());
1725         assert_eq!(_1, One::one());
1726         assert_eq!(_2, Ratio::from_integer(2));
1727         assert_eq!(_1_2, Ratio::new(1, 2));
1728         assert_eq!(_3_2, Ratio::new(3, 2));
1729         assert_eq!(_NEG1_2, Ratio::new(-1, 2));
1730         assert_eq!(_2, From::from(2));
1731     }
1732 
1733     #[test]
test_new_reduce()1734     fn test_new_reduce() {
1735         assert_eq!(Ratio::new(2, 2), One::one());
1736         assert_eq!(Ratio::new(0, i32::MIN), Zero::zero());
1737         assert_eq!(Ratio::new(i32::MIN, i32::MIN), One::one());
1738     }
1739     #[test]
1740     #[should_panic]
test_new_zero()1741     fn test_new_zero() {
1742         let _a = Ratio::new(1, 0);
1743     }
1744 
1745     #[test]
test_approximate_float()1746     fn test_approximate_float() {
1747         assert_eq!(Ratio::from_f32(0.5f32), Some(Ratio::new(1i64, 2)));
1748         assert_eq!(Ratio::from_f64(0.5f64), Some(Ratio::new(1i32, 2)));
1749         assert_eq!(Ratio::from_f32(5f32), Some(Ratio::new(5i64, 1)));
1750         assert_eq!(Ratio::from_f64(5f64), Some(Ratio::new(5i32, 1)));
1751         assert_eq!(Ratio::from_f32(29.97f32), Some(Ratio::new(2997i64, 100)));
1752         assert_eq!(Ratio::from_f32(-29.97f32), Some(Ratio::new(-2997i64, 100)));
1753 
1754         assert_eq!(Ratio::<i8>::from_f32(63.5f32), Some(Ratio::new(127i8, 2)));
1755         assert_eq!(Ratio::<i8>::from_f32(126.5f32), Some(Ratio::new(126i8, 1)));
1756         assert_eq!(Ratio::<i8>::from_f32(127.0f32), Some(Ratio::new(127i8, 1)));
1757         assert_eq!(Ratio::<i8>::from_f32(127.5f32), None);
1758         assert_eq!(Ratio::<i8>::from_f32(-63.5f32), Some(Ratio::new(-127i8, 2)));
1759         assert_eq!(
1760             Ratio::<i8>::from_f32(-126.5f32),
1761             Some(Ratio::new(-126i8, 1))
1762         );
1763         assert_eq!(
1764             Ratio::<i8>::from_f32(-127.0f32),
1765             Some(Ratio::new(-127i8, 1))
1766         );
1767         assert_eq!(Ratio::<i8>::from_f32(-127.5f32), None);
1768 
1769         assert_eq!(Ratio::<u8>::from_f32(-127f32), None);
1770         assert_eq!(Ratio::<u8>::from_f32(127f32), Some(Ratio::new(127u8, 1)));
1771         assert_eq!(Ratio::<u8>::from_f32(127.5f32), Some(Ratio::new(255u8, 2)));
1772         assert_eq!(Ratio::<u8>::from_f32(256f32), None);
1773 
1774         assert_eq!(Ratio::<i64>::from_f64(-10e200), None);
1775         assert_eq!(Ratio::<i64>::from_f64(10e200), None);
1776         assert_eq!(Ratio::<i64>::from_f64(f64::INFINITY), None);
1777         assert_eq!(Ratio::<i64>::from_f64(f64::NEG_INFINITY), None);
1778         assert_eq!(Ratio::<i64>::from_f64(f64::NAN), None);
1779         assert_eq!(
1780             Ratio::<i64>::from_f64(f64::EPSILON),
1781             Some(Ratio::new(1, 4503599627370496))
1782         );
1783         assert_eq!(Ratio::<i64>::from_f64(0.0), Some(Ratio::new(0, 1)));
1784         assert_eq!(Ratio::<i64>::from_f64(-0.0), Some(Ratio::new(0, 1)));
1785     }
1786 
1787     #[test]
1788     #[allow(clippy::eq_op)]
test_cmp()1789     fn test_cmp() {
1790         assert!(_0 == _0 && _1 == _1);
1791         assert!(_0 != _1 && _1 != _0);
1792         assert!(_0 < _1 && !(_1 < _0));
1793         assert!(_1 > _0 && !(_0 > _1));
1794 
1795         assert!(_0 <= _0 && _1 <= _1);
1796         assert!(_0 <= _1 && !(_1 <= _0));
1797 
1798         assert!(_0 >= _0 && _1 >= _1);
1799         assert!(_1 >= _0 && !(_0 >= _1));
1800 
1801         let _0_2: Rational64 = Ratio::new_raw(0, 2);
1802         assert_eq!(_0, _0_2);
1803     }
1804 
1805     #[test]
test_cmp_overflow()1806     fn test_cmp_overflow() {
1807         use core::cmp::Ordering;
1808 
1809         // issue #7 example:
1810         let big = Ratio::new(128u8, 1);
1811         let small = big.recip();
1812         assert!(big > small);
1813 
1814         // try a few that are closer together
1815         // (some matching numer, some matching denom, some neither)
1816         let ratios = [
1817             Ratio::new(125_i8, 127_i8),
1818             Ratio::new(63_i8, 64_i8),
1819             Ratio::new(124_i8, 125_i8),
1820             Ratio::new(125_i8, 126_i8),
1821             Ratio::new(126_i8, 127_i8),
1822             Ratio::new(127_i8, 126_i8),
1823         ];
1824 
1825         fn check_cmp(a: Ratio<i8>, b: Ratio<i8>, ord: Ordering) {
1826             #[cfg(feature = "std")]
1827             println!("comparing {} and {}", a, b);
1828             assert_eq!(a.cmp(&b), ord);
1829             assert_eq!(b.cmp(&a), ord.reverse());
1830         }
1831 
1832         for (i, &a) in ratios.iter().enumerate() {
1833             check_cmp(a, a, Ordering::Equal);
1834             check_cmp(-a, a, Ordering::Less);
1835             for &b in &ratios[i + 1..] {
1836                 check_cmp(a, b, Ordering::Less);
1837                 check_cmp(-a, -b, Ordering::Greater);
1838                 check_cmp(a.recip(), b.recip(), Ordering::Greater);
1839                 check_cmp(-a.recip(), -b.recip(), Ordering::Less);
1840             }
1841         }
1842     }
1843 
1844     #[test]
test_to_integer()1845     fn test_to_integer() {
1846         assert_eq!(_0.to_integer(), 0);
1847         assert_eq!(_1.to_integer(), 1);
1848         assert_eq!(_2.to_integer(), 2);
1849         assert_eq!(_1_2.to_integer(), 0);
1850         assert_eq!(_3_2.to_integer(), 1);
1851         assert_eq!(_NEG1_2.to_integer(), 0);
1852     }
1853 
1854     #[test]
test_numer()1855     fn test_numer() {
1856         assert_eq!(_0.numer(), &0);
1857         assert_eq!(_1.numer(), &1);
1858         assert_eq!(_2.numer(), &2);
1859         assert_eq!(_1_2.numer(), &1);
1860         assert_eq!(_3_2.numer(), &3);
1861         assert_eq!(_NEG1_2.numer(), &(-1));
1862     }
1863     #[test]
test_denom()1864     fn test_denom() {
1865         assert_eq!(_0.denom(), &1);
1866         assert_eq!(_1.denom(), &1);
1867         assert_eq!(_2.denom(), &1);
1868         assert_eq!(_1_2.denom(), &2);
1869         assert_eq!(_3_2.denom(), &2);
1870         assert_eq!(_NEG1_2.denom(), &2);
1871     }
1872 
1873     #[test]
test_is_integer()1874     fn test_is_integer() {
1875         assert!(_0.is_integer());
1876         assert!(_1.is_integer());
1877         assert!(_2.is_integer());
1878         assert!(!_1_2.is_integer());
1879         assert!(!_3_2.is_integer());
1880         assert!(!_NEG1_2.is_integer());
1881     }
1882 
1883     #[cfg(not(feature = "std"))]
1884     use core::fmt::{self, Write};
1885     #[cfg(not(feature = "std"))]
1886     #[derive(Debug)]
1887     struct NoStdTester {
1888         cursor: usize,
1889         buf: [u8; NoStdTester::BUF_SIZE],
1890     }
1891 
1892     #[cfg(not(feature = "std"))]
1893     impl NoStdTester {
new() -> NoStdTester1894         fn new() -> NoStdTester {
1895             NoStdTester {
1896                 buf: [0; Self::BUF_SIZE],
1897                 cursor: 0,
1898             }
1899         }
1900 
clear(&mut self)1901         fn clear(&mut self) {
1902             self.buf = [0; Self::BUF_SIZE];
1903             self.cursor = 0;
1904         }
1905 
1906         const WRITE_ERR: &'static str = "Formatted output too long";
1907         const BUF_SIZE: usize = 32;
1908     }
1909 
1910     #[cfg(not(feature = "std"))]
1911     impl Write for NoStdTester {
write_str(&mut self, s: &str) -> fmt::Result1912         fn write_str(&mut self, s: &str) -> fmt::Result {
1913             for byte in s.bytes() {
1914                 self.buf[self.cursor] = byte;
1915                 self.cursor += 1;
1916                 if self.cursor >= self.buf.len() {
1917                     return Err(fmt::Error {});
1918                 }
1919             }
1920             Ok(())
1921         }
1922     }
1923 
1924     #[cfg(not(feature = "std"))]
1925     impl PartialEq<str> for NoStdTester {
eq(&self, other: &str) -> bool1926         fn eq(&self, other: &str) -> bool {
1927             let other = other.as_bytes();
1928             for index in 0..self.cursor {
1929                 if self.buf.get(index) != other.get(index) {
1930                     return false;
1931                 }
1932             }
1933             true
1934         }
1935     }
1936 
1937     macro_rules! assert_fmt_eq {
1938         ($fmt_args:expr, $string:expr) => {
1939             #[cfg(not(feature = "std"))]
1940             {
1941                 let mut tester = NoStdTester::new();
1942                 write!(tester, "{}", $fmt_args).expect(NoStdTester::WRITE_ERR);
1943                 assert_eq!(tester, *$string);
1944                 tester.clear();
1945             }
1946             #[cfg(feature = "std")]
1947             {
1948                 assert_eq!(std::fmt::format($fmt_args), $string);
1949             }
1950         };
1951     }
1952 
1953     #[test]
test_show()1954     fn test_show() {
1955         // Test:
1956         // :b :o :x, :X, :?
1957         // alternate or not (#)
1958         // positive and negative
1959         // padding
1960         // does not test precision (i.e. truncation)
1961         assert_fmt_eq!(format_args!("{}", _2), "2");
1962         assert_fmt_eq!(format_args!("{:+}", _2), "+2");
1963         assert_fmt_eq!(format_args!("{:-}", _2), "2");
1964         assert_fmt_eq!(format_args!("{}", _1_2), "1/2");
1965         assert_fmt_eq!(format_args!("{}", -_1_2), "-1/2"); // test negatives
1966         assert_fmt_eq!(format_args!("{}", _0), "0");
1967         assert_fmt_eq!(format_args!("{}", -_2), "-2");
1968         assert_fmt_eq!(format_args!("{:+}", -_2), "-2");
1969         assert_fmt_eq!(format_args!("{:b}", _2), "10");
1970         assert_fmt_eq!(format_args!("{:#b}", _2), "0b10");
1971         assert_fmt_eq!(format_args!("{:b}", _1_2), "1/10");
1972         assert_fmt_eq!(format_args!("{:+b}", _1_2), "+1/10");
1973         assert_fmt_eq!(format_args!("{:-b}", _1_2), "1/10");
1974         assert_fmt_eq!(format_args!("{:b}", _0), "0");
1975         assert_fmt_eq!(format_args!("{:#b}", _1_2), "0b1/0b10");
1976         // no std does not support padding
1977         #[cfg(feature = "std")]
1978         assert_eq!(&format!("{:010b}", _1_2), "0000001/10");
1979         #[cfg(feature = "std")]
1980         assert_eq!(&format!("{:#010b}", _1_2), "0b001/0b10");
1981         let half_i8: Ratio<i8> = Ratio::new(1_i8, 2_i8);
1982         assert_fmt_eq!(format_args!("{:b}", -half_i8), "11111111/10");
1983         assert_fmt_eq!(format_args!("{:#b}", -half_i8), "0b11111111/0b10");
1984         #[cfg(feature = "std")]
1985         assert_eq!(&format!("{:05}", Ratio::new(-1_i8, 1_i8)), "-0001");
1986 
1987         assert_fmt_eq!(format_args!("{:o}", _8), "10");
1988         assert_fmt_eq!(format_args!("{:o}", _1_8), "1/10");
1989         assert_fmt_eq!(format_args!("{:o}", _0), "0");
1990         assert_fmt_eq!(format_args!("{:#o}", _1_8), "0o1/0o10");
1991         #[cfg(feature = "std")]
1992         assert_eq!(&format!("{:010o}", _1_8), "0000001/10");
1993         #[cfg(feature = "std")]
1994         assert_eq!(&format!("{:#010o}", _1_8), "0o001/0o10");
1995         assert_fmt_eq!(format_args!("{:o}", -half_i8), "377/2");
1996         assert_fmt_eq!(format_args!("{:#o}", -half_i8), "0o377/0o2");
1997 
1998         assert_fmt_eq!(format_args!("{:x}", _16), "10");
1999         assert_fmt_eq!(format_args!("{:x}", _15), "f");
2000         assert_fmt_eq!(format_args!("{:x}", _1_16), "1/10");
2001         assert_fmt_eq!(format_args!("{:x}", _1_15), "1/f");
2002         assert_fmt_eq!(format_args!("{:x}", _0), "0");
2003         assert_fmt_eq!(format_args!("{:#x}", _1_16), "0x1/0x10");
2004         #[cfg(feature = "std")]
2005         assert_eq!(&format!("{:010x}", _1_16), "0000001/10");
2006         #[cfg(feature = "std")]
2007         assert_eq!(&format!("{:#010x}", _1_16), "0x001/0x10");
2008         assert_fmt_eq!(format_args!("{:x}", -half_i8), "ff/2");
2009         assert_fmt_eq!(format_args!("{:#x}", -half_i8), "0xff/0x2");
2010 
2011         assert_fmt_eq!(format_args!("{:X}", _16), "10");
2012         assert_fmt_eq!(format_args!("{:X}", _15), "F");
2013         assert_fmt_eq!(format_args!("{:X}", _1_16), "1/10");
2014         assert_fmt_eq!(format_args!("{:X}", _1_15), "1/F");
2015         assert_fmt_eq!(format_args!("{:X}", _0), "0");
2016         assert_fmt_eq!(format_args!("{:#X}", _1_16), "0x1/0x10");
2017         #[cfg(feature = "std")]
2018         assert_eq!(format!("{:010X}", _1_16), "0000001/10");
2019         #[cfg(feature = "std")]
2020         assert_eq!(format!("{:#010X}", _1_16), "0x001/0x10");
2021         assert_fmt_eq!(format_args!("{:X}", -half_i8), "FF/2");
2022         assert_fmt_eq!(format_args!("{:#X}", -half_i8), "0xFF/0x2");
2023 
2024         #[cfg(has_int_exp_fmt)]
2025         {
2026             assert_fmt_eq!(format_args!("{:e}", -_2), "-2e0");
2027             assert_fmt_eq!(format_args!("{:#e}", -_2), "-2e0");
2028             assert_fmt_eq!(format_args!("{:+e}", -_2), "-2e0");
2029             assert_fmt_eq!(format_args!("{:e}", _BILLION), "1e9");
2030             assert_fmt_eq!(format_args!("{:+e}", _BILLION), "+1e9");
2031             assert_fmt_eq!(format_args!("{:e}", _BILLION.recip()), "1e0/1e9");
2032             assert_fmt_eq!(format_args!("{:+e}", _BILLION.recip()), "+1e0/1e9");
2033 
2034             assert_fmt_eq!(format_args!("{:E}", -_2), "-2E0");
2035             assert_fmt_eq!(format_args!("{:#E}", -_2), "-2E0");
2036             assert_fmt_eq!(format_args!("{:+E}", -_2), "-2E0");
2037             assert_fmt_eq!(format_args!("{:E}", _BILLION), "1E9");
2038             assert_fmt_eq!(format_args!("{:+E}", _BILLION), "+1E9");
2039             assert_fmt_eq!(format_args!("{:E}", _BILLION.recip()), "1E0/1E9");
2040             assert_fmt_eq!(format_args!("{:+E}", _BILLION.recip()), "+1E0/1E9");
2041         }
2042     }
2043 
2044     mod arith {
2045         use super::super::{Ratio, Rational64};
2046         use super::{to_big, _0, _1, _1_2, _2, _3_2, _5_2, _MAX, _MAX_M1, _MIN, _MIN_P1, _NEG1_2};
2047         use core::fmt::Debug;
2048         use num_integer::Integer;
2049         use num_traits::{Bounded, CheckedAdd, CheckedDiv, CheckedMul, CheckedSub, NumAssign};
2050 
2051         #[test]
test_add()2052         fn test_add() {
2053             fn test(a: Rational64, b: Rational64, c: Rational64) {
2054                 assert_eq!(a + b, c);
2055                 assert_eq!(
2056                     {
2057                         let mut x = a;
2058                         x += b;
2059                         x
2060                     },
2061                     c
2062                 );
2063                 assert_eq!(to_big(a) + to_big(b), to_big(c));
2064                 assert_eq!(a.checked_add(&b), Some(c));
2065                 assert_eq!(to_big(a).checked_add(&to_big(b)), Some(to_big(c)));
2066             }
2067             fn test_assign(a: Rational64, b: i64, c: Rational64) {
2068                 assert_eq!(a + b, c);
2069                 assert_eq!(
2070                     {
2071                         let mut x = a;
2072                         x += b;
2073                         x
2074                     },
2075                     c
2076                 );
2077             }
2078 
2079             test(_1, _1_2, _3_2);
2080             test(_1, _1, _2);
2081             test(_1_2, _3_2, _2);
2082             test(_1_2, _NEG1_2, _0);
2083             test_assign(_1_2, 1, _3_2);
2084         }
2085 
2086         #[test]
test_add_overflow()2087         fn test_add_overflow() {
2088             // compares Ratio(1, T::max_value()) + Ratio(1, T::max_value())
2089             // to Ratio(1+1, T::max_value()) for each integer type.
2090             // Previously, this calculation would overflow.
2091             fn test_add_typed_overflow<T>()
2092             where
2093                 T: Integer + Bounded + Clone + Debug + NumAssign,
2094             {
2095                 let _1_max = Ratio::new(T::one(), T::max_value());
2096                 let _2_max = Ratio::new(T::one() + T::one(), T::max_value());
2097                 assert_eq!(_1_max.clone() + _1_max.clone(), _2_max);
2098                 assert_eq!(
2099                     {
2100                         let mut tmp = _1_max.clone();
2101                         tmp += _1_max;
2102                         tmp
2103                     },
2104                     _2_max
2105                 );
2106             }
2107             test_add_typed_overflow::<u8>();
2108             test_add_typed_overflow::<u16>();
2109             test_add_typed_overflow::<u32>();
2110             test_add_typed_overflow::<u64>();
2111             test_add_typed_overflow::<usize>();
2112             test_add_typed_overflow::<u128>();
2113 
2114             test_add_typed_overflow::<i8>();
2115             test_add_typed_overflow::<i16>();
2116             test_add_typed_overflow::<i32>();
2117             test_add_typed_overflow::<i64>();
2118             test_add_typed_overflow::<isize>();
2119             test_add_typed_overflow::<i128>();
2120         }
2121 
2122         #[test]
test_sub()2123         fn test_sub() {
2124             fn test(a: Rational64, b: Rational64, c: Rational64) {
2125                 assert_eq!(a - b, c);
2126                 assert_eq!(
2127                     {
2128                         let mut x = a;
2129                         x -= b;
2130                         x
2131                     },
2132                     c
2133                 );
2134                 assert_eq!(to_big(a) - to_big(b), to_big(c));
2135                 assert_eq!(a.checked_sub(&b), Some(c));
2136                 assert_eq!(to_big(a).checked_sub(&to_big(b)), Some(to_big(c)));
2137             }
2138             fn test_assign(a: Rational64, b: i64, c: Rational64) {
2139                 assert_eq!(a - b, c);
2140                 assert_eq!(
2141                     {
2142                         let mut x = a;
2143                         x -= b;
2144                         x
2145                     },
2146                     c
2147                 );
2148             }
2149 
2150             test(_1, _1_2, _1_2);
2151             test(_3_2, _1_2, _1);
2152             test(_1, _NEG1_2, _3_2);
2153             test_assign(_1_2, 1, _NEG1_2);
2154         }
2155 
2156         #[test]
test_sub_overflow()2157         fn test_sub_overflow() {
2158             // compares Ratio(1, T::max_value()) - Ratio(1, T::max_value()) to T::zero()
2159             // for each integer type. Previously, this calculation would overflow.
2160             fn test_sub_typed_overflow<T>()
2161             where
2162                 T: Integer + Bounded + Clone + Debug + NumAssign,
2163             {
2164                 let _1_max: Ratio<T> = Ratio::new(T::one(), T::max_value());
2165                 assert!(T::is_zero(&(_1_max.clone() - _1_max.clone()).numer));
2166                 {
2167                     let mut tmp: Ratio<T> = _1_max.clone();
2168                     tmp -= _1_max;
2169                     assert!(T::is_zero(&tmp.numer));
2170                 }
2171             }
2172             test_sub_typed_overflow::<u8>();
2173             test_sub_typed_overflow::<u16>();
2174             test_sub_typed_overflow::<u32>();
2175             test_sub_typed_overflow::<u64>();
2176             test_sub_typed_overflow::<usize>();
2177             test_sub_typed_overflow::<u128>();
2178 
2179             test_sub_typed_overflow::<i8>();
2180             test_sub_typed_overflow::<i16>();
2181             test_sub_typed_overflow::<i32>();
2182             test_sub_typed_overflow::<i64>();
2183             test_sub_typed_overflow::<isize>();
2184             test_sub_typed_overflow::<i128>();
2185         }
2186 
2187         #[test]
test_mul()2188         fn test_mul() {
2189             fn test(a: Rational64, b: Rational64, c: Rational64) {
2190                 assert_eq!(a * b, c);
2191                 assert_eq!(
2192                     {
2193                         let mut x = a;
2194                         x *= b;
2195                         x
2196                     },
2197                     c
2198                 );
2199                 assert_eq!(to_big(a) * to_big(b), to_big(c));
2200                 assert_eq!(a.checked_mul(&b), Some(c));
2201                 assert_eq!(to_big(a).checked_mul(&to_big(b)), Some(to_big(c)));
2202             }
2203             fn test_assign(a: Rational64, b: i64, c: Rational64) {
2204                 assert_eq!(a * b, c);
2205                 assert_eq!(
2206                     {
2207                         let mut x = a;
2208                         x *= b;
2209                         x
2210                     },
2211                     c
2212                 );
2213             }
2214 
2215             test(_1, _1_2, _1_2);
2216             test(_1_2, _3_2, Ratio::new(3, 4));
2217             test(_1_2, _NEG1_2, Ratio::new(-1, 4));
2218             test_assign(_1_2, 2, _1);
2219         }
2220 
2221         #[test]
test_mul_overflow()2222         fn test_mul_overflow() {
2223             fn test_mul_typed_overflow<T>()
2224             where
2225                 T: Integer + Bounded + Clone + Debug + NumAssign + CheckedMul,
2226             {
2227                 let two = T::one() + T::one();
2228                 let _3 = T::one() + T::one() + T::one();
2229 
2230                 // 1/big * 2/3 = 1/(max/4*3), where big is max/2
2231                 // make big = max/2, but also divisible by 2
2232                 let big = T::max_value() / two.clone() / two.clone() * two.clone();
2233                 let _1_big: Ratio<T> = Ratio::new(T::one(), big.clone());
2234                 let _2_3: Ratio<T> = Ratio::new(two.clone(), _3.clone());
2235                 assert_eq!(None, big.clone().checked_mul(&_3.clone()));
2236                 let expected = Ratio::new(T::one(), big / two.clone() * _3.clone());
2237                 assert_eq!(expected.clone(), _1_big.clone() * _2_3.clone());
2238                 assert_eq!(
2239                     Some(expected.clone()),
2240                     _1_big.clone().checked_mul(&_2_3.clone())
2241                 );
2242                 assert_eq!(expected, {
2243                     let mut tmp = _1_big;
2244                     tmp *= _2_3;
2245                     tmp
2246                 });
2247 
2248                 // big/3 * 3 = big/1
2249                 // make big = max/2, but make it indivisible by 3
2250                 let big = T::max_value() / two / _3.clone() * _3.clone() + T::one();
2251                 assert_eq!(None, big.clone().checked_mul(&_3.clone()));
2252                 let big_3 = Ratio::new(big.clone(), _3.clone());
2253                 let expected = Ratio::new(big, T::one());
2254                 assert_eq!(expected, big_3.clone() * _3.clone());
2255                 assert_eq!(expected, {
2256                     let mut tmp = big_3;
2257                     tmp *= _3;
2258                     tmp
2259                 });
2260             }
2261             test_mul_typed_overflow::<u16>();
2262             test_mul_typed_overflow::<u8>();
2263             test_mul_typed_overflow::<u32>();
2264             test_mul_typed_overflow::<u64>();
2265             test_mul_typed_overflow::<usize>();
2266             test_mul_typed_overflow::<u128>();
2267 
2268             test_mul_typed_overflow::<i8>();
2269             test_mul_typed_overflow::<i16>();
2270             test_mul_typed_overflow::<i32>();
2271             test_mul_typed_overflow::<i64>();
2272             test_mul_typed_overflow::<isize>();
2273             test_mul_typed_overflow::<i128>();
2274         }
2275 
2276         #[test]
test_div()2277         fn test_div() {
2278             fn test(a: Rational64, b: Rational64, c: Rational64) {
2279                 assert_eq!(a / b, c);
2280                 assert_eq!(
2281                     {
2282                         let mut x = a;
2283                         x /= b;
2284                         x
2285                     },
2286                     c
2287                 );
2288                 assert_eq!(to_big(a) / to_big(b), to_big(c));
2289                 assert_eq!(a.checked_div(&b), Some(c));
2290                 assert_eq!(to_big(a).checked_div(&to_big(b)), Some(to_big(c)));
2291             }
2292             fn test_assign(a: Rational64, b: i64, c: Rational64) {
2293                 assert_eq!(a / b, c);
2294                 assert_eq!(
2295                     {
2296                         let mut x = a;
2297                         x /= b;
2298                         x
2299                     },
2300                     c
2301                 );
2302             }
2303 
2304             test(_1, _1_2, _2);
2305             test(_3_2, _1_2, _1 + _2);
2306             test(_1, _NEG1_2, _NEG1_2 + _NEG1_2 + _NEG1_2 + _NEG1_2);
2307             test_assign(_1, 2, _1_2);
2308         }
2309 
2310         #[test]
test_div_overflow()2311         fn test_div_overflow() {
2312             fn test_div_typed_overflow<T>()
2313             where
2314                 T: Integer + Bounded + Clone + Debug + NumAssign + CheckedMul,
2315             {
2316                 let two = T::one() + T::one();
2317                 let _3 = T::one() + T::one() + T::one();
2318 
2319                 // 1/big / 3/2 = 1/(max/4*3), where big is max/2
2320                 // big ~ max/2, and big is divisible by 2
2321                 let big = T::max_value() / two.clone() / two.clone() * two.clone();
2322                 assert_eq!(None, big.clone().checked_mul(&_3.clone()));
2323                 let _1_big: Ratio<T> = Ratio::new(T::one(), big.clone());
2324                 let _3_two: Ratio<T> = Ratio::new(_3.clone(), two.clone());
2325                 let expected = Ratio::new(T::one(), big / two.clone() * _3.clone());
2326                 assert_eq!(expected.clone(), _1_big.clone() / _3_two.clone());
2327                 assert_eq!(
2328                     Some(expected.clone()),
2329                     _1_big.clone().checked_div(&_3_two.clone())
2330                 );
2331                 assert_eq!(expected, {
2332                     let mut tmp = _1_big;
2333                     tmp /= _3_two;
2334                     tmp
2335                 });
2336 
2337                 // 3/big / 3 = 1/big where big is max/2
2338                 // big ~ max/2, and big is not divisible by 3
2339                 let big = T::max_value() / two / _3.clone() * _3.clone() + T::one();
2340                 assert_eq!(None, big.clone().checked_mul(&_3.clone()));
2341                 let _3_big = Ratio::new(_3.clone(), big.clone());
2342                 let expected = Ratio::new(T::one(), big);
2343                 assert_eq!(expected, _3_big.clone() / _3.clone());
2344                 assert_eq!(expected, {
2345                     let mut tmp = _3_big;
2346                     tmp /= _3;
2347                     tmp
2348                 });
2349             }
2350             test_div_typed_overflow::<u8>();
2351             test_div_typed_overflow::<u16>();
2352             test_div_typed_overflow::<u32>();
2353             test_div_typed_overflow::<u64>();
2354             test_div_typed_overflow::<usize>();
2355             test_div_typed_overflow::<u128>();
2356 
2357             test_div_typed_overflow::<i8>();
2358             test_div_typed_overflow::<i16>();
2359             test_div_typed_overflow::<i32>();
2360             test_div_typed_overflow::<i64>();
2361             test_div_typed_overflow::<isize>();
2362             test_div_typed_overflow::<i128>();
2363         }
2364 
2365         #[test]
test_rem()2366         fn test_rem() {
2367             fn test(a: Rational64, b: Rational64, c: Rational64) {
2368                 assert_eq!(a % b, c);
2369                 assert_eq!(
2370                     {
2371                         let mut x = a;
2372                         x %= b;
2373                         x
2374                     },
2375                     c
2376                 );
2377                 assert_eq!(to_big(a) % to_big(b), to_big(c))
2378             }
2379             fn test_assign(a: Rational64, b: i64, c: Rational64) {
2380                 assert_eq!(a % b, c);
2381                 assert_eq!(
2382                     {
2383                         let mut x = a;
2384                         x %= b;
2385                         x
2386                     },
2387                     c
2388                 );
2389             }
2390 
2391             test(_3_2, _1, _1_2);
2392             test(_3_2, _1_2, _0);
2393             test(_5_2, _3_2, _1);
2394             test(_2, _NEG1_2, _0);
2395             test(_1_2, _2, _1_2);
2396             test_assign(_3_2, 1, _1_2);
2397         }
2398 
2399         #[test]
test_rem_overflow()2400         fn test_rem_overflow() {
2401             // tests that Ratio(1,2) % Ratio(1, T::max_value()) equals 0
2402             // for each integer type. Previously, this calculation would overflow.
2403             fn test_rem_typed_overflow<T>()
2404             where
2405                 T: Integer + Bounded + Clone + Debug + NumAssign,
2406             {
2407                 let two = T::one() + T::one();
2408                 // value near to maximum, but divisible by two
2409                 let max_div2 = T::max_value() / two.clone() * two.clone();
2410                 let _1_max: Ratio<T> = Ratio::new(T::one(), max_div2);
2411                 let _1_two: Ratio<T> = Ratio::new(T::one(), two);
2412                 assert!(T::is_zero(&(_1_two.clone() % _1_max.clone()).numer));
2413                 {
2414                     let mut tmp: Ratio<T> = _1_two;
2415                     tmp %= _1_max;
2416                     assert!(T::is_zero(&tmp.numer));
2417                 }
2418             }
2419             test_rem_typed_overflow::<u8>();
2420             test_rem_typed_overflow::<u16>();
2421             test_rem_typed_overflow::<u32>();
2422             test_rem_typed_overflow::<u64>();
2423             test_rem_typed_overflow::<usize>();
2424             test_rem_typed_overflow::<u128>();
2425 
2426             test_rem_typed_overflow::<i8>();
2427             test_rem_typed_overflow::<i16>();
2428             test_rem_typed_overflow::<i32>();
2429             test_rem_typed_overflow::<i64>();
2430             test_rem_typed_overflow::<isize>();
2431             test_rem_typed_overflow::<i128>();
2432         }
2433 
2434         #[test]
test_neg()2435         fn test_neg() {
2436             fn test(a: Rational64, b: Rational64) {
2437                 assert_eq!(-a, b);
2438                 assert_eq!(-to_big(a), to_big(b))
2439             }
2440 
2441             test(_0, _0);
2442             test(_1_2, _NEG1_2);
2443             test(-_1, _1);
2444         }
2445         #[test]
2446         #[allow(clippy::eq_op)]
test_zero()2447         fn test_zero() {
2448             assert_eq!(_0 + _0, _0);
2449             assert_eq!(_0 * _0, _0);
2450             assert_eq!(_0 * _1, _0);
2451             assert_eq!(_0 / _NEG1_2, _0);
2452             assert_eq!(_0 - _0, _0);
2453         }
2454         #[test]
2455         #[should_panic]
test_div_0()2456         fn test_div_0() {
2457             let _a = _1 / _0;
2458         }
2459 
2460         #[test]
test_checked_failures()2461         fn test_checked_failures() {
2462             let big = Ratio::new(128u8, 1);
2463             let small = Ratio::new(1, 128u8);
2464             assert_eq!(big.checked_add(&big), None);
2465             assert_eq!(small.checked_sub(&big), None);
2466             assert_eq!(big.checked_mul(&big), None);
2467             assert_eq!(small.checked_div(&big), None);
2468             assert_eq!(_1.checked_div(&_0), None);
2469         }
2470 
2471         #[test]
test_checked_zeros()2472         fn test_checked_zeros() {
2473             assert_eq!(_0.checked_add(&_0), Some(_0));
2474             assert_eq!(_0.checked_sub(&_0), Some(_0));
2475             assert_eq!(_0.checked_mul(&_0), Some(_0));
2476             assert_eq!(_0.checked_div(&_0), None);
2477         }
2478 
2479         #[test]
test_checked_min()2480         fn test_checked_min() {
2481             assert_eq!(_MIN.checked_add(&_MIN), None);
2482             assert_eq!(_MIN.checked_sub(&_MIN), Some(_0));
2483             assert_eq!(_MIN.checked_mul(&_MIN), None);
2484             assert_eq!(_MIN.checked_div(&_MIN), Some(_1));
2485             assert_eq!(_0.checked_add(&_MIN), Some(_MIN));
2486             assert_eq!(_0.checked_sub(&_MIN), None);
2487             assert_eq!(_0.checked_mul(&_MIN), Some(_0));
2488             assert_eq!(_0.checked_div(&_MIN), Some(_0));
2489             assert_eq!(_1.checked_add(&_MIN), Some(_MIN_P1));
2490             assert_eq!(_1.checked_sub(&_MIN), None);
2491             assert_eq!(_1.checked_mul(&_MIN), Some(_MIN));
2492             assert_eq!(_1.checked_div(&_MIN), None);
2493             assert_eq!(_MIN.checked_add(&_0), Some(_MIN));
2494             assert_eq!(_MIN.checked_sub(&_0), Some(_MIN));
2495             assert_eq!(_MIN.checked_mul(&_0), Some(_0));
2496             assert_eq!(_MIN.checked_div(&_0), None);
2497             assert_eq!(_MIN.checked_add(&_1), Some(_MIN_P1));
2498             assert_eq!(_MIN.checked_sub(&_1), None);
2499             assert_eq!(_MIN.checked_mul(&_1), Some(_MIN));
2500             assert_eq!(_MIN.checked_div(&_1), Some(_MIN));
2501         }
2502 
2503         #[test]
test_checked_max()2504         fn test_checked_max() {
2505             assert_eq!(_MAX.checked_add(&_MAX), None);
2506             assert_eq!(_MAX.checked_sub(&_MAX), Some(_0));
2507             assert_eq!(_MAX.checked_mul(&_MAX), None);
2508             assert_eq!(_MAX.checked_div(&_MAX), Some(_1));
2509             assert_eq!(_0.checked_add(&_MAX), Some(_MAX));
2510             assert_eq!(_0.checked_sub(&_MAX), Some(_MIN_P1));
2511             assert_eq!(_0.checked_mul(&_MAX), Some(_0));
2512             assert_eq!(_0.checked_div(&_MAX), Some(_0));
2513             assert_eq!(_1.checked_add(&_MAX), None);
2514             assert_eq!(_1.checked_sub(&_MAX), Some(-_MAX_M1));
2515             assert_eq!(_1.checked_mul(&_MAX), Some(_MAX));
2516             assert_eq!(_1.checked_div(&_MAX), Some(_MAX.recip()));
2517             assert_eq!(_MAX.checked_add(&_0), Some(_MAX));
2518             assert_eq!(_MAX.checked_sub(&_0), Some(_MAX));
2519             assert_eq!(_MAX.checked_mul(&_0), Some(_0));
2520             assert_eq!(_MAX.checked_div(&_0), None);
2521             assert_eq!(_MAX.checked_add(&_1), None);
2522             assert_eq!(_MAX.checked_sub(&_1), Some(_MAX_M1));
2523             assert_eq!(_MAX.checked_mul(&_1), Some(_MAX));
2524             assert_eq!(_MAX.checked_div(&_1), Some(_MAX));
2525         }
2526 
2527         #[test]
test_checked_min_max()2528         fn test_checked_min_max() {
2529             assert_eq!(_MIN.checked_add(&_MAX), Some(-_1));
2530             assert_eq!(_MIN.checked_sub(&_MAX), None);
2531             assert_eq!(_MIN.checked_mul(&_MAX), None);
2532             assert_eq!(
2533                 _MIN.checked_div(&_MAX),
2534                 Some(Ratio::new(_MIN.numer, _MAX.numer))
2535             );
2536             assert_eq!(_MAX.checked_add(&_MIN), Some(-_1));
2537             assert_eq!(_MAX.checked_sub(&_MIN), None);
2538             assert_eq!(_MAX.checked_mul(&_MIN), None);
2539             assert_eq!(_MAX.checked_div(&_MIN), None);
2540         }
2541     }
2542 
2543     #[test]
test_round()2544     fn test_round() {
2545         assert_eq!(_1_3.ceil(), _1);
2546         assert_eq!(_1_3.floor(), _0);
2547         assert_eq!(_1_3.round(), _0);
2548         assert_eq!(_1_3.trunc(), _0);
2549 
2550         assert_eq!(_NEG1_3.ceil(), _0);
2551         assert_eq!(_NEG1_3.floor(), -_1);
2552         assert_eq!(_NEG1_3.round(), _0);
2553         assert_eq!(_NEG1_3.trunc(), _0);
2554 
2555         assert_eq!(_2_3.ceil(), _1);
2556         assert_eq!(_2_3.floor(), _0);
2557         assert_eq!(_2_3.round(), _1);
2558         assert_eq!(_2_3.trunc(), _0);
2559 
2560         assert_eq!(_NEG2_3.ceil(), _0);
2561         assert_eq!(_NEG2_3.floor(), -_1);
2562         assert_eq!(_NEG2_3.round(), -_1);
2563         assert_eq!(_NEG2_3.trunc(), _0);
2564 
2565         assert_eq!(_1_2.ceil(), _1);
2566         assert_eq!(_1_2.floor(), _0);
2567         assert_eq!(_1_2.round(), _1);
2568         assert_eq!(_1_2.trunc(), _0);
2569 
2570         assert_eq!(_NEG1_2.ceil(), _0);
2571         assert_eq!(_NEG1_2.floor(), -_1);
2572         assert_eq!(_NEG1_2.round(), -_1);
2573         assert_eq!(_NEG1_2.trunc(), _0);
2574 
2575         assert_eq!(_1.ceil(), _1);
2576         assert_eq!(_1.floor(), _1);
2577         assert_eq!(_1.round(), _1);
2578         assert_eq!(_1.trunc(), _1);
2579 
2580         // Overflow checks
2581 
2582         let _neg1 = Ratio::from_integer(-1);
2583         let _large_rat1 = Ratio::new(i32::MAX, i32::MAX - 1);
2584         let _large_rat2 = Ratio::new(i32::MAX - 1, i32::MAX);
2585         let _large_rat3 = Ratio::new(i32::MIN + 2, i32::MIN + 1);
2586         let _large_rat4 = Ratio::new(i32::MIN + 1, i32::MIN + 2);
2587         let _large_rat5 = Ratio::new(i32::MIN + 2, i32::MAX);
2588         let _large_rat6 = Ratio::new(i32::MAX, i32::MIN + 2);
2589         let _large_rat7 = Ratio::new(1, i32::MIN + 1);
2590         let _large_rat8 = Ratio::new(1, i32::MAX);
2591 
2592         assert_eq!(_large_rat1.round(), One::one());
2593         assert_eq!(_large_rat2.round(), One::one());
2594         assert_eq!(_large_rat3.round(), One::one());
2595         assert_eq!(_large_rat4.round(), One::one());
2596         assert_eq!(_large_rat5.round(), _neg1);
2597         assert_eq!(_large_rat6.round(), _neg1);
2598         assert_eq!(_large_rat7.round(), Zero::zero());
2599         assert_eq!(_large_rat8.round(), Zero::zero());
2600     }
2601 
2602     #[test]
test_fract()2603     fn test_fract() {
2604         assert_eq!(_1.fract(), _0);
2605         assert_eq!(_NEG1_2.fract(), _NEG1_2);
2606         assert_eq!(_1_2.fract(), _1_2);
2607         assert_eq!(_3_2.fract(), _1_2);
2608     }
2609 
2610     #[test]
test_recip()2611     fn test_recip() {
2612         assert_eq!(_1 * _1.recip(), _1);
2613         assert_eq!(_2 * _2.recip(), _1);
2614         assert_eq!(_1_2 * _1_2.recip(), _1);
2615         assert_eq!(_3_2 * _3_2.recip(), _1);
2616         assert_eq!(_NEG1_2 * _NEG1_2.recip(), _1);
2617 
2618         assert_eq!(_3_2.recip(), _2_3);
2619         assert_eq!(_NEG1_2.recip(), _NEG2);
2620         assert_eq!(_NEG1_2.recip().denom(), &1);
2621     }
2622 
2623     #[test]
2624     #[should_panic(expected = "division by zero")]
test_recip_fail()2625     fn test_recip_fail() {
2626         let _a = Ratio::new(0, 1).recip();
2627     }
2628 
2629     #[test]
test_pow()2630     fn test_pow() {
2631         fn test(r: Rational64, e: i32, expected: Rational64) {
2632             assert_eq!(r.pow(e), expected);
2633             assert_eq!(Pow::pow(r, e), expected);
2634             assert_eq!(Pow::pow(r, &e), expected);
2635             assert_eq!(Pow::pow(&r, e), expected);
2636             assert_eq!(Pow::pow(&r, &e), expected);
2637             #[cfg(feature = "num-bigint")]
2638             test_big(r, e, expected);
2639         }
2640 
2641         #[cfg(feature = "num-bigint")]
2642         fn test_big(r: Rational64, e: i32, expected: Rational64) {
2643             let r = BigRational::new_raw(r.numer.into(), r.denom.into());
2644             let expected = BigRational::new_raw(expected.numer.into(), expected.denom.into());
2645             assert_eq!((&r).pow(e), expected);
2646             assert_eq!(Pow::pow(r.clone(), e), expected);
2647             assert_eq!(Pow::pow(r.clone(), &e), expected);
2648             assert_eq!(Pow::pow(&r, e), expected);
2649             assert_eq!(Pow::pow(&r, &e), expected);
2650         }
2651 
2652         test(_1_2, 2, Ratio::new(1, 4));
2653         test(_1_2, -2, Ratio::new(4, 1));
2654         test(_1, 1, _1);
2655         test(_1, i32::MAX, _1);
2656         test(_1, i32::MIN, _1);
2657         test(_NEG1_2, 2, _1_2.pow(2i32));
2658         test(_NEG1_2, 3, -_1_2.pow(3i32));
2659         test(_3_2, 0, _1);
2660         test(_3_2, -1, _3_2.recip());
2661         test(_3_2, 3, Ratio::new(27, 8));
2662     }
2663 
2664     #[test]
2665     #[cfg(feature = "std")]
test_to_from_str()2666     fn test_to_from_str() {
2667         use std::string::{String, ToString};
2668         fn test(r: Rational64, s: String) {
2669             assert_eq!(FromStr::from_str(&s), Ok(r));
2670             assert_eq!(r.to_string(), s);
2671         }
2672         test(_1, "1".to_string());
2673         test(_0, "0".to_string());
2674         test(_1_2, "1/2".to_string());
2675         test(_3_2, "3/2".to_string());
2676         test(_2, "2".to_string());
2677         test(_NEG1_2, "-1/2".to_string());
2678     }
2679     #[test]
test_from_str_fail()2680     fn test_from_str_fail() {
2681         fn test(s: &str) {
2682             let rational: Result<Rational64, _> = FromStr::from_str(s);
2683             assert!(rational.is_err());
2684         }
2685 
2686         let xs = ["0 /1", "abc", "", "1/", "--1/2", "3/2/1", "1/0"];
2687         for &s in xs.iter() {
2688             test(s);
2689         }
2690     }
2691 
2692     #[cfg(feature = "num-bigint")]
2693     #[test]
test_from_float()2694     fn test_from_float() {
2695         use num_traits::float::FloatCore;
2696         fn test<T: FloatCore>(given: T, (numer, denom): (&str, &str)) {
2697             let ratio: BigRational = Ratio::from_float(given).unwrap();
2698             assert_eq!(
2699                 ratio,
2700                 Ratio::new(
2701                     FromStr::from_str(numer).unwrap(),
2702                     FromStr::from_str(denom).unwrap()
2703                 )
2704             );
2705         }
2706 
2707         // f32
2708         test(core::f32::consts::PI, ("13176795", "4194304"));
2709         test(2f32.powf(100.), ("1267650600228229401496703205376", "1"));
2710         test(
2711             -(2f32.powf(100.)),
2712             ("-1267650600228229401496703205376", "1"),
2713         );
2714         test(
2715             1.0 / 2f32.powf(100.),
2716             ("1", "1267650600228229401496703205376"),
2717         );
2718         test(684729.48391f32, ("1369459", "2"));
2719         test(-8573.5918555f32, ("-4389679", "512"));
2720 
2721         // f64
2722         test(
2723             core::f64::consts::PI,
2724             ("884279719003555", "281474976710656"),
2725         );
2726         test(2f64.powf(100.), ("1267650600228229401496703205376", "1"));
2727         test(
2728             -(2f64.powf(100.)),
2729             ("-1267650600228229401496703205376", "1"),
2730         );
2731         test(684729.48391f64, ("367611342500051", "536870912"));
2732         test(-8573.5918555f64, ("-4713381968463931", "549755813888"));
2733         test(
2734             1.0 / 2f64.powf(100.),
2735             ("1", "1267650600228229401496703205376"),
2736         );
2737     }
2738 
2739     #[cfg(feature = "num-bigint")]
2740     #[test]
test_from_float_fail()2741     fn test_from_float_fail() {
2742         use core::{f32, f64};
2743 
2744         assert_eq!(Ratio::from_float(f32::NAN), None);
2745         assert_eq!(Ratio::from_float(f32::INFINITY), None);
2746         assert_eq!(Ratio::from_float(f32::NEG_INFINITY), None);
2747         assert_eq!(Ratio::from_float(f64::NAN), None);
2748         assert_eq!(Ratio::from_float(f64::INFINITY), None);
2749         assert_eq!(Ratio::from_float(f64::NEG_INFINITY), None);
2750     }
2751 
2752     #[test]
test_signed()2753     fn test_signed() {
2754         assert_eq!(_NEG1_2.abs(), _1_2);
2755         assert_eq!(_3_2.abs_sub(&_1_2), _1);
2756         assert_eq!(_1_2.abs_sub(&_3_2), Zero::zero());
2757         assert_eq!(_1_2.signum(), One::one());
2758         assert_eq!(_NEG1_2.signum(), -<Ratio<i64>>::one());
2759         assert_eq!(_0.signum(), Zero::zero());
2760         assert!(_NEG1_2.is_negative());
2761         assert!(_1_NEG2.is_negative());
2762         assert!(!_NEG1_2.is_positive());
2763         assert!(!_1_NEG2.is_positive());
2764         assert!(_1_2.is_positive());
2765         assert!(_NEG1_NEG2.is_positive());
2766         assert!(!_1_2.is_negative());
2767         assert!(!_NEG1_NEG2.is_negative());
2768         assert!(!_0.is_positive());
2769         assert!(!_0.is_negative());
2770     }
2771 
2772     #[test]
2773     #[cfg(feature = "std")]
test_hash()2774     fn test_hash() {
2775         assert!(crate::hash(&_0) != crate::hash(&_1));
2776         assert!(crate::hash(&_0) != crate::hash(&_3_2));
2777 
2778         // a == b -> hash(a) == hash(b)
2779         let a = Rational64::new_raw(4, 2);
2780         let b = Rational64::new_raw(6, 3);
2781         assert_eq!(a, b);
2782         assert_eq!(crate::hash(&a), crate::hash(&b));
2783 
2784         let a = Rational64::new_raw(123456789, 1000);
2785         let b = Rational64::new_raw(123456789 * 5, 5000);
2786         assert_eq!(a, b);
2787         assert_eq!(crate::hash(&a), crate::hash(&b));
2788     }
2789 
2790     #[test]
test_into_pair()2791     fn test_into_pair() {
2792         assert_eq!((0, 1), _0.into());
2793         assert_eq!((-2, 1), _NEG2.into());
2794         assert_eq!((1, -2), _1_NEG2.into());
2795     }
2796 
2797     #[test]
test_from_pair()2798     fn test_from_pair() {
2799         assert_eq!(_0, Ratio::from((0, 1)));
2800         assert_eq!(_1, Ratio::from((1, 1)));
2801         assert_eq!(_NEG2, Ratio::from((-2, 1)));
2802         assert_eq!(_1_NEG2, Ratio::from((1, -2)));
2803     }
2804 
2805     #[test]
ratio_iter_sum()2806     fn ratio_iter_sum() {
2807         // generic function to assure the iter method can be called
2808         // for any Iterator with Item = Ratio<impl Integer> or Ratio<&impl Integer>
2809         fn iter_sums<T: Integer + Clone>(slice: &[Ratio<T>]) -> [Ratio<T>; 3] {
2810             let mut manual_sum = Ratio::new(T::zero(), T::one());
2811             for ratio in slice {
2812                 manual_sum = manual_sum + ratio;
2813             }
2814             [manual_sum, slice.iter().sum(), slice.iter().cloned().sum()]
2815         }
2816         // collect into array so test works on no_std
2817         let mut nums = [Ratio::new(0, 1); 1000];
2818         for (i, r) in (0..1000).map(|n| Ratio::new(n, 500)).enumerate() {
2819             nums[i] = r;
2820         }
2821         let sums = iter_sums(&nums[..]);
2822         assert_eq!(sums[0], sums[1]);
2823         assert_eq!(sums[0], sums[2]);
2824     }
2825 
2826     #[test]
ratio_iter_product()2827     fn ratio_iter_product() {
2828         // generic function to assure the iter method can be called
2829         // for any Iterator with Item = Ratio<impl Integer> or Ratio<&impl Integer>
2830         fn iter_products<T: Integer + Clone>(slice: &[Ratio<T>]) -> [Ratio<T>; 3] {
2831             let mut manual_prod = Ratio::new(T::one(), T::one());
2832             for ratio in slice {
2833                 manual_prod = manual_prod * ratio;
2834             }
2835             [
2836                 manual_prod,
2837                 slice.iter().product(),
2838                 slice.iter().cloned().product(),
2839             ]
2840         }
2841 
2842         // collect into array so test works on no_std
2843         let mut nums = [Ratio::new(0, 1); 1000];
2844         for (i, r) in (0..1000).map(|n| Ratio::new(n, 500)).enumerate() {
2845             nums[i] = r;
2846         }
2847         let products = iter_products(&nums[..]);
2848         assert_eq!(products[0], products[1]);
2849         assert_eq!(products[0], products[2]);
2850     }
2851 
2852     #[test]
test_num_zero()2853     fn test_num_zero() {
2854         let zero = Rational64::zero();
2855         assert!(zero.is_zero());
2856 
2857         let mut r = Rational64::new(123, 456);
2858         assert!(!r.is_zero());
2859         assert_eq!(r + zero, r);
2860 
2861         r.set_zero();
2862         assert!(r.is_zero());
2863     }
2864 
2865     #[test]
test_num_one()2866     fn test_num_one() {
2867         let one = Rational64::one();
2868         assert!(one.is_one());
2869 
2870         let mut r = Rational64::new(123, 456);
2871         assert!(!r.is_one());
2872         assert_eq!(r * one, r);
2873 
2874         r.set_one();
2875         assert!(r.is_one());
2876     }
2877 
2878     #[test]
test_const()2879     fn test_const() {
2880         const N: Ratio<i32> = Ratio::new_raw(123, 456);
2881         const N_NUMER: &i32 = N.numer();
2882         const N_DENOM: &i32 = N.denom();
2883 
2884         assert_eq!(N_NUMER, &123);
2885         assert_eq!(N_DENOM, &456);
2886 
2887         let r = N.reduced();
2888         assert_eq!(r.numer(), &(123 / 3));
2889         assert_eq!(r.denom(), &(456 / 3));
2890     }
2891 
2892     #[test]
test_ratio_to_i64()2893     fn test_ratio_to_i64() {
2894         assert_eq!(5, Rational64::new(70, 14).to_u64().unwrap());
2895         assert_eq!(-3, Rational64::new(-31, 8).to_i64().unwrap());
2896         assert_eq!(None, Rational64::new(-31, 8).to_u64());
2897     }
2898 
2899     #[test]
2900     #[cfg(feature = "num-bigint")]
test_ratio_to_i128()2901     fn test_ratio_to_i128() {
2902         assert_eq!(
2903             1i128 << 70,
2904             Ratio::<i128>::new(1i128 << 77, 1i128 << 7)
2905                 .to_i128()
2906                 .unwrap()
2907         );
2908     }
2909 
2910     #[test]
2911     #[cfg(feature = "num-bigint")]
test_big_ratio_to_f64()2912     fn test_big_ratio_to_f64() {
2913         assert_eq!(
2914             BigRational::new(
2915                 "1234567890987654321234567890987654321234567890"
2916                     .parse()
2917                     .unwrap(),
2918                 "3".parse().unwrap()
2919             )
2920             .to_f64(),
2921             Some(411522630329218100000000000000000000000000000f64)
2922         );
2923         assert_eq!(
2924             BigRational::new(BigInt::one(), BigInt::one() << 1050).to_f64(),
2925             Some(0f64)
2926         );
2927         assert_eq!(
2928             BigRational::from(BigInt::one() << 1050).to_f64(),
2929             Some(core::f64::INFINITY)
2930         );
2931         assert_eq!(
2932             BigRational::from((-BigInt::one()) << 1050).to_f64(),
2933             Some(core::f64::NEG_INFINITY)
2934         );
2935         assert_eq!(
2936             BigRational::new(
2937                 "1234567890987654321234567890".parse().unwrap(),
2938                 "987654321234567890987654321".parse().unwrap()
2939             )
2940             .to_f64(),
2941             Some(1.2499999893125f64)
2942         );
2943         assert_eq!(
2944             BigRational::new_raw(BigInt::one(), BigInt::zero()).to_f64(),
2945             Some(core::f64::INFINITY)
2946         );
2947         assert_eq!(
2948             BigRational::new_raw(-BigInt::one(), BigInt::zero()).to_f64(),
2949             Some(core::f64::NEG_INFINITY)
2950         );
2951         assert_eq!(
2952             BigRational::new_raw(BigInt::zero(), BigInt::zero()).to_f64(),
2953             None
2954         );
2955     }
2956 
2957     #[test]
test_ratio_to_f64()2958     fn test_ratio_to_f64() {
2959         assert_eq!(Ratio::<u8>::new(1, 2).to_f64(), Some(0.5f64));
2960         assert_eq!(Rational64::new(1, 2).to_f64(), Some(0.5f64));
2961         assert_eq!(Rational64::new(1, -2).to_f64(), Some(-0.5f64));
2962         assert_eq!(Rational64::new(0, 2).to_f64(), Some(0.0f64));
2963         assert_eq!(Rational64::new(0, -2).to_f64(), Some(-0.0f64));
2964         assert_eq!(Rational64::new((1 << 57) + 1, 1 << 54).to_f64(), Some(8f64));
2965         assert_eq!(
2966             Rational64::new((1 << 52) + 1, 1 << 52).to_f64(),
2967             Some(1.0000000000000002f64),
2968         );
2969         assert_eq!(
2970             Rational64::new((1 << 60) + (1 << 8), 1 << 60).to_f64(),
2971             Some(1.0000000000000002f64),
2972         );
2973         assert_eq!(
2974             Ratio::<i32>::new_raw(1, 0).to_f64(),
2975             Some(core::f64::INFINITY)
2976         );
2977         assert_eq!(
2978             Ratio::<i32>::new_raw(-1, 0).to_f64(),
2979             Some(core::f64::NEG_INFINITY)
2980         );
2981         assert_eq!(Ratio::<i32>::new_raw(0, 0).to_f64(), None);
2982     }
2983 }
2984