num_rational/
lib.rs

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