1use std::cmp::Ordering;
2use std::iter::Sum;
3use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Sub, SubAssign};
4use std::ops::Neg;
5
6use crate::Negateable;
7use crate::non_zero::NonZero;
8use crate::non_zero::NonZeroSign;
9use crate::rational::small::{Rational128, Rational16, Rational32, Rational64, Rational8, RationalUsize};
10use crate::rational::small::{NonZeroRational128, NonZeroRational16, NonZeroRational32, NonZeroRational64, NonZeroRational8, NonZeroRationalUsize};
11use crate::rational::small::ops::building_blocks::{add128, add16, add32, add64, add8, add_usize};
12use crate::rational::small::ops::building_blocks::{sub128, sub16, sub32, sub64, sub8, sub_usize};
13use crate::rational::small::ops::building_blocks::{mul128, mul16, mul32, mul64, mul8, mul_usize};
14use crate::rational::small::ops::building_blocks::SignChange;
15use crate::sign::Sign;
16
17pub(crate) mod building_blocks;
18mod with_int;
19mod with_one;
20mod with_zero;
21
22#[cfg(test)]
23mod test;
24
25macro_rules! rational {
26 ($name:ident, $add_name:ident, $sub_name:ident, $mul_name:ident) => {
27 impl AddAssign<&$name> for $name {
28 #[inline]
29 fn add_assign(&mut self, rhs: &Self) {
30 match (self.sign, rhs.sign) {
31 (Sign::Positive, Sign::Positive) | (Sign::Negative, Sign::Negative) => {
32 $add_name(
33 &mut self.numerator,
34 &mut self.denominator,
35 rhs.numerator,
36 rhs.denominator,
37 )
38 }
39 (Sign::Positive, Sign::Negative) | (Sign::Negative, Sign::Positive) => {
40 let sign_change = $sub_name(
41 &mut self.numerator,
42 &mut self.denominator,
43 rhs.numerator,
44 rhs.denominator,
45 );
46 match sign_change {
47 SignChange::None => {}
48 SignChange::Flip => self.sign.negate(),
49 SignChange::Zero => self.sign = Sign::Zero,
50 }
51 }
52 (_, Sign::Zero) => {},
53 (Sign::Zero, _) => {
54 *self = Self {
55 sign: rhs.sign,
56 numerator: rhs.numerator,
57 denominator: rhs.denominator,
58 };
59 },
60 }
61 }
62 }
63
64 impl SubAssign<&$name> for $name {
65 #[inline]
66 fn sub_assign(&mut self, rhs: &Self) {
67 match (self.sign, rhs.sign) {
68 (Sign::Positive, Sign::Positive) | (Sign::Negative, Sign::Negative) => {
69 let sign_change = $sub_name(
70 &mut self.numerator,
71 &mut self.denominator,
72 rhs.numerator,
73 rhs.denominator,
74 );
75 match sign_change {
76 SignChange::None => {}
77 SignChange::Flip => self.sign.negate(),
78 SignChange::Zero => self.sign = Sign::Zero,
79 }
80 }
81 (Sign::Positive, Sign::Negative) | (Sign::Negative, Sign::Positive) => {
82 $add_name(
83 &mut self.numerator,
84 &mut self.denominator,
85 rhs.numerator,
86 rhs.denominator,
87 )
88 }
89 (_, Sign::Zero) => {}
90 (Sign::Zero, _) => {
91 *self = Self {
92 sign: !rhs.sign,
93 numerator: rhs.numerator,
94 denominator: rhs.denominator,
95 };
96 }
97 }
98 }
99 }
100
101 impl Sum for $name {
102 fn sum<I: Iterator<Item=Self>>(mut iter: I) -> Self {
103 let first_value = iter.next();
104 match first_value {
105 None => <Self as num_traits::Zero>::zero(),
106 Some(mut total) => {
107
108 while let Some(next_value) = iter.next() {
109 total += next_value;
110 }
111
112 total
113 }
114 }
115 }
116 }
117
118 impl MulAssign<&$name> for $name {
119 #[inline]
120 fn mul_assign(&mut self, rhs: &Self) {
121 match (self.sign, rhs.sign) {
122 (Sign::Positive | Sign::Negative, Sign::Positive | Sign::Negative) => {
123 self.sign *= rhs.sign;
124 $mul_name(&mut self.numerator, &mut self.denominator, rhs.numerator, rhs.denominator);
125 }
126 (Sign::Zero, _) => {}
127 (_, Sign::Zero) => <Self as num_traits::Zero>::set_zero(self),
128 }
129 }
130 }
131
132 impl Div<$name> for &$name {
133 type Output = $name;
134
135 #[must_use]
136 #[inline]
137 fn div(self, mut rhs: $name) -> Self::Output {
138 match (self.sign, rhs.sign) {
139 (Sign::Positive | Sign::Negative, Sign::Positive | Sign::Negative) => {
140 let sign = self.sign * rhs.sign;
141 $mul_name(&mut rhs.numerator, &mut rhs.denominator, self.denominator, self.numerator);
142 Self::Output {
143 sign,
144 numerator: rhs.denominator,
145 denominator: rhs.numerator,
146 }
147 }
148 (_, Sign::Zero) => panic!(),
149 (Sign::Zero, _) => {
150 <$name as num_traits::Zero>::set_zero(&mut rhs);
151 rhs
152 }
153 }
154 }
155 }
156
157 impl DivAssign<&$name> for $name {
158 #[inline]
159 fn div_assign(&mut self, rhs: &Self) {
160 match (self.sign, rhs.sign) {
161 (Sign::Positive | Sign::Negative, Sign::Positive | Sign::Negative) => {
162 self.sign *= rhs.sign;
163 $mul_name(&mut self.numerator, &mut self.denominator, rhs.denominator, rhs.numerator);
164 }
165 (_, Sign::Zero) => panic!(),
166 (Sign::Zero, _) => {}
167 }
168 }
169 }
170 }
171}
172
173rational!(Rational8, add8, sub8, mul8);
174rational!(Rational16, add16, sub16, mul16);
175rational!(Rational32, add32, sub32, mul32);
176rational!(Rational64, add64, sub64, mul64);
177rational!(Rational128, add128, sub128, mul128);
178rational!(RationalUsize, add_usize, sub_usize, mul_usize);
179
180macro_rules! rational_non_zero {
181 ($name:ident, $add_name:ident, $sub_name:ident, $mul_name:ident) => {
182 impl AddAssign<&$name> for $name {
183 #[inline]
184 fn add_assign(&mut self, rhs: &Self) {
185 match (self.sign, rhs.sign) {
186 (NonZeroSign::Positive, NonZeroSign::Positive) | (NonZeroSign::Negative, NonZeroSign::Negative) => {
187 $add_name(
188 &mut self.numerator,
189 &mut self.denominator,
190 rhs.numerator,
191 rhs.denominator,
192 )
193 }
194 (NonZeroSign::Positive, NonZeroSign::Negative) | (NonZeroSign::Negative, NonZeroSign::Positive) => {
195 let sign_change = $sub_name(
196 &mut self.numerator,
197 &mut self.denominator,
198 rhs.numerator,
199 rhs.denominator,
200 );
201 match sign_change {
202 SignChange::None => {}
203 SignChange::Flip => self.sign.negate(),
204 SignChange::Zero => panic!("attempt to add with overflow"),
205 }
206 }
207 }
208 }
209 }
210 impl SubAssign<&$name> for $name {
211 #[inline]
212 fn sub_assign(&mut self, rhs: &Self) {
213 match (self.sign, rhs.sign) {
214 (NonZeroSign::Positive, NonZeroSign::Positive) | (NonZeroSign::Negative, NonZeroSign::Negative) => {
215 let sign_change = $sub_name(
216 &mut self.numerator,
217 &mut self.denominator,
218 rhs.numerator,
219 rhs.denominator,
220 );
221 match sign_change {
222 SignChange::None => {}
223 SignChange::Flip => self.sign.negate(),
224 SignChange::Zero => panic!("attempt to subtract with overflow"),
225 }
226 }
227 (NonZeroSign::Positive, NonZeroSign::Negative) | (NonZeroSign::Negative, NonZeroSign::Positive) => {
228 $add_name(
229 &mut self.numerator,
230 &mut self.denominator,
231 rhs.numerator,
232 rhs.denominator,
233 )
234 }
235 }
236 }
237 }
238 impl MulAssign<&$name> for $name {
239 #[inline]
240 fn mul_assign(&mut self, rhs: &Self) {
241 self.sign *= rhs.sign;
242 $mul_name(&mut self.numerator, &mut self.denominator, rhs.numerator, rhs.denominator);
243 }
244 }
245 impl Div<$name> for &$name {
246 type Output = $name;
247
248 #[must_use]
249 #[inline]
250 fn div(self, mut rhs: $name) -> Self::Output {
251 let sign = self.sign * rhs.sign;
252 $mul_name(&mut rhs.numerator, &mut rhs.denominator, self.denominator, self.numerator);
253 Self::Output {
254 sign,
255 numerator: rhs.denominator,
256 denominator: rhs.numerator,
257 }
258 }
259 }
260 impl DivAssign<&$name> for $name {
261 #[inline]
262 fn div_assign(&mut self, rhs: &Self) {
263 self.sign *= rhs.sign;
264 $mul_name(&mut self.numerator, &mut self.denominator, rhs.denominator, rhs.numerator);
265 }
266 }
267
268 impl Neg for $name {
269 type Output = Self;
270
271 #[must_use]
272 #[inline]
273 fn neg(mut self) -> Self::Output {
274 self.sign.negate();
275 self
276 }
277 }
278
279 impl Neg for &$name {
280 type Output = $name;
281
282 #[must_use]
283 #[inline]
284 fn neg(self) -> Self::Output {
285 Self::Output {
286 sign: !self.sign,
287 numerator: self.numerator,
288 denominator: self.denominator,
289 }
290 }
291 }
292 }
293}
294rational_non_zero!(NonZeroRational8, add8, sub8, mul8);
295rational_non_zero!(NonZeroRational16, add16, sub16, mul16);
296rational_non_zero!(NonZeroRational32, add32, sub32, mul32);
297rational_non_zero!(NonZeroRational64, add64, sub64, mul64);
298rational_non_zero!(NonZeroRational128, add128, sub128, mul128);
299rational_non_zero!(NonZeroRationalUsize, add_usize, sub_usize, mul_usize);
300
301macro_rules! rational_requiring_wide {
302 ($name:ident, $uty:ty, $BITS:literal, $wide:ty, $sign:ident) => {
303 impl Ord for $name {
304 #[must_use]
305 #[inline]
306 fn cmp(&self, other: &Self) -> Ordering {
307 self.partial_cmp(other).unwrap()
308 }
309 }
310
311 impl PartialOrd for $name {
312 #[must_use]
313 #[inline]
314 #[allow(unreachable_patterns)]
315 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
316 self.sign.partial_cmp(&other.sign).or_else(|| {
317 debug_assert_eq!(self.sign, other.sign);
318 debug_assert!(self.is_not_zero());
319
320 let widening_mul = |left, right| {
321 let wide = unsafe { (left as $wide).unchecked_mul(right as $wide) };
322 ((wide >> $BITS) as $uty, wide as $uty)
323 };
324
325 let ad = widening_mul(self.numerator, other.denominator);
326 let bc = widening_mul(self.denominator, other.numerator);
327
328 Some(match (ad.cmp(&bc), self.sign) {
329 (Ordering::Less, $sign::Positive) | (Ordering::Greater, $sign::Negative) => Ordering::Less,
330 (Ordering::Equal, _) => Ordering::Equal,
331 (Ordering::Greater, $sign::Positive) | (Ordering::Less, $sign::Negative) => Ordering::Greater,
332 _ => panic!("Zero case would have been equal or nonzero type"),
333 })
334 })
335 }
336 }
337 }
338}
339rational_requiring_wide!(Rational8, u8, 8, u16, Sign);
340rational_requiring_wide!(Rational16, u16, 16, u32, Sign);
341rational_requiring_wide!(Rational32, u32, 32, u64, Sign);
342rational_requiring_wide!(Rational64, u64, 64, u128, Sign);
343rational_requiring_wide!(NonZeroRational8, u8, 8, u16, NonZeroSign);
344rational_requiring_wide!(NonZeroRational16, u16, 16, u32, NonZeroSign);
345rational_requiring_wide!(NonZeroRational32, u32, 32, u64, NonZeroSign);
346rational_requiring_wide!(NonZeroRational64, u64, 64, u128, NonZeroSign);
347
348macro_rules! rational_forward {
349 ($name:ident) => {
350 impl<'a> Add<&'a $name> for &'a $name {
351 type Output = $name;
352
353 #[must_use]
354 #[inline]
355 fn add(self, rhs: Self) -> Self::Output {
356 Add::add(self.clone(), rhs)
357 }
358 }
359
360 impl Add for $name {
361 type Output = Self;
362
363 #[must_use]
364 #[inline]
365 fn add(mut self, rhs: Self) -> Self::Output {
366 AddAssign::add_assign(&mut self, rhs);
367 self
368 }
369 }
370
371 impl Add<&$name> for $name {
372 type Output = Self;
373
374 #[must_use]
375 #[inline]
376 fn add(mut self, rhs: &Self) -> Self::Output {
377 AddAssign::add_assign(&mut self, rhs);
378 self
379 }
380 }
381
382 impl Add<$name> for &$name {
383 type Output = $name;
384
385 #[must_use]
386 #[inline]
387 fn add(self, rhs: $name) -> Self::Output {
388 Add::add(rhs, self)
389 }
390 }
391
392 impl AddAssign for $name {
393 #[inline]
394 fn add_assign(&mut self, rhs: Self) {
395 AddAssign::add_assign(self, &rhs);
396 }
397 }
398
399 impl Sub for $name {
400 type Output = Self;
401
402 #[must_use]
403 #[inline]
404 fn sub(mut self, rhs: Self) -> Self::Output {
405 SubAssign::sub_assign(&mut self, rhs);
406 self
407 }
408 }
409
410 impl<'a> Sub<&'a $name> for &'a $name {
411 type Output = $name;
412
413 #[must_use]
414 #[inline]
415 fn sub(self, rhs: Self) -> Self::Output {
416 Sub::sub(self.clone(), rhs)
417 }
418 }
419
420 impl Sub<&$name> for $name {
421 type Output = Self;
422
423 #[must_use]
424 #[inline]
425 fn sub(mut self, rhs: &Self) -> Self::Output {
426 SubAssign::sub_assign(&mut self, rhs);
427 self
428 }
429 }
430
431 impl Sub<$name> for &$name {
432 type Output = $name;
433
434 #[must_use]
435 #[inline]
436 fn sub(self, rhs: $name) -> Self::Output {
437 -Sub::sub(rhs, self)
438 }
439 }
440
441 impl SubAssign for $name {
442 #[inline]
443 fn sub_assign(&mut self, rhs: Self) {
444 SubAssign::sub_assign(self, &rhs)
445 }
446 }
447
448 impl Mul<&$name> for $name {
449 type Output = Self;
450
451 #[must_use]
452 #[inline]
453 fn mul(mut self, rhs: &Self) -> Self::Output {
454 MulAssign::mul_assign(&mut self, rhs);
455 self
456 }
457 }
458
459 impl<'a> Mul<&'a $name> for &'a $name {
460 type Output = $name;
461
462 #[must_use]
463 #[inline]
464 fn mul(self, rhs: Self) -> Self::Output {
465 Mul::mul(self.clone(), rhs)
466 }
467 }
468
469 impl Mul for $name {
470 type Output = Self;
471
472 #[must_use]
473 #[inline]
474 fn mul(mut self, rhs: Self) -> Self::Output {
475 MulAssign::mul_assign(&mut self, rhs);
476 self
477 }
478 }
479
480 impl MulAssign for $name {
481 #[inline]
482 fn mul_assign(&mut self, rhs: Self) {
483 MulAssign::mul_assign(self, &rhs);
484 }
485 }
486
487 impl Mul<$name> for &$name {
488 type Output = $name;
489
490 #[must_use]
491 #[inline]
492 fn mul(self, rhs: $name) -> Self::Output {
493 Mul::mul(rhs, self)
494 }
495 }
496
497 impl Div for $name {
498 type Output = Self;
499
500 #[must_use]
501 #[inline]
502 fn div(mut self, rhs: Self) -> Self::Output {
503 DivAssign::div_assign(&mut self, rhs);
504 self
505 }
506 }
507
508 impl Div<&$name> for $name {
509 type Output = Self;
510
511 #[must_use]
512 #[inline]
513 fn div(mut self, rhs: &Self) -> Self::Output {
514 DivAssign::div_assign(&mut self, rhs);
515 self
516 }
517 }
518
519 impl<'a> Div<&'a $name> for &'a $name {
520 type Output = $name;
521
522 #[must_use]
523 #[inline]
524 fn div(self, rhs: Self) -> Self::Output {
525 Div::div(self.clone(), rhs)
526 }
527 }
528
529 impl DivAssign for $name {
530 #[inline]
531 fn div_assign(&mut self, rhs: Self) {
532 DivAssign::div_assign(self, &rhs);
533 }
534 }
535 }
536}
537
538rational_forward!(Rational8);
539rational_forward!(Rational16);
540rational_forward!(Rational32);
541rational_forward!(Rational64);
542rational_forward!(Rational128);
543rational_forward!(RationalUsize);
544rational_forward!(NonZeroRational8);
545rational_forward!(NonZeroRational16);
546rational_forward!(NonZeroRational32);
547rational_forward!(NonZeroRational64);
548rational_forward!(NonZeroRational128);
549rational_forward!(NonZeroRationalUsize);