algebraeon_nzq/rational/
mod.rs

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