1use std::cmp::Ordering;
2use std::num::{NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8, NonZeroUsize};
3use std::num::{NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI8, NonZeroIsize};
4use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Sub, SubAssign};
5
6use num_traits::{One, Zero};
7use smallvec::{smallvec, SmallVec};
8
9use crate::{NonZeroSign, NonZeroSigned, Signed};
10use crate::{Negateable, NonZero, Sign};
11use crate::integer::big::ops::building_blocks::is_well_formed_non_zero;
12use crate::integer::big::ops::non_zero::{add_assign, is_one_non_zero, mul_assign_single_non_zero, mul_non_zero, subtracting_cmp};
13use crate::integer::big::ops::normalize::simplify_fraction_gcd_single;
14use crate::rational::big::{Big, NonZeroBig};
15
16macro_rules! forwards {
17 ($ty:ty, $large:ty) => {
18 impl<const S: usize> Add<$ty> for $large {
19 type Output = Self;
20
21 #[inline]
22 fn add(mut self, rhs: $ty) -> Self::Output {
23 AddAssign::add_assign(&mut self, rhs);
24 self
25 }
26 }
27
28 impl<const S: usize> Add<&$ty> for $large {
29 type Output = Self;
30
31 #[inline]
32 fn add(mut self, rhs: &$ty) -> Self::Output {
33 AddAssign::add_assign(&mut self, rhs);
34 self
35 }
36 }
37
38 impl<const S: usize> Add<$ty> for &$large {
39 type Output = $large;
40
41 #[inline]
42 fn add(self, rhs: $ty) -> Self::Output {
43 Add::add(self.clone(), rhs)
44 }
45 }
46
47 impl<const S: usize> Add<&$ty> for &$large {
48 type Output = $large;
49
50 #[inline]
51 fn add(self, rhs: &$ty) -> Self::Output {
52 Add::add(self, *rhs)
53 }
54 }
55
56 impl<const S: usize> AddAssign<&$ty> for $large {
57 #[inline]
58 fn add_assign(&mut self, rhs: &$ty) {
59 AddAssign::add_assign(self, *rhs);
60 }
61 }
62
63 impl<const S: usize> Sub<$ty> for $large {
64 type Output = Self;
65
66 #[inline]
67 fn sub(mut self, rhs: $ty) -> Self::Output {
68 SubAssign::sub_assign(&mut self, rhs);
69 self
70 }
71 }
72
73 impl<const S: usize> Sub<&$ty> for $large {
74 type Output = Self;
75
76 #[inline]
77 fn sub(mut self, rhs: &$ty) -> Self::Output {
78 SubAssign::sub_assign(&mut self, rhs);
79 self
80 }
81 }
82
83 impl<const S: usize> Sub<$ty> for &$large {
84 type Output = $large;
85
86 #[inline]
87 fn sub(self, rhs: $ty) -> Self::Output {
88 Sub::sub(self.clone(), rhs)
89 }
90 }
91
92 impl<const S: usize> Sub<&$ty> for &$large {
93 type Output = $large;
94
95 #[inline]
96 fn sub(self, rhs: &$ty) -> Self::Output {
97 Sub::sub(self, *rhs)
98 }
99 }
100
101 impl<const S: usize> SubAssign<&$ty> for $large {
102 #[inline]
103 fn sub_assign(&mut self, rhs: &$ty) {
104 SubAssign::sub_assign(self, *rhs);
105 }
106 }
107
108 impl<const S: usize> Mul<$ty> for $large {
109 type Output = Self;
110
111 #[inline]
112 fn mul(mut self, rhs: $ty) -> Self::Output {
113 MulAssign::mul_assign(&mut self, rhs);
114 self
115 }
116 }
117
118 impl<const S: usize> Mul<&$ty> for $large {
119 type Output = Self;
120
121 #[inline]
122 fn mul(mut self, rhs: &$ty) -> Self::Output {
123 MulAssign::mul_assign(&mut self, rhs);
124 self
125 }
126 }
127
128 impl<const S: usize> Mul<$ty> for &$large {
129 type Output = $large;
130
131 #[inline]
132 fn mul(self, rhs: $ty) -> Self::Output {
133 Mul::mul(self.clone(), rhs)
134 }
135 }
136
137 impl<const S: usize> Mul<&$ty> for &$large {
138 type Output = $large;
139
140 #[inline]
141 fn mul(self, rhs: &$ty) -> Self::Output {
142 Mul::mul(self, *rhs)
143 }
144 }
145
146 impl<const S: usize> MulAssign<&$ty> for $large {
147 #[inline]
148 fn mul_assign(&mut self, rhs: &$ty) {
149 MulAssign::mul_assign(self, *rhs);
150 }
151 }
152
153 impl<const S: usize> Div<$ty> for $large {
154 type Output = Self;
155
156 #[inline]
157 fn div(mut self, rhs: $ty) -> Self::Output {
158 DivAssign::div_assign(&mut self, rhs);
159 self
160 }
161 }
162
163 impl<const S: usize> Div<&$ty> for $large {
164 type Output = Self;
165
166 #[inline]
167 fn div(mut self, rhs: &$ty) -> Self::Output {
168 DivAssign::div_assign(&mut self, rhs);
169 self
170 }
171 }
172
173 impl<const S: usize> Div<$ty> for &$large {
174 type Output = $large;
175
176 #[inline]
177 fn div(self, rhs: $ty) -> Self::Output {
178 Div::div(self.clone(), rhs)
179 }
180 }
181
182 impl<const S: usize> Div<&$ty> for &$large {
183 type Output = $large;
184
185 #[inline]
186 fn div(self, rhs: &$ty) -> Self::Output {
187 Div::div(self, *rhs)
188 }
189 }
190
191 impl<const S: usize> DivAssign<&$ty> for $large {
192 #[inline]
193 fn div_assign(&mut self, rhs: &$ty) {
194 DivAssign::div_assign(self, *rhs);
195 }
196 }
197 }
198}
199
200forwards!(u8, Big<S>);
201forwards!(u16, Big<S>);
202forwards!(u32, Big<S>);
203forwards!(u64, Big<S>);
204forwards!(usize, Big<S>);
205forwards!(NonZeroU8, Big<S>);
206forwards!(NonZeroU16, Big<S>);
207forwards!(NonZeroU32, Big<S>);
208forwards!(NonZeroU64, Big<S>);
209forwards!(NonZeroUsize, Big<S>);
210forwards!(i8, Big<S>);
211forwards!(i16, Big<S>);
212forwards!(i32, Big<S>);
213forwards!(i64, Big<S>);
214forwards!(isize, Big<S>);
215forwards!(NonZeroI8, Big<S>);
216forwards!(NonZeroI16, Big<S>);
217forwards!(NonZeroI32, Big<S>);
218forwards!(NonZeroI64, Big<S>);
219forwards!(NonZeroIsize, Big<S>);
220
221forwards!(u8, NonZeroBig<S>);
222forwards!(u16, NonZeroBig<S>);
223forwards!(u32, NonZeroBig<S>);
224forwards!(u64, NonZeroBig<S>);
225forwards!(usize, NonZeroBig<S>);
226forwards!(NonZeroU8, NonZeroBig<S>);
227forwards!(NonZeroU16, NonZeroBig<S>);
228forwards!(NonZeroU32, NonZeroBig<S>);
229forwards!(NonZeroU64, NonZeroBig<S>);
230forwards!(NonZeroUsize, NonZeroBig<S>);
231forwards!(i8, NonZeroBig<S>);
232forwards!(i16, NonZeroBig<S>);
233forwards!(i32, NonZeroBig<S>);
234forwards!(i64, NonZeroBig<S>);
235forwards!(isize, NonZeroBig<S>);
236forwards!(NonZeroI8, NonZeroBig<S>);
237forwards!(NonZeroI16, NonZeroBig<S>);
238forwards!(NonZeroI32, NonZeroBig<S>);
239forwards!(NonZeroI64, NonZeroBig<S>);
240forwards!(NonZeroIsize, NonZeroBig<S>);
241
242macro_rules! impls {
243 ($ty:ty, $nzty:ty, $sty:ty, $nzsty:ty, $large:ty) => {
244 impl<const S: usize> AddAssign<$ty> for $large {
245 #[inline]
246 fn add_assign(&mut self, rhs: $ty) {
247 if rhs.is_not_zero() {
248 unsafe {
249 self.add_assign_single_int_non_zero(rhs as usize);
251 }
252 }
253 }
254 }
255
256 impl<const S: usize> AddAssign<$nzty> for $large {
257 #[inline]
258 fn add_assign(&mut self, rhs: $nzty) {
259 unsafe {
260 self.add_assign_single_int_non_zero(rhs.get() as usize);
262 }
263 }
264 }
265
266 impl<const S: usize> AddAssign<$sty> for $large {
267 #[inline]
268 fn add_assign(&mut self, rhs: $sty) {
269 match Signed::signum(&rhs) {
270 Sign::Positive => unsafe {
271 self.add_assign_single_int_non_zero(rhs as usize);
273 }
274 Sign::Zero => {}
275 Sign::Negative => unsafe {
276 self.sub_assign_single_int_non_zero(rhs.unsigned_abs() as usize);
278 }
279 }
280 }
281 }
282
283 impl<const S: usize> AddAssign<$nzsty> for $large {
284 #[inline]
285 fn add_assign(&mut self, rhs: $nzsty) {
286 match NonZeroSigned::non_zero_signum(&rhs) {
287 NonZeroSign::Positive => unsafe {
288 self.add_assign_single_int_non_zero(rhs.get() as usize);
290 }
291 NonZeroSign::Negative => unsafe {
292 self.sub_assign_single_int_non_zero(rhs.get().unsigned_abs() as usize);
294 }
295 }
296 }
297 }
298
299 impl<const S: usize> SubAssign<$ty> for $large {
300 #[inline]
301 fn sub_assign(&mut self, rhs: $ty) {
302 if rhs.is_not_zero() {
303 unsafe {
304 self.sub_assign_single_int_non_zero(rhs as usize);
306 }
307 }
308 }
309 }
310
311 impl<const S: usize> SubAssign<$nzty> for $large {
312 #[inline]
313 fn sub_assign(&mut self, rhs: $nzty) {
314 unsafe {
315 self.sub_assign_single_int_non_zero(rhs.get() as usize);
317 }
318 }
319 }
320
321 impl<const S: usize> SubAssign<$sty> for $large {
322 #[inline]
323 fn sub_assign(&mut self, rhs: $sty) {
324 match Signed::signum(&rhs) {
325 Sign::Positive => unsafe {
326 self.sub_assign_single_int_non_zero(rhs as usize);
328 }
329 Sign::Zero => {}
330 Sign::Negative => unsafe {
331 self.add_assign_single_int_non_zero(rhs.unsigned_abs() as usize);
333 }
334 }
335 }
336 }
337
338 impl<const S: usize> SubAssign<$nzsty> for $large {
339 #[inline]
340 fn sub_assign(&mut self, rhs: $nzsty) {
341 match NonZeroSigned::non_zero_signum(&rhs) {
342 NonZeroSign::Positive => unsafe {
343 self.sub_assign_single_int_non_zero(rhs.get() as usize);
345 }
346 NonZeroSign::Negative => unsafe {
347 self.add_assign_single_int_non_zero(rhs.get().unsigned_abs() as usize);
349 }
350 }
351 }
352 }
353
354 impl<const S: usize> MulAssign<$nzty> for $large {
355 #[inline]
356 fn mul_assign(&mut self, rhs: $nzty) {
357 if self.is_not_zero() {
358 unsafe {
359 mul_assign_single_int_non_zero(
361 self.numerator.inner_mut(),
362 self.denominator.inner_mut(),
363 rhs.get() as usize,
364 );
365 }
366 }
367 }
368 }
369
370 impl<const S: usize> MulAssign<$nzsty> for $large {
371 #[inline]
372 fn mul_assign(&mut self, rhs: $nzsty) {
373 if self.is_not_zero() {
374 unsafe {
375 mul_assign_single_int_non_zero(
377 self.numerator.inner_mut(),
378 self.denominator.inner_mut(),
379 rhs.get().unsigned_abs() as usize,
380 );
381 }
382
383 if rhs.is_negative() {
384 self.sign.negate();
385 }
386 }
387 }
388 }
389
390 impl<const S: usize> DivAssign<$ty> for $large {
391 #[inline]
392 fn div_assign(&mut self, rhs: $ty) {
393 if rhs.is_not_zero() {
394 if self.is_not_zero() {
395 unsafe {
396 mul_assign_single_int_non_zero(
398 self.denominator.inner_mut(),
399 self.numerator.inner_mut(),
400 rhs as usize,
401 );
402 }
403 }
404 } else {
405 panic!("attempt to divide by zero");
406 }
407 }
408 }
409
410 impl<const S: usize> DivAssign<$nzty> for $large {
411 #[inline]
412 fn div_assign(&mut self, rhs: $nzty) {
413 if self.is_not_zero() {
414 unsafe {
415 mul_assign_single_int_non_zero(
417 self.denominator.inner_mut(),
418 self.numerator.inner_mut(),
419 rhs.get() as usize,
420 );
421 }
422 }
423 }
424 }
425
426 impl<const S: usize> DivAssign<$sty> for $large {
427 #[inline]
428 fn div_assign(&mut self, rhs: $sty) {
429 if rhs.is_not_zero() {
430 if self.is_not_zero() {
431 unsafe {
432 mul_assign_single_int_non_zero(
434 self.denominator.inner_mut(),
435 self.numerator.inner_mut(),
436 rhs.unsigned_abs() as usize,
437 );
438 }
439
440 if rhs.is_negative() {
441 self.sign.negate();
442 }
443 }
444 } else {
445 panic!("attempt to divide by zero");
446 }
447 }
448 }
449
450 impl<const S: usize> DivAssign<$nzsty> for $large {
451 #[inline]
452 fn div_assign(&mut self, rhs: $nzsty) {
453 if self.is_not_zero() {
454 unsafe {
455 mul_assign_single_int_non_zero(
457 self.denominator.inner_mut(),
458 self.numerator.inner_mut(),
459 rhs.get().unsigned_abs() as usize,
460 );
461 }
462
463 if rhs.is_negative() {
464 self.sign.negate();
465 }
466 }
467 }
468 }
469 }
470}
471
472impls!(u8, NonZeroU8, i8, NonZeroI8, Big<S>);
473impls!(u16, NonZeroU16, i16, NonZeroI16, Big<S>);
474impls!(u32, NonZeroU32, i32, NonZeroI32, Big<S>);
475impls!(u64, NonZeroU64, i64, NonZeroI64, Big<S>);
476impls!(usize, NonZeroUsize, isize, NonZeroIsize, Big<S>);
477
478impls!(u8, NonZeroU8, i8, NonZeroI8, NonZeroBig<S>);
479impls!(u16, NonZeroU16, i16, NonZeroI16, NonZeroBig<S>);
480impls!(u32, NonZeroU32, i32, NonZeroI32, NonZeroBig<S>);
481impls!(u64, NonZeroU64, i64, NonZeroI64, NonZeroBig<S>);
482impls!(usize, NonZeroUsize, isize, NonZeroIsize, NonZeroBig<S>);
483
484macro_rules! impls_set_zero {
485 ($ty:ty, $sty:ty) => {
486 impl<const S: usize> MulAssign<$ty> for Big<S> {
487 #[inline]
488 fn mul_assign(&mut self, rhs: $ty) {
489 if self.is_not_zero() {
490 if rhs.is_not_zero() {
491 unsafe {
492 mul_assign_single_int_non_zero(
494 self.numerator.inner_mut(),
495 self.denominator.inner_mut(),
496 rhs as usize,
497 );
498 }
499 } else {
500 self.set_zero();
501 }
502 }
503 }
504 }
505
506 impl<const S: usize> MulAssign<$sty> for Big<S> {
507 #[inline]
508 fn mul_assign(&mut self, rhs: $sty) {
509 if self.is_not_zero() {
510 match Signed::signum(&rhs) {
511 Sign::Positive => unsafe {
512 mul_assign_single_int_non_zero(
514 self.numerator.inner_mut(),
515 self.denominator.inner_mut(),
516 rhs as usize,
517 );
518 }
519 Sign::Zero => self.set_zero(),
520 Sign::Negative => {
521 unsafe {
522 mul_assign_single_int_non_zero(
524 self.numerator.inner_mut(),
525 self.denominator.inner_mut(),
526 rhs.unsigned_abs() as usize,
527 );
528 }
529 self.sign.negate();
530 }
531 }
532 }
533 }
534 }
535 }
536}
537
538impls_set_zero!(u8, i8);
539impls_set_zero!(u16, i16);
540impls_set_zero!(u32, i32);
541impls_set_zero!(u64, i64);
542impls_set_zero!(usize, isize);
543
544macro_rules! impls_not_become_zero {
545 ($ty:ty, $sty:ty) => {
546 impl<const S: usize> MulAssign<$ty> for NonZeroBig<S> {
547 #[inline]
548 fn mul_assign(&mut self, rhs: $ty) {
549 if self.is_not_zero() {
550 if rhs.is_not_zero() {
551 unsafe {
552 mul_assign_single_int_non_zero(
554 self.numerator.inner_mut(),
555 self.denominator.inner_mut(),
556 rhs as usize,
557 );
558 }
559 } else {
560 panic!("attempt to multiply by zero");
561 }
562 }
563 }
564 }
565
566 impl<const S: usize> MulAssign<$sty> for NonZeroBig<S> {
567 #[inline]
568 fn mul_assign(&mut self, rhs: $sty) {
569 if self.is_not_zero() {
570 match Signed::signum(&rhs) {
571 Sign::Positive => unsafe {
572 mul_assign_single_int_non_zero(
574 self.numerator.inner_mut(),
575 self.denominator.inner_mut(),
576 rhs as usize,
577 );
578 }
579 Sign::Zero => panic!("attempt to multiply by zero"),
580 Sign::Negative => {
581 unsafe {
582 mul_assign_single_int_non_zero(
584 self.numerator.inner_mut(),
585 self.denominator.inner_mut(),
586 rhs.unsigned_abs() as usize,
587 );
588 }
589 self.sign.negate();
590 }
591 }
592 }
593 }
594 }
595 }
596}
597
598impls_not_become_zero!(u8, i8);
599impls_not_become_zero!(u16, i16);
600impls_not_become_zero!(u32, i32);
601impls_not_become_zero!(u64, i64);
602impls_not_become_zero!(usize, isize);
603
604impl<const S: usize> Big<S> {
605 #[inline]
606 unsafe fn add_assign_single_int_non_zero(&mut self, rhs: usize) {
607 debug_assert!(rhs.is_not_zero());
608
609 match self.sign {
610 Sign::Positive => {
611 let difference = unsafe { mul_non_zero::<S>(&self.denominator, &[rhs]) };
618 unsafe { add_assign(self.numerator.inner_mut(), &difference) }
623 },
624 Sign::Zero => {
625 unsafe { *self.numerator.inner_mut() = smallvec![rhs] };
629 self.sign = Sign::Positive;
630 debug_assert!(self.denominator.is_one());
631 }
632 Sign::Negative => {
633 let difference = unsafe { mul_non_zero::<S>(&self.denominator, &[rhs]) };
635 let ordering = unsafe { subtracting_cmp(self.numerator.inner_mut(), &difference) };
639
640 match ordering {
641 Ordering::Less => self.sign.negate(),
642 Ordering::Equal => self.set_zero(),
643 Ordering::Greater => {}
644 }
645 }
646 }
647 }
648
649 #[inline]
650 unsafe fn sub_assign_single_int_non_zero(&mut self, rhs: usize) {
651 debug_assert!(rhs.is_not_zero());
652
653 match self.sign {
654 Sign::Positive => {
655 let difference = unsafe { mul_non_zero::<S>(&self.denominator, &[rhs]) };
660 let ordering = unsafe { subtracting_cmp(self.numerator.inner_mut(), &difference) };
664
665 match ordering {
666 Ordering::Less => self.sign.negate(),
667 Ordering::Equal => self.set_zero(),
668 Ordering::Greater => {}
669 }
670 }
671 Sign::Zero => {
672 unsafe { *self.numerator.inner_mut() = smallvec![rhs] };
676 self.sign = Sign::Negative;
677 debug_assert!(self.denominator.is_one());
678 }
679 Sign::Negative => {
680 let difference = unsafe { mul_non_zero::<S>(&self.denominator, &[rhs]) };
685 unsafe { add_assign(self.numerator.inner_mut(), &difference) }
689 },
690 }
691 }
692}
693
694impl<const S: usize> NonZeroBig<S> {
695 #[inline]
696 unsafe fn add_assign_single_int_non_zero(&mut self, rhs: usize) {
697 debug_assert!(rhs.is_not_zero());
698
699 let difference = unsafe { mul_non_zero::<S>(&self.denominator, &[rhs]) };
704
705 match self.sign {
706 NonZeroSign::Positive => {
707 unsafe { add_assign(self.numerator.inner_mut(), &difference) }
711 },
712 NonZeroSign::Negative => {
713 let ordering = unsafe { subtracting_cmp(self.numerator.inner_mut(), &difference) };
718
719 match ordering {
720 Ordering::Less => self.sign.negate(),
721 Ordering::Equal => panic!("attempt to add resulting in zero"),
722 Ordering::Greater => {}
723 }
724 }
725 }
726 }
727
728 #[inline]
729 unsafe fn sub_assign_single_int_non_zero(&mut self, rhs: usize) {
730 debug_assert!(rhs.is_not_zero());
731
732 match self.sign {
733 NonZeroSign::Positive => {
734 let difference = unsafe { mul_non_zero::<S>(&self.denominator, &[rhs]) };
739 let ordering = unsafe { subtracting_cmp(self.numerator.inner_mut(), &difference) };
744
745 match ordering {
746 Ordering::Less => self.sign.negate(),
747 Ordering::Equal => panic!("attempt to subtract resulting in zero"),
748 Ordering::Greater => {}
749 }
750 }
751 NonZeroSign::Negative => {
752 let difference = unsafe { mul_non_zero::<S>(&self.denominator, &[rhs]) };
757 unsafe { add_assign(self.numerator.inner_mut(), &difference) }
761 },
762 }
763 }
764}
765
766#[inline]
767unsafe fn mul_assign_single_int_non_zero<const S: usize>(
768 numerator: &mut SmallVec<[usize; S]>,
769 denominator: &mut SmallVec<[usize; S]>,
770 mut rhs: usize,
771) {
772 debug_assert!(rhs.is_not_zero());
773 debug_assert!(is_well_formed_non_zero(numerator));
774 debug_assert!(is_well_formed_non_zero(denominator));
775
776 if !rhs.is_one() {
777 if !unsafe { is_one_non_zero(denominator) } {
779 rhs = unsafe { simplify_fraction_gcd_single(denominator, rhs) };
782 }
783 mul_assign_single_non_zero(numerator, rhs);
784 }
785}
786
787#[cfg(test)]
788mod test {
789 use num_traits::{One, Zero};
790
791 use crate::RB;
792 use crate::rational::big::NonZeroBig;
793
794 #[test]
795 fn add() {
796 assert_eq!(RB!(2, 3) + 2, RB!(8, 3));
797 assert_eq!(RB!(5, 6) + 7, RB!(7 * 6 + 5, 6));
798 assert_eq!(RB!(5, 6) - 7, RB!(-7 * 6 + 5, 6));
799 assert_eq!(RB!(5, 6) + -7_i32, RB!(-7 * 6 + 5, 6));
800 assert_eq!(RB!(-5, 6) + 7, RB!(7 * 6 - 5, 6));
801 assert_eq!(RB!(-5, 6) + (-7), -RB!(7 * 6 + 5, 6));
802 assert_eq!(RB!(-2, 3) + 2, RB!(4, 3));
803 assert_eq!(RB!(2, 3) + 0, RB!(2, 3));
804 assert_eq!(RB!(2, 3) - 2, RB!(-4, 3));
805 assert_eq!(RB!(0) - 1, RB!(-1));
806 assert_eq!(RB!(-2, 3) - 2, RB!(-8, 3));
807 }
808
809 #[test]
810 fn mul() {
811 assert_eq!(RB!(2, 3) * 2, RB!(4, 3));
812 assert_eq!(RB!(-2, 3) * 2, RB!(-4, 3));
813 assert_eq!(RB!(2, 3) * 0, RB!(0));
814 assert_eq!(RB!(2, 3) / 2, RB!(1, 3));
815 assert_eq!(RB!(-1) / 1, RB!(-1));
816 assert_eq!(RB!(-2, 3) / 2, RB!(-1, 3));
817 }
818
819 #[test]
820 #[should_panic]
821 #[allow(unused_must_use)]
822 fn mul_zero() {
823 NonZeroBig::<1>::one() * 0_i64;
824 }
825
826 #[test]
827 #[should_panic]
828 #[allow(unused_must_use)]
829 fn add_zero() {
830 NonZeroBig::<1>::one() - 1;
831 }
832
833 #[test]
836 fn add_single_int_cancelling_to_zero() {
837 let mut x = RB!(-5);
838 x += 5_u64;
839 assert!(x.is_zero());
840 assert_eq!(x, RB!(0));
841 assert_eq!(format!("{:?}", x), "0");
842
843 let mut y = RB!(5);
845 y += -5_i64;
846 assert!(y.is_zero());
847 assert_eq!(y, RB!(0));
848 assert_eq!(format!("{:?}", y), "0");
849 }
850
851 #[test]
853 fn sub_single_int_cancelling_to_zero() {
854 let mut x = RB!(5);
855 x -= 5_u64;
856 assert!(x.is_zero());
857 assert_eq!(x, RB!(0));
858 assert_eq!(format!("{:?}", x), "0");
859
860 let mut y = RB!(-5);
861 y -= -5_i64;
862 assert!(y.is_zero());
863 assert_eq!(y, RB!(0));
864 assert_eq!(format!("{:?}", y), "0");
865 }
866
867 #[test]
869 fn add_single_int_to_zero_sets_sign() {
870 let mut x = RB!(0);
871 x += 1_u64;
872 assert!(!x.is_zero());
873 assert_eq!(x, RB!(1));
874 assert_eq!(format!("{:?}", x), "1");
875
876 let mut y = RB!(0);
877 y -= -7_i64;
878 assert!(!y.is_zero());
879 assert_eq!(y, RB!(7));
880 assert_eq!(format!("{:?}", y), "7");
881 }
882}