1use crate::NonZeroUbig;
3use crate::rational::{Rational16, Rational32, Rational64, Rational8};
4use crate::rational::big::Big;
5use crate::sign::Negateable;
6use crate::sign::Sign;
7use crate::Ubig;
8
9macro_rules! define_interations {
10 ($small:ident, $module_name:ident) => {
11 mod $module_name {
12 use super::*;
13
14 mod creation {
15 use super::*;
16
17 impl<const S: usize> From<$small> for Big<S> {
18 #[must_use]
19 #[inline]
20 fn from(value: $small) -> Self {
21 Self {
22 sign: value.sign,
23 numerator: Ubig::new(value.numerator as usize),
24 denominator: unsafe {
25 NonZeroUbig::new_unchecked(value.denominator as usize)
27 },
28 }
29 }
30 }
31
32 impl<const S: usize> From<&$small> for Big<S> {
33 #[must_use]
34 #[inline]
35 fn from(value: &$small) -> Self {
36 Self {
37 sign: value.sign,
38 numerator: Ubig::new(value.numerator as usize),
39 denominator: unsafe {
40 NonZeroUbig::new_unchecked(value.denominator as usize)
42 },
43 }
44 }
45 }
46 }
47
48 mod compare {
49 use super::*;
50
51 impl<const S: usize> PartialEq<$small> for Big<S> {
52 #[inline]
53 fn eq(&self, other: &$small) -> bool {
54 *self.denominator.first() == other.denominator as usize &&
57 match self.sign {
58 Sign::Zero => other.sign == Sign::Zero,
59 Sign::Positive | Sign::Negative => {
60 self.numerator[0] == other.numerator as usize &&
61 self.numerator.len() == 1 &&
62 self.denominator.len() == 1
63 }
64 }
65 }
66 }
67 }
68
69 mod field {
70 use super::*;
71 use crate::sign::Sign;
72
73 mod add {
74 use super::*;
75 use std::ops::{Add, AddAssign};
76 use crate::rational::big::ops::building_blocks::{add_small, sub_small, SignChange};
77
78 impl<const S: usize> Add<$small> for Big<S> {
79 type Output = Self;
80
81 #[must_use]
82 #[inline]
83 fn add(mut self, rhs: $small) -> Self::Output {
84 AddAssign::add_assign(&mut self, &rhs);
85 self
86 }
87 }
88
89 impl<const S: usize> Add<&$small> for Big<S> {
90 type Output = Self;
91
92 #[must_use]
93 #[inline]
94 fn add(mut self, rhs: &$small) -> Self::Output {
95 AddAssign::add_assign(&mut self, rhs);
96 self
97 }
98 }
99
100 impl<const S: usize> Add<Option<&$small>> for Big<S> {
101 type Output = Self;
102
103 #[must_use]
104 #[inline]
105 fn add(self, rhs: Option<&$small>) -> Self::Output {
106 match rhs {
107 None => self,
108 Some(rhs) => Add::add(self, rhs),
109 }
110 }
111 }
112
113 impl<const S: usize> Add<&$small> for &Big<S> {
114 type Output = Big<S>;
115
116 #[must_use]
117 #[inline]
118 fn add(self, rhs: &$small) -> Self::Output {
119 let mut cloned = self.clone();
121 AddAssign::add_assign(&mut cloned, rhs);
122 cloned
123 }
124 }
125
126 impl<const S: usize> Add<Option<&$small>> for &Big<S> {
127 type Output = Big<S>;
128
129 #[must_use]
130 #[inline]
131 fn add(self, rhs: Option<&$small>) -> Self::Output {
132 let copy = self.clone();
134 match rhs {
135 None => copy,
136 Some(rhs) => Add::add(copy, rhs),
137 }
138 }
139 }
140
141 impl<const S: usize> AddAssign<$small> for Big<S> {
142 #[inline]
143 fn add_assign(&mut self, rhs: $small) {
144 AddAssign::add_assign(self, &rhs);
145 }
146 }
147
148 impl<const S: usize> AddAssign<&$small> for Big<S> {
149 #[inline]
150 fn add_assign(&mut self, rhs: &$small) {
151 match (self.sign, rhs.sign) {
152 (Sign::Positive, Sign::Positive) | (Sign::Negative, Sign::Negative) => {
153 unsafe {
154 add_small(
156 self.numerator.inner_mut(),
157 self.denominator.inner_mut(),
158 rhs.numerator as usize,
159 rhs.denominator as usize,
160 );
161 }
162 },
163 (Sign::Negative, Sign::Positive) | (Sign::Positive, Sign::Negative) => {
164 unsafe {
165 let sign_change = sub_small(
167 self.numerator.inner_mut(),
168 self.denominator.inner_mut(),
169 rhs.numerator as usize,
170 rhs.denominator as usize,
171 );
172 match sign_change {
173 SignChange::None => {}
174 SignChange::Flip => self.sign.negate(),
175 SignChange::Zero => self.sign = Sign::Zero,
176 }
177 }
178 }
179 (_, Sign::Zero) => {}
180 (Sign::Zero, _) => {
181 self.sign = rhs.sign;
182 debug_assert_eq!(self.numerator.len(), 0);
183 unsafe {
184 self.numerator.inner_mut().push(rhs.numerator as usize);
186 }
187 debug_assert_eq!(self.denominator.len(), 1);
188 debug_assert_eq!(self.denominator[0], 1);
189 unsafe {
190 *self.denominator.first_mut() = rhs.denominator as usize;
192 }
193 }
194 }
195 }
196 }
197 }
198
199 mod sub {
200 use super::*;
201 use crate::rational::big::ops::building_blocks::{add_small, sub_small, SignChange};
202 use std::ops::{Sub, SubAssign};
203
204 impl<const S: usize> Sub<$small> for Big<S> {
205 type Output = Self;
206
207 #[must_use]
208 #[inline]
209 fn sub(mut self, rhs: $small) -> Self::Output {
210 SubAssign::sub_assign(&mut self, &rhs);
211 self
212 }
213 }
214
215 impl<const S: usize> Sub<&$small> for Big<S> {
216 type Output = Self;
217
218 #[must_use]
219 #[inline]
220 fn sub(mut self, rhs: &$small) -> Self::Output {
221 SubAssign::sub_assign(&mut self, rhs);
222 self
223 }
224 }
225
226 impl<const S: usize> Sub<Option<&$small>> for Big<S> {
227 type Output = Self;
228
229 #[must_use]
230 #[inline]
231 fn sub(self, rhs: Option<&$small>) -> Self::Output {
232 match rhs {
233 None => self,
234 Some(rhs) => Sub::sub(self, rhs),
235 }
236 }
237 }
238
239 impl<const S: usize> Sub<&$small> for &Big<S> {
240 type Output = Big<S>;
241
242 #[must_use]
243 #[inline]
244 fn sub(self, rhs: &$small) -> Self::Output {
245 let mut cloned = self.clone();
247 SubAssign::sub_assign(&mut cloned, rhs);
248 cloned
249 }
250 }
251
252 impl<const S: usize> Sub<Option<&$small>> for &Big<S> {
253 type Output = Big<S>;
254
255 #[must_use]
256 #[inline]
257 fn sub(self, rhs: Option<&$small>) -> Self::Output {
258 let copy = self.clone();
260 match rhs {
261 None => copy,
262 Some(rhs) => Sub::sub(copy, rhs),
263 }
264 }
265 }
266
267 impl<const S: usize> SubAssign<$small> for Big<S> {
268 #[inline]
269 fn sub_assign(&mut self, rhs: $small) {
270 SubAssign::sub_assign(self, &rhs);
271 }
272 }
273
274 impl<const S: usize> SubAssign<&$small> for Big<S> {
275 #[inline]
276 fn sub_assign(&mut self, rhs: &$small) {
277 match (self.sign, rhs.sign) {
278 (Sign::Positive, Sign::Positive) | (Sign::Negative, Sign::Negative) => {
279 unsafe {
280 let sign_change = sub_small(
282 self.numerator.inner_mut(),
283 self.denominator.inner_mut(),
284 rhs.numerator as usize,
285 rhs.denominator as usize,
286 );
287 match sign_change {
288 SignChange::None => {}
289 SignChange::Flip => self.sign.negate(),
290 SignChange::Zero => self.sign = Sign::Zero,
291 }
292 }
293 }
294 (Sign::Negative, Sign::Positive) | (Sign::Positive, Sign::Negative) => {
295 unsafe {
296 add_small(
298 self.numerator.inner_mut(),
299 self.denominator.inner_mut(),
300 rhs.numerator as usize,
301 rhs.denominator as usize,
302 );
303 }
304 }
305 (_, Sign::Zero) => {}
306 (Sign::Zero, _) => {
307 self.sign = -rhs.sign;
308 debug_assert_eq!(self.numerator.len(), 0);
309 unsafe {
310 self.numerator.inner_mut().push(rhs.numerator as usize)
312 };
313 debug_assert_eq!(self.denominator.len(), 1);
314 debug_assert_eq!(self.denominator[0], 1);
315 unsafe {
316 *self.denominator.first_mut() = rhs.denominator as usize;
318 }
319 }
320 }
321 }
322 }
323 }
324
325 mod mul {
326 use super::*;
327 use std::ops::{Mul, MulAssign};
328 use crate::rational::big::ops::building_blocks::mul_small;
329
330 impl<const S: usize> Mul<$small> for Big<S> {
331 type Output = Self;
332
333 #[must_use]
334 #[inline]
335 fn mul(self, rhs: $small) -> Self::Output {
336 Mul::mul(self, &rhs)
337 }
338 }
339
340 impl<const S: usize> Mul<&$small> for Big<S> {
341 type Output = Self;
342
343 #[must_use]
344 #[inline]
345 fn mul(mut self, rhs: &$small) -> Self::Output {
346 MulAssign::mul_assign(&mut self, rhs);
347 self
348 }
349 }
350
351 impl<const S: usize> Mul<&$small> for &Big<S> {
352 type Output = Big<S>;
353
354 #[must_use]
355 #[inline]
356 fn mul(self, rhs: &$small) -> Self::Output {
357 self.clone() * rhs
359 }
360 }
361
362 impl<const S: usize> Mul<Option<&$small>> for Big<S> {
363 type Output = Big<S>;
364
365 #[must_use]
366 #[inline]
367 fn mul(mut self, rhs: Option<&$small>) -> Self::Output {
368 match rhs {
369 None => {
370 <Self as num_traits::Zero>::set_zero(&mut self);
371 self
372 },
373 Some(rhs) => Mul::mul(self, rhs),
374 }
375 }
376 }
377
378 impl<const S: usize> Mul<Option<&$small>> for &Big<S> {
379 type Output = Big<S>;
380
381 #[must_use]
382 #[inline]
383 fn mul(self, rhs: Option<&$small>) -> Self::Output {
384 match rhs {
385 None => <Self::Output as num_traits::Zero>::zero(),
386 Some(rhs) => Mul::mul(self, rhs),
387 }
388 }
389 }
390
391 impl<const S: usize> MulAssign<$small> for Big<S> {
392 #[inline]
393 fn mul_assign(&mut self, rhs: $small) {
394 MulAssign::mul_assign(self, &rhs);
395 }
396 }
397
398 impl<const S: usize> MulAssign<&$small> for Big<S> {
399 #[inline]
400 fn mul_assign(&mut self, rhs: &$small) {
401 match (self.sign, rhs.sign) {
402 (Sign::Positive | Sign::Negative, Sign::Positive | Sign::Negative) => {
403 self.sign *= rhs.sign;
404 unsafe {
405 mul_small(
406 self.numerator.inner_mut(),
407 self.denominator.inner_mut(),
408 rhs.numerator as usize,
409 rhs.denominator as usize,
410 )
411 }
412 }
413 (Sign::Positive | Sign::Negative, Sign::Zero) => {
414 <Self as num_traits::Zero>::set_zero(self);
415 }
416 (Sign::Zero, _) => {}
417 }
418 }
419 }
420 }
421
422 mod div {
423 use super::*;
424 use std::ops::{Div, DivAssign};
425 use crate::rational::big::ops::building_blocks::mul_small;
426
427 impl<const S: usize> Div<$small> for Big<S> {
428 type Output = Big<S>;
429
430 #[must_use]
431 #[inline]
432 fn div(mut self, rhs: $small) -> Self::Output {
433 DivAssign::div_assign(&mut self, rhs);
434 self
435 }
436 }
437
438 impl<const S: usize> Div<&$small> for Big<S> {
439 type Output = Big<S>;
440
441 #[must_use]
442 #[inline]
443 fn div(mut self, rhs: &$small) -> Self::Output {
444 DivAssign::div_assign(&mut self, rhs);
445 self
446 }
447 }
448
449 impl<const S: usize> DivAssign<$small> for Big<S> {
450 #[inline]
451 fn div_assign(&mut self, rhs: $small) {
452 DivAssign::div_assign(self, &rhs);
453 }
454 }
455
456 impl<const S: usize> DivAssign<&$small> for Big<S> {
457 #[inline]
458 fn div_assign(&mut self, rhs: &$small) {
459 match (self.sign, rhs.sign) {
460 (Sign::Positive | Sign::Negative, Sign::Positive | Sign::Negative) => {
461 self.sign *= rhs.sign;
462 unsafe {
463 mul_small(
464 self.numerator.inner_mut(),
465 self.denominator.inner_mut(),
466 rhs.denominator as usize,
467 rhs.numerator as usize,
468 );
469 }
470 }
471 (Sign::Positive | Sign::Negative, Sign::Zero) => panic!("attempt to divide by zero"),
472 (Sign::Zero, _) => {}
473 }
474 }
475 }
476 }
477 }
478 }
479 }
480}
481
482define_interations!(Rational8, rational8);
483define_interations!(Rational16, rational16);
484define_interations!(Rational32, rational32);
485define_interations!(Rational64, rational64);
486
487#[cfg(test)]
488mod test {
489 use num_traits::One;
490 use smallvec::smallvec;
491
492 use crate::{R16, R32, R64, R8, RationalBig, RB, Sign, Ubig};
493 use crate::integer::big::NonZeroUbig;
494
495 #[test]
496 fn test_eq() {
497 assert_eq!(RB!(0), R64!(0));
498 assert_eq!(RB!(-2), R64!(-2));
499 assert_eq!(RB!(854984, 6868468468), R64!(854984, 6868468468));
500 assert_eq!(RB!(-989888, 4968468421), R64!(-989888, 4968468421));
501 assert_ne!(RB!(668468498646846546846546898997987_u128), R8!(1));
502 assert_ne!(RB!(668468498646846546846546898997987.4385484_f64), R8!(1, 2));
503 }
504
505 #[test]
506 fn test_add_sub() {
507 assert_eq!(RB!(0) + R8!(0), RB!(0));
508 assert_eq!(RB!(89) + R8!(1), RB!(90));
509 assert_eq!(RB!(89) - R16!(1), RB!(88));
510
511 assert_eq!(RB!(2, 3) + R16!(4, 9), RB!(10, 9));
512 assert_eq!(RB!(989, 141) + R8!(1, 141), RB!(990, 141));
513 assert_eq!(RB!(-84, 3) + R8!(1, 3), RB!(-83, 3));
514 assert_eq!(RB!(1, 2) + R8!(1, 2), RB!(1));
515 assert_eq!(RB!(-1, 2) + R8!(1, 2), RB!(0));
516 assert_eq!(RB!(-1, 2) + R8!(1), RB!(1, 2));
517 assert_eq!(RB!(7, 2) + R8!(5, 2), RB!(6));
518 assert_eq!(RB!(-7, 2) + R8!(5, 2), RB!(-1));
519 assert_eq!(RB!(-7, 2) - R8!(5, 2), RB!(-6));
520 assert_eq!(
521 RationalBig {
522 sign: Sign::Positive,
523 numerator: unsafe { Ubig::from_inner_unchecked(smallvec![1, 1]) },
524 denominator: unsafe { NonZeroUbig::from_inner_unchecked(smallvec![2]) },
525 } + R8!(1, 2),
526 RationalBig {
527 sign: Sign::Positive,
528 numerator: unsafe { Ubig::from_inner_unchecked(smallvec![(1 << 63) + 1]) },
529 denominator: NonZeroUbig::one(),
530 },
531 );
532
533 assert_eq!(RB!(2, 3) + R8!(8, 1), RB!(8 * 3 + 2, 3));
534 assert_eq!(RB!(8) + R8!(16, 3), RB!(8 * 3 + 16, 3));
535 assert_eq!(RB!(3, 5) + R16!(2, 5), RB!(1));
536
537 assert_eq!(RB!(5) - R32!(7), RB!(-2));
538 assert_eq!(
539 RationalBig {
540 sign: Sign::Positive,
541 numerator: unsafe { Ubig::from_inner_unchecked(smallvec![1, 1]) },
542 denominator: unsafe { NonZeroUbig::from_inner_unchecked(smallvec![2]) },
543 } - R8!(1, 2),
544 RationalBig {
545 sign: Sign::Positive,
546 numerator: unsafe { Ubig::from_inner_unchecked(smallvec![1 << 63]) },
547 denominator: NonZeroUbig::one(),
548 },
549 );
550 assert_eq!(RB!(5, 2) - R8!(2), RB!(1, 2));
551 assert_eq!(RB!(3) - R8!(1, 2), RB!(5, 2));
552 assert_eq!(RB!(16, 3) - R8!(11, 4), RB!(16 * 4 - 11 * 3, 12));
553
554 assert_eq!(RB!(0) + R8!(1, 2), RB!(1, 2));
555 assert_eq!(RB!(0) - R8!(3, 4), RB!(-3, 4));
556 assert_eq!(RB!(-10, 4) + R8!(-10, 8), RB!(-15, 4));
557 assert_eq!(RB!(-10, 4) + R64!(1, 4), RB!(-9, 4));
558 assert_eq!(RB!(-10, 8) + R64!(-10, 9), RB!(-5 * 17, 3 * 3 * 2 * 2));
559 assert_eq!(RB!(-5, 4) + R64!(-5, 4), RB!(-5, 2));
560 assert_eq!(RB!(-7, 6) + R64!(-7, 6), RB!(-7, 3));
561
562 let limit = 10;
563 for a in -limit..limit {
564 for b in 1..limit {
565 for c in -limit..limit {
566 for d in 1..limit {
567 assert_eq!(RB!(a, b as u64) + R64!(c, d as u64), RB!(a * d + c * b, b as u64 * d as u64), "{} / {} - {} / {}", a, b, c, d);
568 }
569 }
570 }
571 }
572 }
573
574 #[test]
575 fn test_mul_div() {
576 assert_eq!(RB!(0) * R8!(18), RB!(0));
577 assert_eq!(RB!(1) * R8!(6), RB!(6));
578 assert_eq!(RB!(-1) * R64!(65488846), -RB!(65488846));
579 assert_eq!(RB!(7, 11) * R8!(11, 7), RB!(1));
580 assert_eq!(RB!(7, 11) * R16!(22, 7), RB!(2));
581 assert_eq!(RB!(14, 33) * R32!(3, 2), RB!(7, 11));
582 assert_eq!(RB!(4, 3) * R64!(0), RB!(0));
583
584 let limit = 10;
585 for a in -limit..limit {
586 for b in 1..limit {
587 for c in -limit..limit {
588 for d in 1..limit {
589 assert_eq!(RB!(a, b as u64) * R64!(c, d as u64), RB!(a * c, (b * d) as u64), "{} / {} * {} / {}", a, b, c, d);
590 }
591 }
592 }
593 }
594 }
595}