Coverage Report

Created: 2021-11-03 07:11

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