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