extended_rational/
lib.rs

1//! Provides implementations of high-accuracy projectively-extended rational numbers
2//! and macros for creating them
3//!
4//! Projectively-extended rationals differ from normal rationals because they have
5//! a single, signless infinity and a single, signless zero. This means that `1/0`
6//! can be defined as equal to `∞` and `1/∞` equal to `0`.
7//!
8//! # Infinity
9//!
10//! For unsigned numbers, `∞` is greater than every number, whereas with signed numbers,
11//! `∞` is not comparable to any number but itself. This is because `∞` equals `-∞` so no
12//! ordering can exist.
13//!
14//! # NaN
15//!
16//! `∞ + ∞`, `∞ - ∞`, `∞ * 0`, `0 * ∞`, `∞ / ∞`, and `0 / 0` are all `NaN`
17//!
18//! A value of `NaN` in any operation always returns `NaN`. `NaN` is not ordered and
19//! is not equal to any number, including itself.
20//!
21//! # Panics
22//!
23//! No operation should ever panic. Operations that overflow round each input to a
24//! simpler fraction until they can succeed. Any invalid operations should
25//! return `NaN` instead of panicking.
26//!
27//! # Additional Features
28//!
29//! For use with the [bit manager] crate, add this to your `Cargo.toml`:
30//!
31//! ```toml
32//! [features]
33//! default = ["extended-rational/bit_manager_enabled"]
34//! ```
35//!
36//! [bit manager]: http://docs.rs/bit_manager
37
38#![deny(missing_docs, trivial_casts, unused_macros)]
39
40#[macro_use]
41#[cfg(feature="bit_manager_enabled")]
42extern crate bit_manager_derive;
43
44use std::*;
45use std::cmp::*;
46use std::ops::*;
47
48/// A macro for creating a new [signed rational](struct.Rational.html) using a given ratio or decimal
49///
50/// *Floating-point conversions may be wrong due to small rounding errors.*
51///
52/// # Alternatives
53///
54/// * `ratio!(n, d)` is equivalent to `Rational::from([n, d])`
55/// * `ratio!(n)` is equivalent to `Rational::from(n)`
56///
57/// # Examples
58///
59/// ```
60/// # #[macro_use]
61/// # extern crate extended_rational;
62/// # use extended_rational::Rational;
63/// # fn main() {
64/// let five_thirds = ratio!(5, 3);
65/// let neg_seven_and_a_half = ratio!(-7.5);
66///
67/// assert_eq!(five_thirds, Rational::from([5, 3]));
68/// assert_eq!(neg_seven_and_a_half, Rational::new(-15, 2));
69/// # }
70/// ```
71#[macro_export]
72macro_rules! ratio {
73    ( $ n : expr , $ d : expr ) => ( $crate::Rational::from([$n, $d]) );
74    ( $ n : expr ) => ( $crate::Rational::from($n) );
75}
76
77/// A macro for creating a new [unsigned rational](struct.URational.html) using a given ratio or decimal
78///
79/// *Floating-point conversions may be wrong due to small rounding errors.*
80///
81/// # Panics
82///
83/// On attempt to create negative rational. *Doesn't panic in optimized builds.*
84///
85/// # Alternatives
86///
87/// * `uratio!(n, d)` is equivalent to `ratio!(n, d).try_unsigned()`
88/// * `uratio!(n)` is equivalent to `ratio!(n).try_unsigned()`
89///
90/// # Examples
91///
92/// ```
93/// # #[macro_use]
94/// # extern crate extended_rational;
95/// # use extended_rational::URational;
96/// # fn main() {
97/// let five_thirds = uratio!(5, 3);
98/// let seventeen = uratio!(17);
99///
100/// assert_eq!(five_thirds, URational::new(5, 3));
101/// assert_eq!(seventeen, URational::new(17, 1));
102/// # }
103/// ```
104#[macro_export]
105macro_rules! uratio {
106    ( $ n : expr , $ d : expr ) => {{
107        $crate::Rational::from([$n, $d]).try_unsigned()
108    }};
109    ( $ n : expr ) => {{
110        $crate::Rational::from($n).try_unsigned()
111    }};
112}
113
114macro_rules! try_or {
115    (continue $x: expr) => {
116        match $x {
117            Some(x) => x,
118            None => continue,
119        }
120    };
121    (return $r: expr; $x: expr) => {
122        match $x {
123            Some(x) => x,
124            None => return $r,
125        }
126    };
127    (return $x: expr) => {
128        match $x {
129            Some(x) => x,
130            None => return None,
131        }
132    };
133}
134
135macro_rules! impl_u_from {
136    ($($t: ty)+) => {
137        $(
138            impl From<$t> for URational {
139                /// Create a new unsigned rational with the given value.
140                fn from(n: $t) -> URational {
141                    URational::new(n as u64, 1)
142                }
143            }
144            impl From<($t, $t)> for URational {
145                /// Create a new unsigned rational with the given numerator and denominator tuple.
146                fn from(tuple: ($t, $t)) -> URational {
147                    let (n, d) = tuple;
148                    URational::new(n as u64, d as u64)
149                }
150            }
151            impl From<[$t; 2]> for URational {
152                /// Create a new unsigned rational with the given numerator and denominator array.
153                fn from(array: [$t; 2]) -> URational {
154                    URational::new(array[0] as u64, array[1] as u64)
155                }
156            }
157            impl From<$t> for Rational {
158                /// Create a new signed rational with the given value.
159                fn from(n: $t) -> Rational {
160                    Rational::from(URational::from(n))
161                }
162            }
163            impl From<($t, $t)> for Rational {
164                /// Create a new signed rational with the given numerator and denominator tuple.
165                fn from(tuple: ($t, $t)) -> Rational {
166                    Rational::from(URational::from(tuple))
167                }
168            }
169            impl From<[$t; 2]> for Rational {
170                /// Create a new signed rational with the given numerator and denominator array.
171                fn from(array: [$t; 2]) -> Rational {
172                    Rational::from(URational::from(array))
173                }
174            }
175        )+
176    }
177}
178
179macro_rules! impl_from {
180    ($($t: ty)+) => {
181        $(
182            impl From<$t> for Rational {
183                /// Creates a new signed rational with the given value.
184                fn from(n: $t) -> Rational {
185                    Rational::new(n as i64, 1)
186                }
187            }
188            impl From<($t, $t)> for Rational {
189                /// Creates a new signed rational with the given numerator and denominator tuple.
190                fn from(tuple: ($t, $t)) -> Rational {
191                    let (n, d) = tuple;
192                    Rational::new(n as i64, d as i64)
193                }
194            }
195            impl From<[$t; 2]> for Rational {
196                /// Creates a new signed rational with the given numerator and denominator array.
197                fn from(array: [$t; 2]) -> Rational {
198                    Rational::new(array[0] as i64, array[1] as i64)
199                }
200            }
201        )+
202    }
203}
204
205macro_rules! impl_float {
206    ($($t: ty [$total: expr, $sig: expr])+) => {
207        $(
208            impl From<URational> for $t {
209                /// Creates an approximation of the given unsigned rational.
210                fn from(r: URational) -> $t {
211                    (r.numerator as $t) / (r.denominator as $t)
212                }
213            }
214            impl From<Rational> for $t {
215                /// Creates an approximation of the given signed rational.
216                fn from(r: Rational) -> $t {
217                    (if r.negative { -1.0 } else { 1.0 }) * (r.unsigned.numerator as $t) / (r.unsigned.denominator as $t)
218                }
219            }
220            impl From<$t> for Rational {
221                /// Attempts to approximate the given floating-point number with a signed rational.
222                ///
223                /// ## Rounding
224                ///
225                /// * If the exponent is too large, `∞` will be returned
226                /// * If the exponent is too small, `0` will be returned
227                fn from(f: $t) -> Rational {
228                    match f.classify() {
229                        std::num::FpCategory::Infinite => return Rational::infinity(),
230                        std::num::FpCategory::Nan => return Rational::nan(),
231                        std::num::FpCategory::Zero | std::num::FpCategory::Subnormal => return Rational::zero(),
232                        _ => (),
233                    }
234
235                    let bits = f.to_bits() as u64;
236                    let neg = (bits >> ($total - 1)) == 1;
237                    let exponent = ((bits >> $sig) & ((1u64 << ($total - 1 - $sig)) - 1)) as i32 - ((1i32 << ($total - 2 - $sig)) - 1) - $sig;
238                    let significand = (1u64 << $sig) + (bits & ((1u64 << $sig) - 1));
239
240                    if exponent < 0 {
241                        if let Some(modifier) = 1u64.checked_shl(-exponent as u32) {
242                            Rational::new_raw(URational::new(significand, modifier), neg)
243                        } else {
244                            Rational::zero()
245                        }
246                    } else {
247                        if let Some(sig_mod) = significand.checked_shl(exponent as u32) {
248                            Rational::new_raw(URational::new(sig_mod, 1), neg)
249                        } else {
250                            Rational::infinity()
251                        }
252                    }
253                }
254            }
255        )+
256    }
257}
258
259macro_rules! impl_ops {
260    ($rational: ident; $assign: ident $non: ident, $assign_name: ident $non_name: ident, $f: ident $($b: expr)*) => {
261        impl $assign for $rational {
262            #[inline]
263            fn $assign_name(&mut self, mut other: $rational) {
264                self.$f(&mut other $(, $b)*);
265            }
266        }
267        impl $non for $rational {
268            type Output = $rational;
269
270            #[inline]
271            fn $non_name(self, mut other: $rational) -> $rational {
272                let mut r = self;
273                r.$f(&mut other$(, $b)*);
274                r
275            }
276        }
277    };
278    ($assign: ident $non: ident, $assign_name: ident $non_name: ident, $f: ident $($b: expr)*) => {
279        impl_ops!(URational; $assign $non, $assign_name $non_name, $f $($b)*);
280        impl_ops!(Rational; $assign $non, $assign_name $non_name, $f $($b)*);
281    }
282}
283
284/// Returns the greatest common divisor of two numbers.
285pub fn gcd(mut a: u64, mut b: u64) -> u64 {
286    while b != 0 {
287        let c = b;
288        b = a % b;
289        a = c;
290    }
291    a
292}
293
294/// Returns the least common multiple of two numbers
295/// or `None` if the calculation overflows.
296pub fn lcm(a: u64, b: u64) -> Option<u64> {
297    a.checked_mul(b/gcd(a, b))
298}
299
300/// A type representing an unsigned projectively-extended rational number
301///
302/// Subtracting a large number from a smaller one always returns `0` unless
303/// the larger number is `∞`.
304///
305/// # Examples
306///
307/// ```
308/// use extended_rational::URational;
309///
310/// let a = URational::new(3, 17);
311/// let b = URational::new(4, 7);
312///
313/// assert_eq!(a+b, URational::new(89, 119));
314/// ```
315///
316/// Use the [uratio!](macro.uratio.html) macro for more convenient use.
317///
318/// ```
319/// # #[macro_use]
320/// # extern crate extended_rational;
321/// # #[allow(unused_variables)]
322/// # fn main() {
323/// let a = uratio!(3, 17);
324/// let b = uratio!(4, 7);
325/// # }
326/// ```
327///
328/// Or for easy conversions from primitive types.
329///
330/// ```
331/// # #[macro_use]
332/// # extern crate extended_rational;
333/// # #[allow(unused_variables)]
334/// # fn main() {
335/// let a = uratio!(343.863);
336/// let b = uratio!(2u8);
337/// # }
338/// ```
339#[derive(Copy, Clone)]
340#[cfg_attr(feature="bit_manager_enabled", derive(BitStore))]
341pub struct URational {
342    numerator: u64,
343    denominator: u64,
344}
345
346impl URational {
347    /// Create a new unsigned rational with the given numerator and denominator.
348    pub fn new(numerator: u64, denominator: u64) -> URational {
349        let mut r = URational {
350            numerator,
351            denominator,
352        };
353        r.simplify();
354        r
355    }
356
357    /// Returns the numerator of this rational.
358    #[inline(always)] pub fn numerator(self) -> u64 { self.numerator }
359
360    /// Returns the numerator of this rational mutably.
361    #[inline(always)] pub fn numerator_mut(&mut self) -> &mut u64 { &mut self.numerator }
362
363    /// Returns the denominator of this rational.
364    #[inline(always)] pub fn denominator(self) -> u64 { self.denominator }
365
366    /// Returns the denominator of this rational mutably.
367    #[inline(always)] pub fn denominator_mut(&mut self) -> &mut u64 { &mut self.denominator }
368
369    /// Returns the smallest value an unsigned rational can store.
370    #[inline(always)] pub fn min_value() -> URational { URational { numerator: 0, denominator: 1 } }
371
372    /// Returns the smallest non-zero value an unsigned rational can store.
373    #[inline(always)] pub fn min_pos_value() -> URational { URational { numerator: 1, denominator: u64::MAX } }
374
375    /// Returns the largest value an unsigned rational can store.
376    #[inline(always)] pub fn max_value() -> URational { URational { numerator: u64::MAX, denominator: 1 } }
377
378    /// Returns an unsigned rational representing `NaN`.
379    #[inline(always)] pub fn nan() -> URational { URational { numerator: 0, denominator: 0 } }
380
381    /// Returns an unsigned rational representing `0`.
382    #[inline(always)] pub fn zero() -> URational { URational { numerator: 0, denominator: 1 } }
383
384    /// Returns an unsigned rational representing `∞`.
385    #[inline(always)] pub fn infinity() -> URational { URational { numerator: 1, denominator: 0 } }
386
387    /// Returns an unsigned rational representing `1`.
388    #[inline(always)] pub fn one() -> URational { URational { numerator: 1, denominator: 1 } }
389
390    /// Returns `true` if this rational is `NaN` and `false` otherwise.
391    #[inline] pub fn is_nan(self) -> bool { self.numerator == 0 && self.denominator == 0 }
392
393    /// Returns `true` if this rational is `0` and `false` otherwise.
394    #[inline] pub fn is_zero(self) -> bool { self.numerator == 0 && self.denominator != 0 }
395
396    /// Returns `true` if this rational is `∞` and `false` otherwise.
397    #[inline] pub fn is_infinity(self) -> bool { self.numerator != 0 && self.denominator == 0 }
398
399    /// Returns `true` if this rational is a signed number (not `NaN`, `0`, or `∞`) and `false` otherwise.
400    #[inline] pub fn is_signed(self) -> bool { self.numerator != 0 && self.denominator != 0 }
401
402    /// Returns the reciprocal of this rational.
403    #[inline] pub fn reciprocal(self) -> URational { URational { numerator: self.denominator, denominator: self.numerator } }
404
405    /// Returns the complexity of this rational (max of numerator and denominator).
406    #[inline] pub fn complexity(self) -> u64 { max(self.numerator, self.denominator) }
407
408    /// Returns this rational with no fractional component by rounding down.
409    pub fn floor(self) -> URational {
410        if self.denominator != 0 {
411            URational {
412                numerator: self.numerator / self.denominator,
413                denominator: 1,
414            }
415        } else {
416            self
417        }
418    }
419
420    /// Returns this rational with no fractional component by rounding.
421    pub fn round(self) -> URational {
422        if self.denominator != 0 {
423            if (self.numerator % self.denominator) > self.denominator/2 {
424                URational {
425                    numerator: (self.numerator / self.denominator) + 1,
426                    denominator: 1,
427                }
428            } else {
429                URational {
430                    numerator: self.numerator / self.denominator,
431                    denominator: 1,
432                }
433            }
434        } else {
435            self
436        }
437    }
438
439    /// Returns this rational with no fractional component by rounding up.
440    pub fn ceil(self) -> URational {
441        if self.denominator != 0 {
442            if (self.numerator % self.denominator) != 0 {
443                URational {
444                    numerator: (self.numerator / self.denominator) + 1,
445                    denominator: 1,
446                }
447            } else {
448                URational {
449                    numerator: self.numerator / self.denominator,
450                    denominator: 1,
451                }
452            }
453        } else {
454            self
455        }
456    }
457
458    /// Computes `self + other`, returning `None` if rounding occurred.
459    pub fn add_exact(mut self, mut other: URational) -> Option<URational> {
460        if self.add_sub_exact(&mut other, false) {
461            Some(self)
462        } else {
463            None
464        }
465    }
466
467    /// Computes `self - other`, returning `None` if rounding occurred.
468    pub fn sub_exact(mut self, mut other: URational) -> Option<URational> {
469        if self.add_sub_exact(&mut other, true) {
470            Some(self)
471        } else {
472            None
473        }
474    }
475
476    /// Computes `self * other`, returning `None` if rounding occurred.
477    pub fn mul_exact(mut self, mut other: URational) -> Option<URational> {
478        if self.mul_div_exact(&mut other, false) {
479            Some(self)
480        } else {
481            None
482        }
483    }
484
485    /// Computes `self / other`, returning `None` if rounding occurred.
486    pub fn div_exact(mut self, mut other: URational) -> Option<URational> {
487        if self.mul_div_exact(&mut other, true) {
488            Some(self)
489        } else {
490            None
491        }
492    }
493
494    /// Computes `self % other`, returning `None` if rounding occurred.
495    pub fn rem_exact(mut self, mut other: URational) -> Option<URational> {
496        if self.rem_div_exact(&mut other) {
497            Some(self)
498        } else {
499            None
500        }
501    }
502
503    fn simplify(&mut self) {
504        let common = gcd(self.numerator, self.denominator);
505        if common > 1 {
506            self.numerator /= common;
507            self.denominator /= common;
508        }
509    }
510
511    fn shift_partial(a: &mut u64) {
512        if *a & 0b11 == 0b11 {
513            *a >>= 1;
514            *a += 1;
515        } else {
516            *a >>= 1;
517        }
518    }
519
520    fn shift(&mut self) {
521        URational::shift_partial(&mut self.numerator);
522        URational::shift_partial(&mut self.denominator);
523        self.simplify();
524    }
525
526    fn add_sub_exact(&mut self, other: &mut URational, sub: bool) -> bool {
527        if sub && other > self && !other.is_infinity() {
528            *self = URational::zero();
529            return true;
530        } else if self.denominator == 0 && other.denominator == 0 {
531            *self = URational::nan();
532            return true;
533        } else if self.denominator == 0 {
534            return true;
535        } else if other.denominator == 0 {
536            *self = *other;
537            return true;
538        } else if self.denominator == other.denominator {
539            self.numerator = if sub {
540                try_or!(return false; self.numerator.checked_sub(other.numerator))
541            } else {
542                try_or!(return false; self.numerator.checked_add(other.numerator))
543            };
544            self.simplify();
545            return true;
546        }
547        let common = try_or!(return false; lcm(self.denominator, other.denominator));
548        let self_mul = common / self.denominator;
549        let other_mul = common / other.denominator;
550        let n0 = try_or!(return false; self.numerator.checked_mul(self_mul));
551        let n1 = try_or!(return false; other.numerator.checked_mul(other_mul));
552        self.numerator = if sub {
553            try_or!(return false; n0.checked_sub(n1))
554        } else {
555            try_or!(return false; n0.checked_add(n1))
556        };
557        self.denominator = common;
558        self.simplify();
559        true
560    }
561
562    fn mul_div_exact(&mut self, other: &mut URational, div: bool) -> bool {
563        if div {
564            *other = other.reciprocal();
565        }
566        if self.is_nan() {
567            return true;
568        } else if other.is_nan() || (self.is_infinity() && other.is_zero()) || (self.is_zero() && other.is_infinity()) {
569            *self = URational::nan();
570            return true;
571        } else if !self.is_signed() {
572            return true;
573        } else if !other.is_signed() {
574            *self = *other;
575            return true;
576        }
577        let ndc = gcd(self.numerator, other.denominator);
578        self.numerator /= ndc;
579        other.denominator /= ndc;
580        let dnc = gcd(self.denominator, other.numerator);
581        self.denominator /= dnc;
582        other.numerator /= dnc;
583        let n = try_or!(return false; self.numerator.checked_mul(other.numerator));
584        self.denominator = try_or!(return false; self.denominator.checked_mul(other.denominator));
585        self.numerator = n;
586        true
587    }
588
589    fn rem_div_exact(&mut self, other: &mut URational) -> bool {
590        if self.is_nan() {
591            return true;
592        } else if other.is_nan() {
593            *self = URational::nan();
594            return true;
595        } else if other.is_zero() || self.is_infinity() {
596            *self = URational::zero();
597            return true;
598        } else if other.is_infinity() {
599            return true;
600        }
601        if self.denominator == other.denominator {
602            self.numerator = try_or!(return false; self.numerator.checked_rem(other.numerator));
603            self.simplify();
604            return true;
605        }
606        let common = try_or!(return false; lcm(self.denominator, other.denominator));
607        let self_mul = common / self.denominator;
608        let other_mul = common / other.denominator;
609        let n0 = try_or!(return false; self.numerator.checked_mul(self_mul));
610        let n1 = try_or!(return false; other.numerator.checked_mul(other_mul));
611        self.numerator = try_or!(return false; n0.checked_rem(n1));
612        self.denominator = common;
613        self.simplify();
614        true
615    }
616
617    fn add_sub(&mut self, other: &mut URational, sub: bool) {
618        let mut first = true;
619        loop {
620            if first {
621                first = false;
622            } else if self >= other {
623                self.shift();
624            } else {
625                other.shift();
626            }
627            if URational::add_sub_exact(self, other, sub) {
628                return;
629            }
630        }
631    }
632
633    fn mul_div(&mut self, other: &mut URational, div: bool) {
634        let mut first = true;
635        loop {
636            if first {
637                first = false;
638            } else if self >= other {
639                self.shift();
640            } else {
641                other.shift();
642            }
643            if URational::mul_div_exact(self, other, div) {
644                return;
645            }
646        }
647    }
648
649    fn rem_div(&mut self, other: &mut URational) {
650        let mut first = true;
651        loop {
652            if first {
653                first = false;
654            } else if self >= other {
655                self.shift();
656            } else {
657                other.shift();
658            }
659            if URational::rem_div_exact(self, other) {
660                return;
661            }
662        }
663    }
664}
665
666impl Default for URational {
667    fn default() -> URational {
668        URational::zero()
669    }
670}
671
672impl PartialEq for URational {
673    fn eq(&self, other: &URational) -> bool {
674        self.numerator == other.numerator && self.denominator == other.denominator && (self.numerator != 0 || self.denominator != 0) && (other.numerator != 0 || other.denominator != 0)
675    }
676}
677
678impl PartialOrd for URational {
679    fn partial_cmp(&self, other: &URational) -> Option<Ordering> {
680        if self.eq(other) {
681            Some(Ordering::Equal)
682        } else if (self.numerator == 0 && self.denominator == 0) || (other.numerator == 0 && other.denominator == 0) {
683            None
684        } else {
685            let mut a = *self;
686            let mut b = *other;
687            let mut first = true;
688            loop {
689                if first {
690                    first = false;
691                } else {
692                    a.shift();
693                    b.shift();
694                }
695                let nd = try_or!(continue a.numerator.checked_mul(b.denominator));
696                let dn = try_or!(continue a.denominator.checked_mul(b.numerator));
697                if nd > dn {
698                    return Some(Ordering::Greater)
699                } else {
700                    return Some(Ordering::Less)
701                }
702            }
703        }
704    }
705}
706
707impl fmt::Display for URational {
708    /// Formats the rational.
709    ///
710    /// # Style
711    ///
712    /// * `NaN`, `∞`, and whole numbers are written directly
713    /// * Ratios with complexities less than 100 are written as fractions (`n/d`)
714    /// * All other numbers are written as decimals
715    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
716        if self.denominator == 1 {
717            write!(f, "{}", self.numerator)
718        } else if self.denominator == 0 {
719            if self.numerator == 0 {
720                write!(f, "NaN")
721            } else {
722                write!(f, "∞")
723            }
724        } else if self.complexity() < 100 {
725            write!(f, "{}/{}", self.numerator, self.denominator)
726        } else {
727            write!(f, "{}", self.numerator as f64 / self.denominator as f64)
728        }
729    }
730}
731
732impl fmt::Debug for URational {
733    /// Formats the rational.
734    ///
735    /// # Style
736    ///
737    /// All numbers are written as fractions in parentheses `(n/d)`
738    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
739        write!(f, "({}/{})", self.numerator, self.denominator)
740    }
741}
742
743/// A type representing a signed projectively-extended rational number
744///
745/// # Examples
746///
747/// ```
748/// use extended_rational::Rational;
749///
750/// let a = Rational::new(3, 17);
751/// let b = Rational::new(-4, 7);
752///
753/// assert_eq!(a+b, Rational::new(-47, 119));
754/// ```
755///
756/// Use the [ratio!](macro.ratio.html) macro for more convenient use.
757///
758/// ```
759/// # #[macro_use]
760/// # extern crate extended_rational;
761/// # #[allow(unused_variables)]
762/// # fn main() {
763/// let a = ratio!(3, 17);
764/// let b = ratio!(-4, 7);
765/// # }
766/// ```
767///
768/// Or for easy conversions from primitive types.
769///
770/// ```
771/// # #[macro_use]
772/// # extern crate extended_rational;
773/// # #[allow(unused_variables)]
774/// # fn main() {
775/// let a = ratio!(-77.332);
776/// let b = ratio!(2u8);
777/// # }
778/// ```
779#[derive(Copy, Clone)]
780#[cfg_attr(feature="bit_manager_enabled", derive(BitStore))]
781pub struct Rational {
782    unsigned: URational,
783    negative: bool,
784}
785
786impl Rational {
787    /// Create a new signed rational with the given numerator and denominator.
788    pub fn new(numerator: i64, denominator: i64) -> Rational {
789        let take_sign = |signed: i64| {
790            (
791                if signed == i64::MIN {
792                    i64::MAX as u64 + 1
793                } else {
794                    signed.abs() as u64
795                },
796                signed < 0,
797            )
798        };
799        let (n, sn) = take_sign(numerator);
800        let (d, sd) = take_sign(denominator);
801        Rational::new_raw(URational::new(n, d), sn != sd)
802    }
803
804    /// Create a new signed rational with the given unsigned rational and sign.
805    pub fn new_raw(unsigned: URational, negative: bool) -> Rational {
806        Rational {
807            unsigned,
808            negative: if unsigned.is_signed() {
809                negative
810            } else {
811                false
812            },
813        }
814    }
815
816    /// Returns the underlying numerator of this rational.
817    #[inline(always)] pub fn numerator(self) -> u64 { self.unsigned.numerator }
818
819    /// Returns the underlying numerator of this rational mutably.
820    #[inline(always)] pub fn numerator_mut(&mut self) -> &mut u64 { &mut self.unsigned.numerator }
821
822    /// Returns the underlying denominator of this rational.
823    #[inline(always)] pub fn denominator(self) -> u64 { self.unsigned.denominator }
824
825    /// Returns the underlying denominator of this rational mutably.
826    #[inline(always)] pub fn denominator_mut(&mut self) -> &mut u64 { &mut self.unsigned.denominator }
827
828    /// Returns the underlying sign of this rational.
829    #[inline(always)] pub fn sign(self) -> bool { self.negative }
830
831    /// Returns the underlying sign of this rational mutably.
832    #[inline(always)] pub fn sign_mut(&mut self) -> &mut bool { &mut self.negative }
833
834    /// Returns the underlying unsigned rational of this rational.
835    #[inline(always)] pub fn unsigned(self) -> URational { self.unsigned }
836
837    /// Returns the underlying unsigned rational of this rational mutably.
838    #[inline(always)] pub fn unsigned_mut(&mut self) -> &mut URational { &mut self.unsigned }
839
840    /// Returns the underlying unsigned rational of this rational, panicking if sign is negative.
841    ///
842    /// *Does not panic in optimized builds.*
843    #[inline]
844    pub fn try_unsigned(self) -> URational {
845        debug_assert!(!self.negative, "cannot create a URational with a negative sign.");
846        self.unsigned
847    }
848
849    /// Returns the smallest value a signed rational can store.
850    #[inline(always)] pub fn min_value() -> Rational { Rational { unsigned: URational { numerator: u64::MAX, denominator: 1 }, negative: true } }
851
852    /// Returns the smallest positive value a signed rational can store.
853    #[inline(always)] pub fn min_pos_value() -> Rational { Rational { unsigned: URational { numerator: 1, denominator: u64::MAX }, negative: false } }
854
855    /// Returns the largest negative value a signed rational can store.
856    #[inline(always)] pub fn max_neg_value() -> Rational { Rational { unsigned: URational { numerator: 1, denominator: u64::MAX }, negative: true } }
857
858    /// Returns the largest value a signed rational can store.
859    #[inline(always)] pub fn max_value() -> Rational { Rational { unsigned: URational { numerator: u64::MAX, denominator: 1 }, negative: false } }
860
861    /// Returns a signed rational representing `NaN`.
862    #[inline(always)] pub fn nan() -> Rational { Rational { unsigned: URational { numerator: 0, denominator: 0 }, negative: false } }
863
864    /// Returns a signed rational representing `0`.
865    #[inline(always)] pub fn zero() -> Rational { Rational { unsigned: URational { numerator: 0, denominator: 1 }, negative: false } }
866
867    /// Returns a signed rational representing `∞`.
868    #[inline(always)] pub fn infinity() -> Rational { Rational { unsigned: URational { numerator: 1, denominator: 0 }, negative: false } }
869
870    /// Returns a signed rational representing `1`.
871    #[inline(always)] pub fn one() -> Rational { Rational { unsigned: URational { numerator: 1, denominator: 1 }, negative: false } }
872
873    /// Returns a signed rational representing `-1`.
874    #[inline(always)] pub fn negative_one() -> Rational { Rational { unsigned: URational { numerator: 1, denominator: 1 }, negative: true } }
875
876    /// Returns `true` if this rational is `NaN` and `false` otherwise.
877    #[inline(always)] pub fn is_nan(self) -> bool { self.unsigned.is_nan() }
878
879    /// Returns `true` if this rational is `0` and `false` otherwise.
880    #[inline(always)] pub fn is_zero(self) -> bool { self.unsigned.is_zero() }
881
882    /// Returns `true` if this rational is `∞` and `false` otherwise.
883    #[inline(always)] pub fn is_infinity(self) -> bool { self.unsigned.is_infinity() }
884
885    /// Returns `true` if this rational is a signed number (not `NaN`, `0`, or `∞`) and `false` otherwise.
886    #[inline(always)] pub fn is_signed(self) -> bool { self.unsigned.is_signed() }
887
888    /// Returns `true` if this rational is a negative number and `false` otherwise.
889    #[inline(always)] pub fn is_negative(self) -> bool { self.negative }
890
891    /// Returns the reciprocal of this rational.
892    #[inline] pub fn reciprocal(self) -> Rational { Rational { unsigned: self.unsigned.reciprocal(), negative: self.negative } }
893
894    /// Returns the negative reciprocal of this rational.
895    #[inline] pub fn negative_reciprocal(self) -> Rational { Rational::new_raw( self.unsigned.reciprocal(), !self.negative) }
896
897    /// Returns the complexity of this rational (max of absolute values of numerator and denominator).
898    #[inline(always)] pub fn complexity(self) -> u64 { self.unsigned.complexity() }
899
900    /// Returns `true` if this rational is a positive number and `false` otherwise.
901    #[inline] pub fn is_positive(self) -> bool { self.unsigned.is_signed() && !self.negative }
902
903    /// Returns this rational with no fractional component by rounding towards zero.
904    #[inline]
905    pub fn floor(self) -> Rational {
906        Rational {
907            unsigned: self.unsigned.floor(),
908            negative: self.negative,
909        }
910    }
911
912    /// Returns this rational with no fractional component by rounding.
913    #[inline]
914    pub fn round(self) -> Rational {
915        Rational {
916            unsigned: self.unsigned.round(),
917            negative: self.negative,
918        }
919    }
920
921    /// Returns this rational with no fractional component by rounding away from zero.
922    #[inline]
923    pub fn ceil(self) -> Rational {
924        Rational {
925            unsigned: self.unsigned.ceil(),
926            negative: self.negative,
927        }
928    }
929
930    /// Returns this rational without a negative sign.
931    #[inline]
932    pub fn abs(self) -> Rational {
933        Rational {
934            unsigned: self.unsigned,
935            negative: false,
936        }
937    }
938
939    /// Computes `self + other`, returning `None` if rounding occurred.
940    pub fn add_exact(mut self, mut other: Rational) -> Option<Rational> {
941        if self.add_sub_exact(&mut other, false) {
942            Some(self)
943        } else {
944            None
945        }
946    }
947
948    /// Computes `self - other`, returning `None` if rounding occurred.
949    pub fn sub_exact(mut self, mut other: Rational) -> Option<Rational> {
950        if self.add_sub_exact(&mut other, true) {
951            Some(self)
952        } else {
953            None
954        }
955    }
956
957    /// Computes `self * other`, returning `None` if rounding occurred.
958    pub fn mul_exact(mut self, mut other: Rational) -> Option<Rational> {
959        if self.mul_div_exact(&mut other, false) {
960            Some(self)
961        } else {
962            None
963        }
964    }
965
966    /// Computes `self / other`, returning `None` if rounding occurred.
967    pub fn div_exact(mut self, mut other: Rational) -> Option<Rational> {
968        if self.mul_div_exact(&mut other, true) {
969            Some(self)
970        } else {
971            None
972        }
973    }
974
975    /// Computes `self % other`, returning `None` if rounding occurred.
976    pub fn rem_exact(mut self, mut other: Rational) -> Option<Rational> {
977        if self.rem_div_exact(&mut other) {
978            Some(self)
979        } else {
980            None
981        }
982    }
983
984    fn check_sign(&mut self) {
985        if !self.unsigned.is_signed() {
986            self.negative = false;
987        }
988    }
989
990    fn add_sub_exact(&mut self, other: &mut Rational, sub: bool) -> bool {
991        let negative = other.negative != sub;
992        if self.negative != negative {
993            if self.unsigned >= other.unsigned {
994                if !self.unsigned.add_sub_exact(&mut other.unsigned, true) {
995                    return false;
996                }
997            } else {
998                self.negative = negative;
999                if !other.unsigned.add_sub_exact(&mut self.unsigned, true) {
1000                    return false;
1001                }
1002                self.unsigned = other.unsigned;
1003            };
1004        } else {
1005            if !self.unsigned.add_sub_exact(&mut other.unsigned, false) {
1006                return false;
1007            }
1008        }
1009        self.check_sign();
1010        true
1011    }
1012
1013    fn mul_div_exact(&mut self, other: &mut Rational, div: bool) -> bool {
1014        self.negative = self.negative != other.negative;
1015        if self.unsigned.mul_div_exact(&mut other.unsigned, div) {
1016            self.check_sign();
1017            true
1018        } else {
1019            false
1020        }
1021    }
1022
1023    fn rem_div_exact(&mut self, other: &mut Rational) -> bool {
1024        if self.unsigned.rem_div_exact(&mut other.unsigned) {
1025            self.check_sign();
1026            true
1027        } else {
1028            false
1029        }
1030    }
1031
1032    fn add_sub(&mut self, other: &mut Rational, sub: bool) {
1033        let negative = other.negative != sub;
1034        if self.negative != negative {
1035            if self.unsigned >= other.unsigned {
1036                self.unsigned.add_sub(&mut other.unsigned, true);
1037            } else {
1038                self.negative = negative;
1039                other.unsigned.add_sub(&mut self.unsigned, true);
1040                self.unsigned = other.unsigned;
1041            };
1042        } else {
1043            self.unsigned.add_sub(&mut other.unsigned, false);
1044        }
1045        self.check_sign();
1046    }
1047
1048    fn mul_div(&mut self, other: &mut Rational, div: bool) {
1049        self.negative = self.negative != other.negative;
1050        self.unsigned.mul_div(&mut other.unsigned, div);
1051        self.check_sign();
1052    }
1053
1054    fn rem_div(&mut self, other: &mut Rational) {
1055        self.unsigned.rem_div(&mut other.unsigned);
1056        self.check_sign();
1057    }
1058}
1059
1060impl Default for Rational {
1061    fn default() -> Rational {
1062        Rational::zero()
1063    }
1064}
1065
1066impl PartialEq for Rational {
1067    fn eq(&self, other: &Rational) -> bool {
1068        self.unsigned == other.unsigned && (self.negative == other.negative || !(self.is_signed() || other.is_signed()))
1069    }
1070}
1071
1072impl PartialOrd for Rational {
1073    fn partial_cmp(&self, other: &Rational) -> Option<Ordering> {
1074        if self.eq(other) {
1075            Some(Ordering::Equal)
1076        } else if self.is_infinity() || other.is_infinity() {
1077            None
1078        } else if let Some(ordering) = self.unsigned.partial_cmp(&other.unsigned) {
1079            if self.negative != other.negative {
1080                if self.negative {
1081                    Some(Ordering::Less)
1082                } else {
1083                    Some(Ordering::Greater)
1084                }
1085            } else if self.negative {
1086                if ordering == Ordering::Greater {
1087                    Some(Ordering::Less)
1088                } else {
1089                    Some(Ordering::Greater)
1090                }
1091            } else {
1092                Some(ordering)
1093            }
1094        } else {
1095            None
1096        }
1097    }
1098}
1099
1100impl fmt::Display for Rational {
1101    /// Formats the rational.
1102    ///
1103    /// # Style
1104    ///
1105    /// * `NaN`, `∞`, and whole numbers are written directly
1106    /// * Ratios with complexities less than 100 are written as fractions (`n/d`)
1107    /// * All other numbers are written as decimals
1108    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
1109        if self.negative {
1110            write!(f, "-{}", self.unsigned)
1111        } else {
1112            write!(f, "{}", self.unsigned)
1113        }
1114    }
1115}
1116
1117impl fmt::Debug for Rational {
1118    /// Formats the rational.
1119    ///
1120    /// # Style
1121    ///
1122    /// All numbers are written as fractions in parentheses `(n/d)`
1123    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
1124        if self.negative {
1125            write!(f, "(-{}/{})", self.unsigned.numerator, self.unsigned.denominator)
1126        } else {
1127            write!(f, "({}/{})", self.unsigned.numerator, self.unsigned.denominator)
1128        }
1129    }
1130}
1131
1132impl_ops!(AddAssign Add, add_assign add, add_sub false);
1133impl_ops!(SubAssign Sub, sub_assign sub, add_sub true);
1134impl_ops!(MulAssign Mul, mul_assign mul, mul_div false);
1135impl_ops!(DivAssign Div, div_assign div, mul_div true);
1136impl_ops!(RemAssign Rem, rem_assign rem, rem_div);
1137
1138impl Neg for Rational {
1139    type Output = Rational;
1140
1141    fn neg(self) -> Rational {
1142        Rational {
1143            unsigned: self.unsigned,
1144            negative: !self.negative,
1145        }
1146    }
1147}
1148
1149impl From<URational> for Rational {
1150    /// Create a new signed rational from an unsigned rational.
1151    fn from(r: URational) -> Rational {
1152        Rational::new_raw(r, false)
1153    }
1154}
1155
1156impl From<(URational, bool)> for Rational {
1157    /// Create a new signed rational from an unsigned rational and a sign.
1158    fn from(tuple: (URational, bool)) -> Rational {
1159        let (unsigned, negative) = tuple;
1160        Rational::new_raw(unsigned, negative)
1161    }
1162}
1163
1164impl_float!(f64 [64, 52] f32 [32, 23]);
1165
1166impl_u_from!(u64 u32 u16 u8);
1167
1168impl_from!(i64 i32 i16 i8);