ibig/
add_ops.rs

1//! Addition and subtraction operators.
2
3use crate::{
4    add,
5    arch::word::Word,
6    buffer::Buffer,
7    helper_macros,
8    ibig::IBig,
9    primitive::{PrimitiveSigned, PrimitiveUnsigned},
10    sign::Sign::*,
11    ubig::{Repr::*, UBig},
12};
13use core::{
14    mem,
15    ops::{Add, AddAssign, Sub, SubAssign},
16};
17
18impl Add<UBig> for UBig {
19    type Output = UBig;
20
21    #[inline]
22    fn add(self, rhs: UBig) -> UBig {
23        match (self.into_repr(), rhs.into_repr()) {
24            (Small(word0), Small(word1)) => UBig::add_word(word0, word1),
25            (Small(word0), Large(buffer1)) => UBig::add_large_word(buffer1, word0),
26            (Large(buffer0), Small(word1)) => UBig::add_large_word(buffer0, word1),
27            (Large(buffer0), Large(buffer1)) => {
28                if buffer0.len() >= buffer1.len() {
29                    UBig::add_large(buffer0, &buffer1)
30                } else {
31                    UBig::add_large(buffer1, &buffer0)
32                }
33            }
34        }
35    }
36}
37
38impl Add<&UBig> for UBig {
39    type Output = UBig;
40
41    #[inline]
42    fn add(self, rhs: &UBig) -> UBig {
43        match (self.into_repr(), rhs.repr()) {
44            (Small(word0), Small(word1)) => UBig::add_word(word0, *word1),
45            (Small(word0), Large(buffer1)) => UBig::add_large_word(buffer1.clone(), word0),
46            (Large(buffer0), Small(word1)) => UBig::add_large_word(buffer0, *word1),
47            (Large(buffer0), Large(buffer1)) => UBig::add_large(buffer0, buffer1),
48        }
49    }
50}
51
52impl Add<UBig> for &UBig {
53    type Output = UBig;
54
55    #[inline]
56    fn add(self, rhs: UBig) -> UBig {
57        rhs.add(self)
58    }
59}
60
61impl Add<&UBig> for &UBig {
62    type Output = UBig;
63
64    #[inline]
65    fn add(self, rhs: &UBig) -> UBig {
66        match (self.repr(), rhs.repr()) {
67            (Small(word0), Small(word1)) => UBig::add_word(*word0, *word1),
68            (Small(word0), Large(buffer1)) => UBig::add_large_word(buffer1.clone(), *word0),
69            (Large(buffer0), Small(word1)) => UBig::add_large_word(buffer0.clone(), *word1),
70            (Large(buffer0), Large(buffer1)) => {
71                if buffer0.len() >= buffer1.len() {
72                    UBig::add_large(buffer0.clone(), buffer1)
73                } else {
74                    UBig::add_large(buffer1.clone(), buffer0)
75                }
76            }
77        }
78    }
79}
80
81impl AddAssign<UBig> for UBig {
82    #[inline]
83    fn add_assign(&mut self, rhs: UBig) {
84        *self = mem::take(self) + rhs;
85    }
86}
87
88impl AddAssign<&UBig> for UBig {
89    #[inline]
90    fn add_assign(&mut self, rhs: &UBig) {
91        *self = mem::take(self) + rhs;
92    }
93}
94
95impl Sub<UBig> for UBig {
96    type Output = UBig;
97
98    #[inline]
99    fn sub(self, rhs: UBig) -> UBig {
100        match (self.into_repr(), rhs.into_repr()) {
101            (Small(word0), Small(word1)) => UBig::sub_word(word0, word1),
102            (Small(_), Large(_)) => UBig::panic_negative(),
103            (Large(buffer0), Small(word1)) => UBig::sub_large_word(buffer0, word1),
104            (Large(buffer0), Large(buffer1)) => UBig::sub_large(buffer0, &buffer1),
105        }
106    }
107}
108
109impl Sub<&UBig> for UBig {
110    type Output = UBig;
111
112    #[inline]
113    fn sub(self, rhs: &UBig) -> UBig {
114        match (self.into_repr(), rhs.repr()) {
115            (Small(word0), Small(word1)) => UBig::sub_word(word0, *word1),
116            (Small(_), Large(_)) => UBig::panic_negative(),
117            (Large(buffer0), Small(word1)) => UBig::sub_large_word(buffer0, *word1),
118            (Large(buffer0), Large(buffer1)) => UBig::sub_large(buffer0, buffer1),
119        }
120    }
121}
122
123impl Sub<UBig> for &UBig {
124    type Output = UBig;
125
126    #[inline]
127    fn sub(self, rhs: UBig) -> UBig {
128        match (self.repr(), rhs.into_repr()) {
129            (Small(word0), Small(word1)) => UBig::sub_word(*word0, word1),
130            (Small(_), Large(_)) => UBig::panic_negative(),
131            (Large(buffer0), Small(word1)) => UBig::sub_large_word(buffer0.clone(), word1),
132            (Large(buffer0), Large(buffer1)) => UBig::sub_large_ref_val(buffer0, buffer1),
133        }
134    }
135}
136
137impl Sub<&UBig> for &UBig {
138    type Output = UBig;
139
140    #[inline]
141    fn sub(self, rhs: &UBig) -> UBig {
142        match (self.repr(), rhs.repr()) {
143            (Small(word0), Small(word1)) => UBig::sub_word(*word0, *word1),
144            (Small(_), Large(_)) => UBig::panic_negative(),
145            (Large(buffer0), Small(word1)) => UBig::sub_large_word(buffer0.clone(), *word1),
146            (Large(buffer0), Large(buffer1)) => UBig::sub_large(buffer0.clone(), buffer1),
147        }
148    }
149}
150
151impl SubAssign<UBig> for UBig {
152    #[inline]
153    fn sub_assign(&mut self, rhs: UBig) {
154        *self = mem::take(self) - rhs;
155    }
156}
157
158impl SubAssign<&UBig> for UBig {
159    #[inline]
160    fn sub_assign(&mut self, rhs: &UBig) {
161        *self = mem::take(self) - rhs;
162    }
163}
164
165impl Add<IBig> for IBig {
166    type Output = IBig;
167
168    #[inline]
169    fn add(self, rhs: IBig) -> IBig {
170        let (sign0, mag0) = self.into_sign_magnitude();
171        let (sign1, mag1) = rhs.into_sign_magnitude();
172        match (sign0, sign1) {
173            (Positive, Positive) => IBig::from(mag0 + mag1),
174            (Positive, Negative) => IBig::sub_ubig_val_val(mag0, mag1),
175            (Negative, Positive) => IBig::sub_ubig_val_val(mag1, mag0),
176            (Negative, Negative) => -IBig::from(mag0 + mag1),
177        }
178    }
179}
180
181impl Add<&IBig> for IBig {
182    type Output = IBig;
183
184    #[inline]
185    fn add(self, rhs: &IBig) -> IBig {
186        let (sign0, mag0) = self.into_sign_magnitude();
187        let (sign1, mag1) = (rhs.sign(), rhs.magnitude());
188        match (sign0, sign1) {
189            (Positive, Positive) => IBig::from(mag0 + mag1),
190            (Positive, Negative) => IBig::sub_ubig_val_ref(mag0, mag1),
191            (Negative, Positive) => -IBig::sub_ubig_val_ref(mag0, mag1),
192            (Negative, Negative) => -IBig::from(mag0 + mag1),
193        }
194    }
195}
196
197impl Add<IBig> for &IBig {
198    type Output = IBig;
199
200    #[inline]
201    fn add(self, rhs: IBig) -> IBig {
202        rhs.add(self)
203    }
204}
205
206impl Add<&IBig> for &IBig {
207    type Output = IBig;
208
209    #[inline]
210    fn add(self, rhs: &IBig) -> IBig {
211        let (sign0, mag0) = (self.sign(), self.magnitude());
212        let (sign1, mag1) = (rhs.sign(), rhs.magnitude());
213        match (sign0, sign1) {
214            (Positive, Positive) => IBig::from(mag0 + mag1),
215            (Positive, Negative) => IBig::sub_ubig_ref_ref(mag0, mag1),
216            (Negative, Positive) => IBig::sub_ubig_ref_ref(mag1, mag0),
217            (Negative, Negative) => -IBig::from(mag0 + mag1),
218        }
219    }
220}
221
222impl AddAssign<IBig> for IBig {
223    #[inline]
224    fn add_assign(&mut self, rhs: IBig) {
225        *self = mem::take(self) + rhs;
226    }
227}
228
229impl AddAssign<&IBig> for IBig {
230    #[inline]
231    fn add_assign(&mut self, rhs: &IBig) {
232        *self = mem::take(self) + rhs;
233    }
234}
235
236impl Sub<IBig> for IBig {
237    type Output = IBig;
238
239    #[inline]
240    fn sub(self, rhs: IBig) -> IBig {
241        self + -rhs
242    }
243}
244
245impl Sub<&IBig> for IBig {
246    type Output = IBig;
247
248    #[inline]
249    fn sub(self, rhs: &IBig) -> IBig {
250        -(-self + rhs)
251    }
252}
253
254impl Sub<IBig> for &IBig {
255    type Output = IBig;
256
257    #[inline]
258    fn sub(self, rhs: IBig) -> IBig {
259        self + -rhs
260    }
261}
262
263impl Sub<&IBig> for &IBig {
264    type Output = IBig;
265
266    #[inline]
267    fn sub(self, rhs: &IBig) -> IBig {
268        let (sign0, mag0) = (self.sign(), self.magnitude());
269        let (sign1, mag1) = (rhs.sign(), rhs.magnitude());
270        match (sign0, sign1) {
271            (Positive, Positive) => IBig::sub_ubig_ref_ref(mag0, mag1),
272            (Positive, Negative) => IBig::from(mag0 + mag1),
273            (Negative, Positive) => -IBig::from(mag0 + mag1),
274            (Negative, Negative) => IBig::sub_ubig_ref_ref(mag1, mag0),
275        }
276    }
277}
278
279impl SubAssign<IBig> for IBig {
280    #[inline]
281    fn sub_assign(&mut self, rhs: IBig) {
282        *self = mem::take(self) - rhs;
283    }
284}
285
286impl SubAssign<&IBig> for IBig {
287    #[inline]
288    fn sub_assign(&mut self, rhs: &IBig) {
289        *self = mem::take(self) - rhs;
290    }
291}
292
293macro_rules! impl_add_ubig_unsigned {
294    ($t:ty) => {
295        impl Add<$t> for UBig {
296            type Output = UBig;
297
298            #[inline]
299            fn add(self, rhs: $t) -> UBig {
300                self.add_unsigned(rhs)
301            }
302        }
303
304        impl Add<$t> for &UBig {
305            type Output = UBig;
306
307            #[inline]
308            fn add(self, rhs: $t) -> UBig {
309                self.add_ref_unsigned(rhs)
310            }
311        }
312
313        helper_macros::forward_binop_second_arg_by_value!(impl Add<$t> for UBig, add);
314        helper_macros::forward_binop_swap_args!(impl Add<UBig> for $t, add);
315
316        impl AddAssign<$t> for UBig {
317            #[inline]
318            fn add_assign(&mut self, rhs: $t) {
319                self.add_assign_unsigned(rhs)
320            }
321        }
322
323        helper_macros::forward_binop_assign_arg_by_value!(impl AddAssign<$t> for UBig, add_assign);
324
325        impl Sub<$t> for UBig {
326            type Output = UBig;
327
328            #[inline]
329            fn sub(self, rhs: $t) -> UBig {
330                self.sub_unsigned(rhs)
331            }
332        }
333
334        impl Sub<$t> for &UBig {
335            type Output = UBig;
336
337            #[inline]
338            fn sub(self, rhs: $t) -> UBig {
339                self.sub_ref_unsigned(rhs)
340            }
341        }
342
343        helper_macros::forward_binop_second_arg_by_value!(impl Sub<$t> for UBig, sub);
344
345        impl SubAssign<$t> for UBig {
346            #[inline]
347            fn sub_assign(&mut self, rhs: $t) {
348                self.sub_assign_unsigned(rhs)
349            }
350        }
351
352        helper_macros::forward_binop_assign_arg_by_value!(impl SubAssign<$t> for UBig, sub_assign);
353    };
354}
355
356impl_add_ubig_unsigned!(u8);
357impl_add_ubig_unsigned!(u16);
358impl_add_ubig_unsigned!(u32);
359impl_add_ubig_unsigned!(u64);
360impl_add_ubig_unsigned!(u128);
361impl_add_ubig_unsigned!(usize);
362
363macro_rules! impl_add_ubig_signed {
364    ($t:ty) => {
365        impl Add<$t> for UBig {
366            type Output = UBig;
367
368            #[inline]
369            fn add(self, rhs: $t) -> UBig {
370                self.add_signed(rhs)
371            }
372        }
373
374        impl Add<$t> for &UBig {
375            type Output = UBig;
376
377            #[inline]
378            fn add(self, rhs: $t) -> UBig {
379                self.add_ref_signed(rhs)
380            }
381        }
382
383        helper_macros::forward_binop_second_arg_by_value!(impl Add<$t> for UBig, add);
384        helper_macros::forward_binop_swap_args!(impl Add<UBig> for $t, add);
385
386        impl AddAssign<$t> for UBig {
387            #[inline]
388            fn add_assign(&mut self, rhs: $t) {
389                self.add_assign_signed(rhs)
390            }
391        }
392
393        helper_macros::forward_binop_assign_arg_by_value!(impl AddAssign<$t> for UBig, add_assign);
394
395        impl Sub<$t> for UBig {
396            type Output = UBig;
397
398            #[inline]
399            fn sub(self, rhs: $t) -> UBig {
400                self.sub_signed(rhs)
401            }
402        }
403
404        impl Sub<$t> for &UBig {
405            type Output = UBig;
406
407            #[inline]
408            fn sub(self, rhs: $t) -> UBig {
409                self.sub_ref_signed(rhs)
410            }
411        }
412
413        helper_macros::forward_binop_second_arg_by_value!(impl Sub<$t> for UBig, sub);
414
415        impl SubAssign<$t> for UBig {
416            #[inline]
417            fn sub_assign(&mut self, rhs: $t) {
418                self.sub_assign_signed(rhs)
419            }
420        }
421
422        helper_macros::forward_binop_assign_arg_by_value!(impl SubAssign<$t> for UBig, sub_assign);
423    };
424}
425
426impl_add_ubig_signed!(i8);
427impl_add_ubig_signed!(i16);
428impl_add_ubig_signed!(i32);
429impl_add_ubig_signed!(i64);
430impl_add_ubig_signed!(i128);
431impl_add_ubig_signed!(isize);
432
433macro_rules! impl_add_ibig_primitive {
434    ($t:ty) => {
435        impl Add<$t> for IBig {
436            type Output = IBig;
437
438            #[inline]
439            fn add(self, rhs: $t) -> IBig {
440                self.add_primitive(rhs)
441            }
442        }
443
444        impl Add<$t> for &IBig {
445            type Output = IBig;
446
447            #[inline]
448            fn add(self, rhs: $t) -> IBig {
449                self.add_ref_primitive(rhs)
450            }
451        }
452
453        helper_macros::forward_binop_second_arg_by_value!(impl Add<$t> for IBig, add);
454        helper_macros::forward_binop_swap_args!(impl Add<IBig> for $t, add);
455
456        impl AddAssign<$t> for IBig {
457            #[inline]
458            fn add_assign(&mut self, rhs: $t) {
459                self.add_assign_primitive(rhs)
460            }
461        }
462
463        helper_macros::forward_binop_assign_arg_by_value!(impl AddAssign<$t> for IBig, add_assign);
464
465        impl Sub<$t> for IBig {
466            type Output = IBig;
467
468            #[inline]
469            fn sub(self, rhs: $t) -> IBig {
470                self.sub_primitive(rhs)
471            }
472        }
473
474        impl Sub<$t> for &IBig {
475            type Output = IBig;
476
477            #[inline]
478            fn sub(self, rhs: $t) -> IBig {
479                self.sub_ref_primitive(rhs)
480            }
481        }
482
483        impl Sub<IBig> for $t {
484            type Output = IBig;
485
486            #[inline]
487            fn sub(self, rhs: IBig) -> IBig {
488                rhs.sub_from_primitive(self)
489            }
490        }
491
492        impl Sub<&IBig> for $t {
493            type Output = IBig;
494
495            #[inline]
496            fn sub(self, rhs: &IBig) -> IBig {
497                rhs.sub_ref_from_primitive(self)
498            }
499        }
500
501        helper_macros::forward_binop_second_arg_by_value!(impl Sub<$t> for IBig, sub);
502        helper_macros::forward_binop_first_arg_by_value!(impl Sub<IBig> for $t, sub);
503
504        impl SubAssign<$t> for IBig {
505            #[inline]
506            fn sub_assign(&mut self, rhs: $t) {
507                self.sub_assign_primitive(rhs)
508            }
509        }
510
511        helper_macros::forward_binop_assign_arg_by_value!(impl SubAssign<$t> for IBig, sub_assign);
512    };
513}
514
515impl_add_ibig_primitive!(u8);
516impl_add_ibig_primitive!(u16);
517impl_add_ibig_primitive!(u32);
518impl_add_ibig_primitive!(u64);
519impl_add_ibig_primitive!(u128);
520impl_add_ibig_primitive!(usize);
521impl_add_ibig_primitive!(i8);
522impl_add_ibig_primitive!(i16);
523impl_add_ibig_primitive!(i32);
524impl_add_ibig_primitive!(i64);
525impl_add_ibig_primitive!(i128);
526impl_add_ibig_primitive!(isize);
527
528impl UBig {
529    /// Add two `Word`s.
530    #[inline]
531    fn add_word(a: Word, b: Word) -> UBig {
532        let (res, overflow) = a.overflowing_add(b);
533        if overflow {
534            let mut buffer = Buffer::allocate(2);
535            buffer.push(res);
536            buffer.push(1);
537            buffer.into()
538        } else {
539            UBig::from_word(res)
540        }
541    }
542
543    /// Add a large number to a `Word`.
544    fn add_large_word(mut buffer: Buffer, rhs: Word) -> UBig {
545        debug_assert!(buffer.len() >= 2);
546        if add::add_word_in_place(&mut buffer, rhs) {
547            buffer.push_may_reallocate(1);
548        }
549        buffer.into()
550    }
551
552    /// Add two large numbers.
553    fn add_large(mut buffer: Buffer, rhs: &[Word]) -> UBig {
554        let n = buffer.len().min(rhs.len());
555        let overflow = add::add_same_len_in_place(&mut buffer[..n], &rhs[..n]);
556        if rhs.len() > n {
557            buffer.ensure_capacity(rhs.len());
558            buffer.extend(&rhs[n..]);
559        }
560        if overflow && add::add_one_in_place(&mut buffer[n..]) {
561            buffer.push_may_reallocate(1);
562        }
563        buffer.into()
564    }
565
566    /// Subtract two `Word`s.
567    #[inline]
568    fn sub_word(a: Word, b: Word) -> UBig {
569        match a.checked_sub(b) {
570            Some(res) => UBig::from_word(res),
571            None => UBig::panic_negative(),
572        }
573    }
574
575    fn sub_large_word(mut lhs: Buffer, rhs: Word) -> UBig {
576        let overflow = add::sub_word_in_place(&mut lhs, rhs);
577        assert!(!overflow);
578        lhs.into()
579    }
580
581    fn sub_large(mut lhs: Buffer, rhs: &[Word]) -> UBig {
582        if lhs.len() < rhs.len() || add::sub_in_place(&mut lhs, rhs) {
583            UBig::panic_negative();
584        }
585        lhs.into()
586    }
587
588    fn sub_large_ref_val(lhs: &[Word], mut rhs: Buffer) -> UBig {
589        let n = rhs.len();
590        if lhs.len() < n {
591            UBig::panic_negative();
592        }
593        let borrow = add::sub_same_len_in_place_swap(&lhs[..n], &mut rhs);
594        rhs.ensure_capacity(lhs.len());
595        rhs.extend(&lhs[n..]);
596        if borrow && add::sub_one_in_place(&mut rhs[n..]) {
597            UBig::panic_negative();
598        }
599        rhs.into()
600    }
601
602    #[inline]
603    fn add_unsigned<T: PrimitiveUnsigned>(self, rhs: T) -> UBig {
604        self + UBig::from_unsigned(rhs)
605    }
606
607    #[inline]
608    fn add_ref_unsigned<T: PrimitiveUnsigned>(&self, rhs: T) -> UBig {
609        self + UBig::from_unsigned(rhs)
610    }
611
612    #[inline]
613    fn add_assign_unsigned<T: PrimitiveUnsigned>(&mut self, rhs: T) {
614        *self += UBig::from_unsigned(rhs)
615    }
616
617    #[inline]
618    fn sub_unsigned<T: PrimitiveUnsigned>(self, rhs: T) -> UBig {
619        self - UBig::from_unsigned(rhs)
620    }
621
622    #[inline]
623    fn sub_ref_unsigned<T: PrimitiveUnsigned>(&self, rhs: T) -> UBig {
624        self - UBig::from_unsigned(rhs)
625    }
626
627    #[inline]
628    fn sub_assign_unsigned<T: PrimitiveUnsigned>(&mut self, rhs: T) {
629        *self -= UBig::from_unsigned(rhs)
630    }
631
632    #[inline]
633    fn add_signed<T: PrimitiveSigned>(self, rhs: T) -> UBig {
634        UBig::from_ibig_panic_on_overflow(IBig::from(self) + IBig::from_signed(rhs))
635    }
636
637    #[inline]
638    fn add_ref_signed<T: PrimitiveSigned>(&self, rhs: T) -> UBig {
639        UBig::from_ibig_panic_on_overflow(IBig::from(self) + IBig::from_signed(rhs))
640    }
641
642    #[inline]
643    fn add_assign_signed<T: PrimitiveSigned>(&mut self, rhs: T) {
644        *self = mem::take(self).add_signed(rhs)
645    }
646
647    #[inline]
648    fn sub_signed<T: PrimitiveSigned>(self, rhs: T) -> UBig {
649        UBig::from_ibig_panic_on_overflow(IBig::from(self) - IBig::from_signed(rhs))
650    }
651
652    #[inline]
653    fn sub_ref_signed<T: PrimitiveSigned>(&self, rhs: T) -> UBig {
654        UBig::from_ibig_panic_on_overflow(IBig::from(self) - IBig::from_signed(rhs))
655    }
656
657    #[inline]
658    fn sub_assign_signed<T: PrimitiveSigned>(&mut self, rhs: T) {
659        *self = mem::take(self).sub_signed(rhs)
660    }
661}
662
663impl IBig {
664    #[inline]
665    fn sub_ubig_val_val(lhs: UBig, rhs: UBig) -> IBig {
666        match (lhs.into_repr(), rhs.into_repr()) {
667            (Small(word0), Small(word1)) => IBig::sub_word_word(word0, word1),
668            (Small(word0), Large(buffer1)) => -IBig::sub_large_word(buffer1, word0),
669            (Large(buffer0), Small(word1)) => IBig::sub_large_word(buffer0, word1),
670            (Large(buffer0), Large(buffer1)) => {
671                if buffer0.len() >= buffer1.len() {
672                    IBig::sub_large(buffer0, &buffer1)
673                } else {
674                    -IBig::sub_large(buffer1, &buffer0)
675                }
676            }
677        }
678    }
679
680    #[inline]
681    fn sub_ubig_val_ref(lhs: UBig, rhs: &UBig) -> IBig {
682        match (lhs.into_repr(), rhs.repr()) {
683            (Small(word0), Small(word1)) => IBig::sub_word_word(word0, *word1),
684            (Small(word0), Large(buffer1)) => -IBig::sub_large_word(buffer1.clone(), word0),
685            (Large(buffer0), Small(word1)) => IBig::sub_large_word(buffer0, *word1),
686            (Large(buffer0), Large(buffer1)) => IBig::sub_large(buffer0, buffer1),
687        }
688    }
689
690    #[inline]
691    fn sub_ubig_ref_ref(lhs: &UBig, rhs: &UBig) -> IBig {
692        match (lhs.repr(), rhs.repr()) {
693            (Small(word0), Small(word1)) => IBig::sub_word_word(*word0, *word1),
694            (Small(word0), Large(buffer1)) => -IBig::sub_large_word(buffer1.clone(), *word0),
695            (Large(buffer0), Small(word1)) => IBig::sub_large_word(buffer0.clone(), *word1),
696            (Large(buffer0), Large(buffer1)) => {
697                if buffer0.len() >= buffer1.len() {
698                    IBig::sub_large(buffer0.clone(), buffer1)
699                } else {
700                    -IBig::sub_large(buffer1.clone(), buffer0)
701                }
702            }
703        }
704    }
705
706    #[inline]
707    fn sub_word_word(lhs: Word, rhs: Word) -> IBig {
708        let (val, overflow) = lhs.overflowing_sub(rhs);
709        if !overflow {
710            IBig::from(val)
711        } else {
712            -IBig::from(val.wrapping_neg())
713        }
714    }
715
716    fn sub_large_word(lhs: Buffer, rhs: Word) -> IBig {
717        UBig::sub_large_word(lhs, rhs).into()
718    }
719
720    fn sub_large(mut lhs: Buffer, rhs: &[Word]) -> IBig {
721        if lhs.len() >= rhs.len() {
722            let sign = add::sub_in_place_with_sign(&mut lhs, rhs);
723            IBig::from_sign_magnitude(sign, lhs.into())
724        } else {
725            let res = UBig::sub_large_ref_val(rhs, lhs);
726            IBig::from_sign_magnitude(Negative, res)
727        }
728    }
729
730    #[inline]
731    fn add_primitive<T>(self, rhs: T) -> IBig
732    where
733        IBig: From<T>,
734    {
735        self + IBig::from(rhs)
736    }
737
738    #[inline]
739    fn add_ref_primitive<T>(&self, rhs: T) -> IBig
740    where
741        IBig: From<T>,
742    {
743        self + IBig::from(rhs)
744    }
745
746    #[inline]
747    fn add_assign_primitive<T>(&mut self, rhs: T)
748    where
749        IBig: From<T>,
750    {
751        *self += IBig::from(rhs)
752    }
753
754    #[inline]
755    fn sub_primitive<T>(self, rhs: T) -> IBig
756    where
757        IBig: From<T>,
758    {
759        self - IBig::from(rhs)
760    }
761
762    #[inline]
763    fn sub_ref_primitive<T>(&self, rhs: T) -> IBig
764    where
765        IBig: From<T>,
766    {
767        self - IBig::from(rhs)
768    }
769
770    #[inline]
771    fn sub_assign_primitive<T>(&mut self, rhs: T)
772    where
773        IBig: From<T>,
774    {
775        *self -= IBig::from(rhs)
776    }
777
778    #[inline]
779    fn sub_from_primitive<T>(self, rhs: T) -> IBig
780    where
781        IBig: From<T>,
782    {
783        IBig::from(rhs) - self
784    }
785
786    #[inline]
787    fn sub_ref_from_primitive<T>(&self, rhs: T) -> IBig
788    where
789        IBig: From<T>,
790    {
791        IBig::from(rhs) - self
792    }
793}