algebraeon_nzq/rational/
mod.rs

1use crate::integer::*;
2use crate::natural::*;
3use crate::traits::*;
4use algebraeon_sets::structure::*;
5use malachite_base::num::basic::traits::{One, OneHalf, Two, Zero};
6use malachite_q::arithmetic::traits::{Approximate, SimplestRationalInInterval};
7use std::{
8    ops::{Add, AddAssign, Div, Mul, MulAssign, Neg, Sub, SubAssign},
9    str::FromStr,
10};
11
12#[derive(Default, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
13pub struct Rational(malachite_q::Rational);
14
15impl Rational {
16    pub(crate) fn from_malachite(value: malachite_q::Rational) -> Self {
17        Self(value)
18    }
19    pub(crate) fn to_malachite(self) -> malachite_q::Rational {
20        self.0
21    }
22    pub(crate) fn to_malachite_ref(&self) -> &malachite_q::Rational {
23        &self.0
24    }
25}
26
27impl std::fmt::Display for Rational {
28    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
29        self.0.fmt(f)
30    }
31}
32
33impl From<u8> for Rational {
34    fn from(value: u8) -> Self {
35        Self(malachite_q::Rational::from(value))
36    }
37}
38impl From<u16> for Rational {
39    fn from(value: u16) -> Self {
40        Self(malachite_q::Rational::from(value))
41    }
42}
43impl From<u32> for Rational {
44    fn from(value: u32) -> Self {
45        Self(malachite_q::Rational::from(value))
46    }
47}
48impl From<u64> for Rational {
49    fn from(value: u64) -> Self {
50        Self(malachite_q::Rational::from(value))
51    }
52}
53impl From<u128> for Rational {
54    fn from(value: u128) -> Self {
55        Self(malachite_q::Rational::from(value))
56    }
57}
58impl From<usize> for Rational {
59    fn from(value: usize) -> Self {
60        Self(malachite_q::Rational::from(value))
61    }
62}
63impl From<i8> for Rational {
64    fn from(value: i8) -> Self {
65        Self(malachite_q::Rational::from(value))
66    }
67}
68impl From<i16> for Rational {
69    fn from(value: i16) -> Self {
70        Self(malachite_q::Rational::from(value))
71    }
72}
73impl From<i32> for Rational {
74    fn from(value: i32) -> Self {
75        Self(malachite_q::Rational::from(value))
76    }
77}
78impl From<i64> for Rational {
79    fn from(value: i64) -> Self {
80        Self(malachite_q::Rational::from(value))
81    }
82}
83impl From<i128> for Rational {
84    fn from(value: i128) -> Self {
85        Self(malachite_q::Rational::from(value))
86    }
87}
88impl From<isize> for Rational {
89    fn from(value: isize) -> Self {
90        Self(malachite_q::Rational::from(value))
91    }
92}
93impl From<Natural> for Rational {
94    fn from(value: Natural) -> Self {
95        Self(malachite_q::Rational::from(value.to_malachite()))
96    }
97}
98impl From<&Natural> for Rational {
99    fn from(value: &Natural) -> Self {
100        Self(malachite_q::Rational::from(value.to_malachite_ref()))
101    }
102}
103impl From<Integer> for Rational {
104    fn from(value: Integer) -> Self {
105        Self(malachite_q::Rational::from(value.to_malachite()))
106    }
107}
108impl From<&Integer> for Rational {
109    fn from(value: &Integer) -> Self {
110        Self(malachite_q::Rational::from(value.to_malachite_ref()))
111    }
112}
113
114impl FromStr for Rational {
115    type Err = ();
116
117    fn from_str(s: &str) -> Result<Self, Self::Err> {
118        Ok(Self(malachite_q::Rational::from_str(s)?))
119    }
120}
121
122impl Rational {
123    pub const ZERO: Self = Self(malachite_q::Rational::ZERO);
124    pub const ONE: Self = Self(malachite_q::Rational::ONE);
125    pub const TWO: Self = Self(malachite_q::Rational::TWO);
126    pub const ONE_HALF: Self = Self(malachite_q::Rational::ONE_HALF);
127}
128
129impl PartialEq<Natural> for Rational {
130    fn eq(&self, other: &Natural) -> bool {
131        self.0.eq(other.to_malachite_ref())
132    }
133}
134impl PartialEq<&Natural> for Rational {
135    fn eq(&self, other: &&Natural) -> bool {
136        self.eq(*other)
137    }
138}
139impl PartialOrd<Natural> for Rational {
140    fn partial_cmp(&self, other: &Natural) -> Option<std::cmp::Ordering> {
141        self.0.partial_cmp(other.to_malachite_ref())
142    }
143}
144impl PartialOrd<&Natural> for Rational {
145    fn partial_cmp(&self, other: &&Natural) -> Option<std::cmp::Ordering> {
146        self.partial_cmp(*other)
147    }
148}
149
150impl PartialEq<Integer> for Rational {
151    fn eq(&self, other: &Integer) -> bool {
152        self.0.eq(other.to_malachite_ref())
153    }
154}
155impl PartialEq<&Integer> for Rational {
156    fn eq(&self, other: &&Integer) -> bool {
157        self.eq(*other)
158    }
159}
160impl PartialOrd<Integer> for Rational {
161    fn partial_cmp(&self, other: &Integer) -> Option<std::cmp::Ordering> {
162        self.0.partial_cmp(other.to_malachite_ref())
163    }
164}
165impl PartialOrd<&Integer> for Rational {
166    fn partial_cmp(&self, other: &&Integer) -> Option<std::cmp::Ordering> {
167        self.partial_cmp(*other)
168    }
169}
170
171impl AddAssign<Rational> for Rational {
172    fn add_assign(&mut self, rhs: Rational) {
173        self.0.add_assign(rhs.0)
174    }
175}
176impl AddAssign<&Rational> for Rational {
177    fn add_assign(&mut self, rhs: &Rational) {
178        self.0.add_assign(&rhs.0)
179    }
180}
181
182impl SubAssign<Rational> for Rational {
183    fn sub_assign(&mut self, rhs: Rational) {
184        self.0.sub_assign(rhs.0)
185    }
186}
187impl SubAssign<&Rational> for Rational {
188    fn sub_assign(&mut self, rhs: &Rational) {
189        self.0.sub_assign(&rhs.0)
190    }
191}
192
193impl MulAssign<Rational> for Rational {
194    fn mul_assign(&mut self, rhs: Rational) {
195        self.0.mul_assign(rhs.0)
196    }
197}
198impl MulAssign<&Rational> for Rational {
199    fn mul_assign(&mut self, rhs: &Rational) {
200        self.0.mul_assign(&rhs.0)
201    }
202}
203
204impl Neg for Rational {
205    type Output = Rational;
206
207    fn neg(self) -> Self::Output {
208        Rational(self.0.neg())
209    }
210}
211impl Neg for &Rational {
212    type Output = Rational;
213
214    fn neg(self) -> Self::Output {
215        Rational((&self.0).neg())
216    }
217}
218
219impl Add<Rational> for Rational {
220    type Output = Rational;
221
222    fn add(self, rhs: Rational) -> Self::Output {
223        Rational(self.0.add(rhs.0))
224    }
225}
226impl Add<&Rational> for Rational {
227    type Output = Rational;
228
229    fn add(self, rhs: &Rational) -> Self::Output {
230        Rational(self.0.add(&rhs.0))
231    }
232}
233impl Add<Rational> for &Rational {
234    type Output = Rational;
235
236    fn add(self, rhs: Rational) -> Self::Output {
237        Rational((&self.0).add(rhs.0))
238    }
239}
240impl Add<&Rational> for &Rational {
241    type Output = Rational;
242
243    fn add(self, rhs: &Rational) -> Self::Output {
244        Rational((&self.0).add(&rhs.0))
245    }
246}
247
248impl Sub<Rational> for Rational {
249    type Output = Rational;
250
251    fn sub(self, rhs: Rational) -> Self::Output {
252        Rational(self.0.sub(rhs.0))
253    }
254}
255impl Sub<&Rational> for Rational {
256    type Output = Rational;
257
258    fn sub(self, rhs: &Rational) -> Self::Output {
259        Rational(self.0.sub(&rhs.0))
260    }
261}
262impl Sub<Rational> for &Rational {
263    type Output = Rational;
264
265    fn sub(self, rhs: Rational) -> Self::Output {
266        Rational((&self.0).sub(rhs.0))
267    }
268}
269impl Sub<&Rational> for &Rational {
270    type Output = Rational;
271
272    fn sub(self, rhs: &Rational) -> Self::Output {
273        Rational((&self.0).sub(&rhs.0))
274    }
275}
276
277impl Mul<Rational> for Rational {
278    type Output = Rational;
279
280    fn mul(self, rhs: Rational) -> Self::Output {
281        Rational(self.0.mul(rhs.0))
282    }
283}
284impl Mul<&Rational> for Rational {
285    type Output = Rational;
286
287    fn mul(self, rhs: &Rational) -> Self::Output {
288        Rational(self.0.mul(&rhs.0))
289    }
290}
291impl Mul<Rational> for &Rational {
292    type Output = Rational;
293
294    fn mul(self, rhs: Rational) -> Self::Output {
295        Rational((&self.0).mul(rhs.0))
296    }
297}
298impl Mul<&Rational> for &Rational {
299    type Output = Rational;
300
301    fn mul(self, rhs: &Rational) -> Self::Output {
302        Rational((&self.0).mul(&rhs.0))
303    }
304}
305
306impl Div<Rational> for Rational {
307    type Output = Rational;
308
309    fn div(self, rhs: Rational) -> Self::Output {
310        Rational(self.0.div(rhs.0))
311    }
312}
313impl Div<&Rational> for Rational {
314    type Output = Rational;
315
316    fn div(self, rhs: &Rational) -> Self::Output {
317        Rational(self.0.div(&rhs.0))
318    }
319}
320impl Div<Rational> for &Rational {
321    type Output = Rational;
322
323    fn div(self, rhs: Rational) -> Self::Output {
324        Rational((&self.0).div(rhs.0))
325    }
326}
327impl Div<&Rational> for &Rational {
328    type Output = Rational;
329
330    fn div(self, rhs: &Rational) -> Self::Output {
331        Rational((&self.0).div(&rhs.0))
332    }
333}
334
335impl Abs for Rational {
336    type Output = Rational;
337
338    fn abs(self) -> Self::Output {
339        use malachite_base::num::arithmetic::traits::Abs;
340        Rational(self.0.abs())
341    }
342}
343
344impl Abs for &Rational {
345    type Output = Rational;
346
347    fn abs(self) -> Self::Output {
348        use malachite_base::num::arithmetic::traits::Abs;
349        Rational((&self.0).abs())
350    }
351}
352
353impl Fraction for Rational {
354    type NumeratorOutput = Integer;
355    type DenominatorOutput = Natural;
356
357    fn numerator(self) -> Self::NumeratorOutput {
358        (&self).numerator()
359    }
360    fn denominator(self) -> Self::DenominatorOutput {
361        (&self).denominator()
362    }
363}
364
365impl Fraction for &Rational {
366    type NumeratorOutput = Integer;
367    type DenominatorOutput = Natural;
368
369    fn numerator(self) -> Self::NumeratorOutput {
370        if self >= &Rational::ZERO {
371            Integer::from(Natural::from_malachite(self.0.numerator_ref().clone()))
372        } else {
373            -Natural::from_malachite(self.0.numerator_ref().clone())
374        }
375    }
376    fn denominator(self) -> Self::DenominatorOutput {
377        Natural::from_malachite(self.0.denominator_ref().clone())
378    }
379}
380
381impl Floor for Rational {
382    type Output = Integer;
383
384    fn floor(self) -> Self::Output {
385        use malachite_base::num::arithmetic::traits::Floor;
386        Integer::from_malachite(self.0.floor())
387    }
388}
389
390impl Floor for &Rational {
391    type Output = Integer;
392
393    fn floor(self) -> Self::Output {
394        use malachite_base::num::arithmetic::traits::Floor;
395        Integer::from_malachite((&self.0).floor())
396    }
397}
398
399impl Ceil for Rational {
400    type Output = Integer;
401
402    fn ceil(self) -> Self::Output {
403        use malachite_base::num::arithmetic::traits::Ceiling;
404        Integer::from_malachite(self.0.ceiling())
405    }
406}
407
408impl Ceil for &Rational {
409    type Output = Integer;
410
411    fn ceil(self) -> Self::Output {
412        use malachite_base::num::arithmetic::traits::Ceiling;
413        Integer::from_malachite((&self.0).ceiling())
414    }
415}
416
417impl Rational {
418    pub fn from_integers(n: impl Into<Integer>, d: impl Into<Integer>) -> Self {
419        Self(malachite_q::Rational::from_integers(
420            n.into().to_malachite(),
421            d.into().to_malachite(),
422        ))
423    }
424
425    pub fn into_abs_numerator_and_denominator(self) -> (Natural, Natural) {
426        let (n, d) = self.0.into_numerator_and_denominator();
427        (Natural::from_malachite(n), Natural::from_malachite(d))
428    }
429
430    pub fn simplest_rational_in_closed_interval(a: &Rational, b: &Rational) -> Self {
431        Self(malachite_q::Rational::simplest_rational_in_closed_interval(
432            &a.0, &b.0,
433        ))
434    }
435
436    pub fn simplest_rational_in_open_interval(a: &Rational, b: &Rational) -> Self {
437        Self(malachite_q::Rational::simplest_rational_in_open_interval(
438            &a.0, &b.0,
439        ))
440    }
441
442    pub fn exhaustive_rationals() -> impl Iterator<Item = Rational> {
443        malachite_q::exhaustive::exhaustive_rationals().map(|v| Rational(v))
444    }
445
446    pub fn approximate(self, max_denominator: &Natural) -> Self {
447        Self(self.0.approximate(max_denominator.to_malachite_ref()))
448    }
449
450    pub fn try_from_float_simplest(x: f64) -> Result<Self, ()> {
451        match malachite_q::Rational::try_from_float_simplest(x) {
452            Ok(x) => Ok(Self(x)),
453            Err(_) => Err(()),
454        }
455    }
456}
457
458impl MetaType for Rational {
459    type Structure = CannonicalStructure<Rational>;
460
461    fn structure() -> std::rc::Rc<Self::Structure> {
462        CannonicalStructure::new().into()
463    }
464}
465
466pub fn rat_to_string(a: Rational) -> String {
467    if a == Rational::ZERO {
468        return "0".into();
469    }
470    let neg = a < Rational::from(0);
471    let (mant, exp, _): (f64, _, _) = a
472        .to_malachite()
473        .sci_mantissa_and_exponent_round(malachite_base::rounding_modes::RoundingMode::Nearest)
474        .unwrap();
475    let mut b = (2.0 as f64).powf(exp as f64) * mant;
476    if neg {
477        b = -b;
478    }
479    b = (1000.0 * b).round() / 1000.0;
480    b.to_string()
481}