1use std::cmp::Ordering;
2use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Sub, SubAssign};
3
4use num_traits::{One, Zero};
5use smallvec::SmallVec;
6
7use crate::{Negateable, NonZero, NonZeroUbig, Sign, Ubig};
8use crate::integer::big::ops::building_blocks::is_well_formed_non_zero;
9use crate::integer::big::ops::non_zero::{add_assign, mul_non_zero, subtracting_cmp};
10use crate::integer::big::ops::normalize::simplify_fraction_without_info;
11use crate::rational::big::{Big, NonZeroBig};
12
13mod small;
14
15impl<const S: usize> Add<Ubig<S>> for Big<S> {
16 type Output = Self;
17
18 #[inline]
19 fn add(mut self, rhs: Ubig<S>) -> Self::Output {
20 AddAssign::add_assign(&mut self, rhs);
21 self
22 }
23}
24
25impl<const S: usize> Add<&Ubig<S>> for Big<S> {
26 type Output = Self;
27
28 #[inline]
29 fn add(mut self, rhs: &Ubig<S>) -> Self::Output {
30 AddAssign::add_assign(&mut self, rhs);
31 self
32 }
33}
34
35impl<const S: usize> AddAssign<Ubig<S>> for Big<S> {
36 #[inline]
37 fn add_assign(&mut self, rhs: Ubig<S>) {
38 AddAssign::add_assign(self, &rhs);
40 }
41}
42
43impl<const S: usize> AddAssign<&Ubig<S>> for Big<S> {
44 #[inline]
45 fn add_assign(&mut self, rhs: &Ubig<S>) {
46 if rhs.is_not_zero() {
47 unsafe {
48 self.add_assign_int_non_zero(rhs);
50 }
51 }
52 }
53}
54
55impl<const S: usize> Add<NonZeroUbig<S>> for Big<S> {
56 type Output = Self;
57
58 #[inline]
59 fn add(mut self, rhs: NonZeroUbig<S>) -> Self::Output {
60 AddAssign::add_assign(&mut self, rhs);
61 self
62 }
63}
64
65impl<const S: usize> Add<&NonZeroUbig<S>> for Big<S> {
66 type Output = Self;
67
68 #[inline]
69 fn add(mut self, rhs: &NonZeroUbig<S>) -> Self::Output {
70 AddAssign::add_assign(&mut self, rhs);
71 self
72 }
73}
74
75impl<const S: usize> AddAssign<NonZeroUbig<S>> for Big<S> {
76 #[inline]
77 fn add_assign(&mut self, rhs: NonZeroUbig<S>) {
78 AddAssign::add_assign(self, &rhs);
80 }
81}
82
83impl<const S: usize> AddAssign<&NonZeroUbig<S>> for Big<S> {
84 #[inline]
85 fn add_assign(&mut self, rhs: &NonZeroUbig<S>) {
86 unsafe {
87 self.add_assign_int_non_zero(rhs);
89 }
90 }
91}
92
93impl<const S: usize> Big<S> {
94 #[inline]
95 unsafe fn add_assign_int_non_zero(&mut self, rhs: &[usize]) {
96 debug_assert!(is_well_formed_non_zero(rhs));
97
98 match self.sign {
99 Sign::Positive => {
100 unsafe {
106 let difference = mul_non_zero::<S>(&self.denominator, rhs);
107 add_assign(self.numerator.inner_mut(), &difference)
108 }
109 },
110 Sign::Zero => {
111 unsafe { *self.numerator.inner_mut() = SmallVec::from_slice(rhs) };
116 self.sign = Sign::Positive;
117 debug_assert!(self.denominator.is_one());
118 }
119 Sign::Negative => {
120 let ordering = unsafe {
124 let difference = mul_non_zero::<S>(&self.denominator, rhs);
125 subtracting_cmp(self.numerator.inner_mut(), &difference)
126 };
127
128 match ordering {
129 Ordering::Less => self.sign.negate(),
130 Ordering::Equal => self.set_zero(),
131 Ordering::Greater => {}
132 }
133 }
134 }
135 }
136}
137
138impl<const S: usize> Sub<Ubig<S>> for Big<S> {
139 type Output = Self;
140
141 #[inline]
142 fn sub(mut self, rhs: Ubig<S>) -> Self::Output {
143 SubAssign::sub_assign(&mut self, rhs);
144 self
145 }
146}
147
148impl<const S: usize> Sub<&Ubig<S>> for Big<S> {
149 type Output = Self;
150
151 #[inline]
152 fn sub(mut self, rhs: &Ubig<S>) -> Self::Output {
153 SubAssign::sub_assign(&mut self, rhs);
154 self
155 }
156}
157
158impl<const S: usize> SubAssign<Ubig<S>> for Big<S> {
159 #[inline]
160 fn sub_assign(&mut self, rhs: Ubig<S>) {
161 SubAssign::sub_assign(self, &rhs);
163 }
164}
165
166impl<const S: usize> SubAssign<&Ubig<S>> for Big<S> {
167 #[inline]
168 fn sub_assign(&mut self, rhs: &Ubig<S>) {
169 if rhs.is_not_zero() {
170 unsafe {
171 self.sub_assign_int_non_zero(rhs);
173 }
174 }
175 }
176}
177
178impl<const S: usize> Sub<NonZeroUbig<S>> for Big<S> {
179 type Output = Self;
180
181 #[inline]
182 fn sub(mut self, rhs: NonZeroUbig<S>) -> Self::Output {
183 SubAssign::sub_assign(&mut self, rhs);
184 self
185 }
186}
187
188impl<const S: usize> Sub<&NonZeroUbig<S>> for Big<S> {
189 type Output = Self;
190
191 #[inline]
192 fn sub(mut self, rhs: &NonZeroUbig<S>) -> Self::Output {
193 SubAssign::sub_assign(&mut self, rhs);
194 self
195 }
196}
197
198impl<const S: usize> SubAssign<NonZeroUbig<S>> for Big<S> {
199 #[inline]
200 fn sub_assign(&mut self, rhs: NonZeroUbig<S>) {
201 SubAssign::sub_assign(self, &rhs);
203 }
204}
205
206impl<const S: usize> SubAssign<&NonZeroUbig<S>> for Big<S> {
207 #[inline]
208 fn sub_assign(&mut self, rhs: &NonZeroUbig<S>) {
209 unsafe {
210 self.sub_assign_int_non_zero(rhs);
212 }
213 }
214}
215
216impl<const S: usize> Big<S> {
217 #[inline]
218 unsafe fn sub_assign_int_non_zero(&mut self, rhs: &[usize]) {
219 debug_assert!(is_well_formed_non_zero(rhs));
220
221 match self.sign {
222 Sign::Positive => {
223 let ordering = unsafe {
229 let difference = mul_non_zero::<S>(&self.denominator, rhs);
230 subtracting_cmp(self.numerator.inner_mut(), &difference)
231 };
232
233 match ordering {
234 Ordering::Less => self.sign.negate(),
235 Ordering::Equal => self.set_zero(),
236 Ordering::Greater => {}
237 }
238 }
239 Sign::Zero => {
240 unsafe { *self.numerator.inner_mut() = SmallVec::from_slice(rhs) };
245 self.sign = Sign::Negative;
246 debug_assert!(self.denominator.is_one());
247 }
248 Sign::Negative => {
249 unsafe {
253 let difference = mul_non_zero::<S>(&self.denominator, rhs);
254 add_assign(self.numerator.inner_mut(), &difference)
255 }
256 },
257 }
258 }
259}
260
261impl<const S: usize> Mul<Ubig<S>> for Big<S> {
262 type Output = Self;
263
264 #[inline]
265 fn mul(mut self, rhs: Ubig<S>) -> Self::Output {
266 MulAssign::mul_assign(&mut self, rhs);
267 self
268 }
269}
270
271impl<const S: usize> MulAssign<Ubig<S>> for Big<S> {
272 #[inline]
273 fn mul_assign(&mut self, rhs: Ubig<S>) {
274 if !rhs.is_zero() {
275 if self.is_not_zero() {
276 unsafe {
281 mul_assign_int_owning(
282 self.numerator.inner_mut(),
283 self.denominator.inner_mut(),
284 rhs.into_inner(),
285 );
286 }
287 }
288 } else {
289 self.set_zero();
290 }
291 }
292}
293
294impl<const S: usize> Mul<NonZeroUbig<S>> for Big<S> {
295 type Output = Self;
296
297 #[inline]
298 fn mul(mut self, rhs: NonZeroUbig<S>) -> Self::Output {
299 MulAssign::mul_assign(&mut self, rhs);
300 self
301 }
302}
303
304impl<const S: usize> MulAssign<NonZeroUbig<S>> for Big<S> {
305 #[inline]
306 fn mul_assign(&mut self, rhs: NonZeroUbig<S>) {
307 if self.is_not_zero() {
308 unsafe {
313 mul_assign_int_owning(
314 self.numerator.inner_mut(),
315 self.denominator.inner_mut(),
316 rhs.into_inner(),
317 );
318 }
319 }
320 }
321}
322
323impl<const S: usize> Mul<NonZeroUbig<S>> for NonZeroBig<S> {
324 type Output = Self;
325
326 #[inline]
327 fn mul(mut self, rhs: NonZeroUbig<S>) -> Self::Output {
328 MulAssign::mul_assign(&mut self, rhs);
329 self
330 }
331}
332
333impl<const S: usize> MulAssign<NonZeroUbig<S>> for NonZeroBig<S> {
334 #[inline]
335 fn mul_assign(&mut self, rhs: NonZeroUbig<S>) {
336 unsafe {
341 mul_assign_int_owning(
342 self.numerator.inner_mut(),
343 self.denominator.inner_mut(),
344 rhs.into_inner(),
345 );
346 }
347 }
348}
349
350impl<const S: usize> Mul<&NonZeroUbig<S>> for NonZeroBig<S> {
351 type Output = Self;
352
353 #[inline]
354 fn mul(mut self, rhs: &NonZeroUbig<S>) -> Self::Output {
355 MulAssign::mul_assign(&mut self, rhs);
356 self
357 }
358}
359
360impl<const S: usize> MulAssign<&NonZeroUbig<S>> for NonZeroBig<S> {
361 #[inline]
362 fn mul_assign(&mut self, rhs: &NonZeroUbig<S>) {
363 unsafe {
368 mul_assign_int(
369 self.numerator.inner_mut(),
370 self.denominator.inner_mut(),
371 rhs.inner(),
372 );
373 }
374 }
375}
376
377impl<const S: usize> MulAssign<&NonZeroUbig<S>> for Big<S> {
378 #[inline]
379 fn mul_assign(&mut self, rhs: &NonZeroUbig<S>) {
380 if self.is_not_zero() {
381 unsafe {
386 mul_assign_int(
387 self.numerator.inner_mut(),
388 self.denominator.inner_mut(),
389 rhs.inner(),
390 );
391 }
392 }
393 }
394}
395
396impl<const S: usize> Div<NonZeroUbig<S>> for Big<S> {
397 type Output = Self;
398
399 #[inline]
400 fn div(mut self, rhs: NonZeroUbig<S>) -> Self::Output {
401 DivAssign::div_assign(&mut self, rhs);
402 self
403 }
404}
405
406impl<const S: usize> DivAssign<NonZeroUbig<S>> for Big<S> {
407 #[inline]
408 fn div_assign(&mut self, rhs: NonZeroUbig<S>) {
409 if self.is_not_zero() {
410 unsafe {
417 mul_assign_int_owning(
418 self.denominator.inner_mut(),
419 self.numerator.inner_mut(),
420 rhs.into_inner(),
421 );
422 }
423 }
424 }
425}
426
427impl<const S: usize> DivAssign<&NonZeroUbig<S>> for Big<S> {
428 #[inline]
429 fn div_assign(&mut self, rhs: &NonZeroUbig<S>) {
430 if self.is_not_zero() {
431 unsafe {
438 mul_assign_int(
439 self.denominator.inner_mut(),
440 self.numerator.inner_mut(),
441 rhs.inner(),
442 );
443 }
444 }
445 }
446}
447
448impl<const S: usize> Div<Ubig<S>> for Big<S> {
449 type Output = Self;
450
451 #[inline]
452 fn div(mut self, rhs: Ubig<S>) -> Self::Output {
453 DivAssign::div_assign(&mut self, rhs);
454 self
455 }
456}
457
458impl<const S: usize> DivAssign<Ubig<S>> for Big<S> {
459 #[inline]
460 fn div_assign(&mut self, rhs: Ubig<S>) {
461 if !rhs.is_zero() {
462 if self.is_not_zero() {
463 unsafe {
470 mul_assign_int_owning(
471 self.denominator.inner_mut(),
472 self.numerator.inner_mut(),
473 rhs.into_inner(),
474 );
475 }
476 }
477 } else {
478 panic!("attempt to divide by zero");
479 }
480 }
481}
482
483impl<const S: usize> Div<NonZeroUbig<S>> for NonZeroBig<S> {
484 type Output = Self;
485
486 #[inline]
487 fn div(mut self, rhs: NonZeroUbig<S>) -> Self::Output {
488 DivAssign::div_assign(&mut self, rhs);
489 self
490 }
491}
492
493impl<const S: usize> DivAssign<NonZeroUbig<S>> for NonZeroBig<S> {
494 #[inline]
495 fn div_assign(&mut self, rhs: NonZeroUbig<S>) {
496 unsafe {
503 mul_assign_int_owning(
504 self.denominator.inner_mut(),
505 self.numerator.inner_mut(),
506 rhs.into_inner(),
507 );
508 }
509 }
510}
511
512impl<const S: usize> Div<&NonZeroUbig<S>> for NonZeroBig<S> {
513 type Output = Self;
514
515 #[inline]
516 fn div(mut self, rhs: &NonZeroUbig<S>) -> Self::Output {
517 DivAssign::div_assign(&mut self, rhs);
518 self
519 }
520}
521
522impl<const S: usize> DivAssign<&NonZeroUbig<S>> for NonZeroBig<S> {
523 #[inline]
524 fn div_assign(&mut self, rhs: &NonZeroUbig<S>) {
525 unsafe {
532 mul_assign_int(
533 self.denominator.inner_mut(),
534 self.numerator.inner_mut(),
535 rhs.inner(),
536 );
537 }
538 }
539}
540
541#[inline]
542unsafe fn mul_assign_int<const S: usize>(
543 left_numerator: &mut SmallVec<[usize; S]>, left_denominator: &mut SmallVec<[usize; S]>,
544 right: &[usize],
545) {
546 debug_assert!(is_well_formed_non_zero(left_numerator));
547 debug_assert!(is_well_formed_non_zero(left_denominator));
548 debug_assert!(is_well_formed_non_zero(right));
549
550 unsafe {
553 *left_numerator = mul_non_zero(left_numerator, right);
554 simplify_fraction_without_info(left_numerator, left_denominator);
555 }
556}
557
558#[inline]
559unsafe fn mul_assign_int_owning<const S: usize>(
560 left_numerator: &mut SmallVec<[usize; S]>, left_denominator: &mut SmallVec<[usize; S]>,
561 mut right: SmallVec<[usize; S]>,
562) {
563 debug_assert!(is_well_formed_non_zero(left_numerator));
564 debug_assert!(is_well_formed_non_zero(left_denominator));
565 debug_assert!(is_well_formed_non_zero(&right));
566
567 unsafe {
571 simplify_fraction_without_info(left_denominator, &mut right);
572 *left_numerator = mul_non_zero(left_numerator, &right);
573 }
574}
575
576#[cfg(test)]
577mod test {
578 use std::ops::DivAssign;
579
580 use num_traits::{One, Zero};
581
582 use crate::{NonZeroUbig, RationalBig, Ubig};
583 use crate::rational::big::NonZeroBig;
584 use crate::RB;
585
586 #[test]
587 fn add() {
588 assert_eq!(RB!(2, 3) + NonZeroUbig::new(2).unwrap(), RB!(8, 3));
589 assert_eq!(RB!(-2, 3) + NonZeroUbig::new(2).unwrap(), RB!(4, 3));
590 assert_eq!(RB!(2, 3) + Ubig::zero(), RB!(2, 3));
591 assert_eq!(RB!(2, 3) - NonZeroUbig::new(2).unwrap(), RB!(-4, 3));
592 assert_eq!(RB!(0) - NonZeroUbig::one(), RB!(-1));
593 assert_eq!(RB!(-2, 3) - NonZeroUbig::new(2).unwrap(), RB!(-8, 3));
594 }
595
596 #[test]
597 fn mul_assign() {
598 assert_eq!(RB!(2, 3) * NonZeroUbig::new(2).unwrap(), RB!(4, 3));
599 assert_eq!(RB!(2, 3) * Ubig::zero(), RB!(0));
600 assert_eq!(RB!(2, 3) / NonZeroUbig::new(2).unwrap(), RB!(1, 3));
601 assert_eq!(RB!(0) * NonZeroUbig::one(), RB!(0));
602 }
603
604 #[test]
605 #[should_panic]
606 #[allow(unused_must_use)]
607 fn mul_panic() {
608 RationalBig::one() / Ubig::zero();
609 }
610
611 #[test]
614 fn add_int_cancelling_to_zero() {
615 let mut x = RB!(-5);
616 x += NonZeroUbig::new(5).unwrap();
617 assert!(x.is_zero());
618 assert_eq!(x, RB!(0));
619 assert_eq!(format!("{:?}", x), "0");
620
621 let mut y = RB!(-5);
622 y += Ubig::new(5);
623 assert!(y.is_zero());
624 assert_eq!(y, RB!(0));
625 assert_eq!(format!("{:?}", y), "0");
626 }
627
628 #[test]
630 fn sub_int_cancelling_to_zero() {
631 let mut x = RB!(5);
632 x -= NonZeroUbig::new(5).unwrap();
633 assert!(x.is_zero());
634 assert_eq!(x, RB!(0));
635 assert_eq!(format!("{:?}", x), "0");
636
637 let mut y = RB!(5);
638 y -= Ubig::new(5);
639 assert!(y.is_zero());
640 assert_eq!(y, RB!(0));
641 assert_eq!(format!("{:?}", y), "0");
642 }
643
644 #[test]
646 fn add_int_to_zero_sets_sign() {
647 let mut x = RB!(0);
648 x += NonZeroUbig::new(5).unwrap();
649 assert!(!x.is_zero());
650 assert_eq!(x, RB!(5));
651 assert_eq!(format!("{:?}", x), "5");
652
653 let mut y = RB!(0);
654 y += Ubig::new(5);
655 assert!(!y.is_zero());
656 assert_eq!(y, RB!(5));
657 assert_eq!(format!("{:?}", y), "5");
658 }
659
660 #[test]
662 fn div_non_zero_big_by_non_zero_ubig() {
663 let two = NonZeroUbig::new(2).unwrap();
664
665 let mut expected = NonZeroBig::<8>::one();
666 DivAssign::div_assign(&mut expected, two.clone());
667
668 let owned = NonZeroBig::<8>::one() / two.clone();
669 assert!(owned == expected);
670 assert!(owned * two.clone() == NonZeroBig::<8>::one());
671
672 let borrowed = NonZeroBig::<8>::one() / &two;
673 assert!(borrowed == expected);
674 assert!(borrowed * &two == NonZeroBig::<8>::one());
675 }
676
677 #[test]
679 fn div_zero_by_ubig() {
680 let mut x = RB!(0);
681 x /= Ubig::<8>::new(2);
682 assert!(x.is_zero());
683 assert_eq!(x, RB!(0));
684 assert_eq!(format!("{:?}", x), "0");
685
686 let y = RB!(0) / Ubig::<8>::new(2);
687 assert!(y.is_zero());
688 assert_eq!(y, RB!(0));
689 }
690}