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