algebraeon_nzq/rational/
mod.rs1use 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}