Skip to main content

thruput_u256/
signed_arith.rs

1//! [`I256`] arithmetic: operators, and the `checked_`/`wrapping_`/
2//! `overflowing_`/`saturating_` families behind them.
3//!
4//! Two's complement does most of the work. Addition, subtraction,
5//! multiplication and every bitwise operation produce the same 256 bits
6//! whether the operands are read as signed or unsigned, so those route
7//! straight to [`U256`] and only the *overflow test* is signed. What is
8//! genuinely different lives here: sign-aware division, the arithmetic right
9//! shift, and negation.
10//!
11//! Overflow behaves as it does on the unsigned side and as it does for the
12//! primitives -- wrap when `overflow-checks` is off, panic when it is on, with
13//! every guard folding away in a release contract build. `MIN` is the one
14//! value with no negation, which makes `-MIN`, `MIN.abs()` and `MIN / -1`
15//! overflow.
16
17use crate::arith::OVERFLOW_CHECKS;
18use crate::{I256, U256};
19use core::ops::{
20    Add, AddAssign, BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor,
21    BitXorAssign, Div, DivAssign, Mul, MulAssign, Neg, Not, Rem, RemAssign,
22    Shl, ShlAssign, Shr, ShrAssign, Sub, SubAssign,
23};
24
25impl I256 {
26    // -----------------------------------------------------------------------
27    // Negation and absolute value
28    // -----------------------------------------------------------------------
29
30    /// Negation, with a flag reporting whether it overflowed.
31    ///
32    /// Only [`MIN`](Self::MIN) overflows: its magnitude has no positive
33    /// counterpart, and it negates to itself.
34    #[inline]
35    pub const fn overflowing_neg(self) -> (Self, bool) {
36        (
37            self.cast_unsigned().wrapping_neg().cast_signed(),
38            self.const_eq(Self::MIN),
39        )
40    }
41
42    /// Negation, returning `None` on overflow.
43    #[inline]
44    pub const fn checked_neg(self) -> Option<Self> {
45        match self.overflowing_neg() {
46            (v, false) => Some(v),
47            (_, true) => None,
48        }
49    }
50
51    /// Negation, wrapping on overflow (`MIN` negates to itself).
52    #[inline]
53    pub const fn wrapping_neg(self) -> Self {
54        self.overflowing_neg().0
55    }
56
57    /// Negation, saturating at [`MAX`](Self::MAX).
58    #[inline]
59    pub const fn saturating_neg(self) -> Self {
60        match self.overflowing_neg() {
61            (v, false) => v,
62            (_, true) => Self::MAX,
63        }
64    }
65
66    /// Absolute value, with a flag reporting whether it overflowed.
67    #[inline]
68    pub const fn overflowing_abs(self) -> (Self, bool) {
69        if self.is_negative() {
70            self.overflowing_neg()
71        } else {
72            (self, false)
73        }
74    }
75
76    /// Absolute value, returning `None` on overflow.
77    #[inline]
78    pub const fn checked_abs(self) -> Option<Self> {
79        match self.overflowing_abs() {
80            (v, false) => Some(v),
81            (_, true) => None,
82        }
83    }
84
85    /// Absolute value, wrapping on overflow (`MIN` maps to itself).
86    #[inline]
87    pub const fn wrapping_abs(self) -> Self {
88        self.overflowing_abs().0
89    }
90
91    /// Absolute value, saturating at [`MAX`](Self::MAX).
92    #[inline]
93    pub const fn saturating_abs(self) -> Self {
94        match self.overflowing_abs() {
95            (v, false) => v,
96            (_, true) => Self::MAX,
97        }
98    }
99
100    /// Absolute value.
101    ///
102    /// See [`unsigned_abs`](Self::unsigned_abs) for the total version: `MIN`
103    /// has no representable absolute value here.
104    ///
105    /// # Panics
106    ///
107    /// On `MIN`, if `overflow-checks` is on -- otherwise it wraps to `MIN`,
108    /// like the primitives.
109    #[inline]
110    pub const fn abs(self) -> Self {
111        let (v, overflow) = self.overflowing_abs();
112        if OVERFLOW_CHECKS && overflow {
113            panic!("attempt to negate with overflow");
114        }
115        v
116    }
117
118    // -----------------------------------------------------------------------
119    // Addition and subtraction
120    // -----------------------------------------------------------------------
121
122    /// Wrapping addition, with a flag reporting whether it overflowed.
123    #[inline]
124    pub const fn overflowing_add(self, rhs: Self) -> (Self, bool) {
125        let v = self
126            .cast_unsigned()
127            .wrapping_add(rhs.cast_unsigned())
128            .cast_signed();
129        // Signed overflow is exactly: two operands of the same sign producing
130        // a result of the other one.
131        let overflow = self.is_negative() == rhs.is_negative()
132            && v.is_negative() != self.is_negative();
133        (v, overflow)
134    }
135
136    /// Wrapping subtraction, with a flag reporting whether it overflowed.
137    #[inline]
138    pub const fn overflowing_sub(self, rhs: Self) -> (Self, bool) {
139        let v = self
140            .cast_unsigned()
141            .wrapping_sub(rhs.cast_unsigned())
142            .cast_signed();
143        // Mirror image: operands of opposite signs, result taking the
144        // subtrahend's.
145        let overflow = self.is_negative() != rhs.is_negative()
146            && v.is_negative() != self.is_negative();
147        (v, overflow)
148    }
149
150    /// Addition, returning `None` on overflow.
151    #[inline]
152    pub const fn checked_add(self, rhs: Self) -> Option<Self> {
153        match self.overflowing_add(rhs) {
154            (v, false) => Some(v),
155            (_, true) => None,
156        }
157    }
158
159    /// Subtraction, returning `None` on overflow.
160    #[inline]
161    pub const fn checked_sub(self, rhs: Self) -> Option<Self> {
162        match self.overflowing_sub(rhs) {
163            (v, false) => Some(v),
164            (_, true) => None,
165        }
166    }
167
168    /// Addition, wrapping on overflow.
169    #[inline]
170    pub const fn wrapping_add(self, rhs: Self) -> Self {
171        self.overflowing_add(rhs).0
172    }
173
174    /// Subtraction, wrapping on overflow.
175    #[inline]
176    pub const fn wrapping_sub(self, rhs: Self) -> Self {
177        self.overflowing_sub(rhs).0
178    }
179
180    /// Addition, saturating at [`MIN`](Self::MIN) or [`MAX`](Self::MAX).
181    #[inline]
182    pub const fn saturating_add(self, rhs: Self) -> Self {
183        match self.overflowing_add(rhs) {
184            (v, false) => v,
185            // Same-sign operands are what overflowed, so the direction is
186            // whichever sign they shared.
187            (_, true) => self.saturation_bound(),
188        }
189    }
190
191    /// Subtraction, saturating at [`MIN`](Self::MIN) or [`MAX`](Self::MAX).
192    #[inline]
193    pub const fn saturating_sub(self, rhs: Self) -> Self {
194        match self.overflowing_sub(rhs) {
195            (v, false) => v,
196            (_, true) => self.saturation_bound(),
197        }
198    }
199
200    /// The bound an overflow away from `self` saturates to: an overflow can
201    /// only ever leave the range on `self`'s own side of zero.
202    #[inline]
203    const fn saturation_bound(self) -> Self {
204        if self.is_negative() {
205            Self::MIN
206        } else {
207            Self::MAX
208        }
209    }
210
211    // -----------------------------------------------------------------------
212    // Multiplication
213    // -----------------------------------------------------------------------
214
215    /// Wrapping multiplication, with a flag reporting whether it overflowed.
216    ///
217    /// One 256x256 multiply, not two. The overflow test needs the magnitude
218    /// product, and the wrapped *signed* bits follow from it without a second
219    /// pass: `a * b = (-1)^(sign a ^ sign b) * |a| * |b|`, and that identity
220    /// survives reduction mod 2^256, so negating the magnitude product gives
221    /// exactly the bits `cast_unsigned().wrapping_mul()` would have.
222    ///
223    /// Which callers this helps is worth being precise about. It is every form
224    /// that *consumes* the overflow flag -- [`checked_mul`](Self::checked_mul),
225    /// [`saturating_mul`](Self::saturating_mul), this function, and each step
226    /// of [`pow`](Self::pow). The bare `*` operator is not among them: in a
227    /// release contract profile `OVERFLOW_CHECKS` folds to false, the flag goes
228    /// unread, and LLVM was already dropping the second multiply as dead.
229    ///
230    /// Measured on rv32 by `scripts/bigint-bench.sh -o "mul signed_mul"`: a
231    /// saturating signed multiply costs 1095.02 gas against 1019.02 for a bare
232    /// wrapping unsigned one -- **+76 gas for the sign handling and the bound
233    /// check**, where a second full schoolbook pass would have been on the
234    /// order of +1,000.
235    #[inline]
236    pub const fn overflowing_mul(self, rhs: Self) -> (Self, bool) {
237        let (mag, wide) =
238            self.unsigned_abs().overflowing_mul(rhs.unsigned_abs());
239        let negative = self.is_negative() != rhs.is_negative();
240
241        let v = if negative { mag.wrapping_neg() } else { mag };
242
243        // The bound depends on the result's sign, since the negative range
244        // reaches one further.
245        let limit = if negative {
246            // 2^255, `MIN`'s magnitude.
247            U256::ONE.wrapping_shl(255)
248        } else {
249            Self::MAX.cast_unsigned()
250        };
251        (v.cast_signed(), wide || mag.const_gt(limit))
252    }
253
254    /// Multiplication, returning `None` on overflow.
255    #[inline]
256    pub const fn checked_mul(self, rhs: Self) -> Option<Self> {
257        match self.overflowing_mul(rhs) {
258            (v, false) => Some(v),
259            (_, true) => None,
260        }
261    }
262
263    /// Multiplication, wrapping on overflow.
264    #[inline]
265    pub const fn wrapping_mul(self, rhs: Self) -> Self {
266        self.overflowing_mul(rhs).0
267    }
268
269    /// Multiplication, saturating at [`MIN`](Self::MIN) or
270    /// [`MAX`](Self::MAX).
271    #[inline]
272    pub const fn saturating_mul(self, rhs: Self) -> Self {
273        match self.overflowing_mul(rhs) {
274            (v, false) => v,
275            (_, true) => {
276                if self.is_negative() == rhs.is_negative() {
277                    Self::MAX
278                } else {
279                    Self::MIN
280                }
281            }
282        }
283    }
284
285    // -----------------------------------------------------------------------
286    // Division
287    // -----------------------------------------------------------------------
288
289    /// Divides, returning the quotient and remainder, or `None` if `rhs` is
290    /// zero or the division overflows.
291    ///
292    /// The quotient truncates toward zero and the remainder takes the sign of
293    /// the dividend, matching Rust's primitives and Solidity's `int256`.
294    /// `MIN / -1` is the one overflow: its quotient is `2^255`.
295    #[inline]
296    pub const fn checked_div_rem(self, rhs: Self) -> Option<(Self, Self)> {
297        if rhs.is_zero()
298            || (self.const_eq(Self::MIN) && rhs.const_eq(Self::MINUS_ONE))
299        {
300            return None;
301        }
302        Some(self.div_rem_unchecked(rhs))
303    }
304
305    /// The division itself, with the two special cases already ruled out.
306    ///
307    /// `MIN / 1` still reaches here and produces a magnitude of `2^255`, which
308    /// negates back to `MIN` exactly; only `MIN / -1` needs the magnitude to
309    /// stay positive, and that is the case the callers reject.
310    #[inline]
311    const fn div_rem_unchecked(self, rhs: Self) -> (Self, Self) {
312        let (q, r) =
313            match self.unsigned_abs().checked_div_rem(rhs.unsigned_abs()) {
314                Some(v) => v,
315                None => panic!("attempt to divide by zero"),
316            };
317        let q = if self.is_negative() != rhs.is_negative() {
318            q.wrapping_neg()
319        } else {
320            q
321        };
322        // `|r| < |rhs| <= 2^255`, so the remainder is always representable.
323        let r = if self.is_negative() {
324            r.wrapping_neg()
325        } else {
326            r
327        };
328        (q.cast_signed(), r.cast_signed())
329    }
330
331    /// Divides, returning the quotient and remainder.
332    ///
333    /// # Panics
334    ///
335    /// If `rhs` is zero, or on `MIN / -1`. **Both panics are unconditional**,
336    /// and deliberately so: division overflow is the one arithmetic overflow
337    /// the primitives do not key off `overflow-checks`. `i128::MIN / -1`
338    /// panics under `-C overflow-checks=off` exactly as it does with checks
339    /// on, because the alternative on real hardware is a trap rather than a
340    /// wrapped value. Matching the primitives here means *not* gating this.
341    ///
342    /// The consequence is worth stating plainly, since it is the opposite of
343    /// what the rest of this type does: a contract profile silently wraps
344    /// `MIN + 1` and `MIN * 2`, but aborts on `MIN / -1`. Reach for
345    /// [`wrapping_div`](Self::wrapping_div) or
346    /// [`checked_div`](Self::checked_div) if an abort is not what the call
347    /// site wants.
348    #[inline]
349    pub const fn div_rem(self, rhs: Self) -> (Self, Self) {
350        if rhs.is_zero() {
351            panic!("attempt to divide by zero");
352        }
353        if self.const_eq(Self::MIN) && rhs.const_eq(Self::MINUS_ONE) {
354            panic!("attempt to divide with overflow");
355        }
356        self.div_rem_unchecked(rhs)
357    }
358
359    /// Division, with a flag reporting whether it overflowed.
360    ///
361    /// The flag is set only by `MIN / -1`, whose wrapped quotient is `MIN`.
362    ///
363    /// # Panics
364    ///
365    /// If `rhs` is zero.
366    #[inline]
367    pub const fn overflowing_div(self, rhs: Self) -> (Self, bool) {
368        if self.const_eq(Self::MIN) && rhs.const_eq(Self::MINUS_ONE) {
369            return (Self::MIN, true);
370        }
371        (self.wrapping_div(rhs), false)
372    }
373
374    /// Remainder, with a flag reporting whether it overflowed.
375    ///
376    /// The flag is set only by `MIN % -1`, whose wrapped remainder is zero.
377    ///
378    /// # Panics
379    ///
380    /// If `rhs` is zero.
381    #[inline]
382    pub const fn overflowing_rem(self, rhs: Self) -> (Self, bool) {
383        if self.const_eq(Self::MIN) && rhs.const_eq(Self::MINUS_ONE) {
384            return (Self::ZERO, true);
385        }
386        (self.wrapping_rem(rhs), false)
387    }
388
389    /// Division, returning `None` if `rhs` is zero or the division overflows.
390    #[inline]
391    pub const fn checked_div(self, rhs: Self) -> Option<Self> {
392        match self.checked_div_rem(rhs) {
393            Some((q, _)) => Some(q),
394            None => None,
395        }
396    }
397
398    /// Remainder, returning `None` if `rhs` is zero or the division overflows.
399    #[inline]
400    pub const fn checked_rem(self, rhs: Self) -> Option<Self> {
401        match self.checked_div_rem(rhs) {
402            Some((_, r)) => Some(r),
403            None => None,
404        }
405    }
406
407    /// Division, wrapping on overflow (`MIN / -1` is `MIN`).
408    ///
409    /// # Panics
410    ///
411    /// If `rhs` is zero.
412    #[inline]
413    pub const fn wrapping_div(self, rhs: Self) -> Self {
414        if self.const_eq(Self::MIN) && rhs.const_eq(Self::MINUS_ONE) {
415            return Self::MIN;
416        }
417        self.div_rem_unchecked(rhs).0
418    }
419
420    /// Remainder, wrapping on overflow (`MIN % -1` is zero).
421    ///
422    /// # Panics
423    ///
424    /// If `rhs` is zero.
425    #[inline]
426    pub const fn wrapping_rem(self, rhs: Self) -> Self {
427        if self.const_eq(Self::MIN) && rhs.const_eq(Self::MINUS_ONE) {
428            return Self::ZERO;
429        }
430        self.div_rem_unchecked(rhs).1
431    }
432
433    /// Euclidean division: the quotient whose remainder is never negative.
434    ///
435    /// `(-7).div_euclid(2)` is `-4`, where `(-7) / 2` is `-3`.
436    ///
437    /// # Panics
438    ///
439    /// As [`div_rem`](Self::div_rem).
440    #[inline]
441    pub const fn div_euclid(self, rhs: Self) -> Self {
442        let (q, r) = self.div_rem(rhs);
443        if r.is_negative() {
444            // Step the quotient away from zero in the divisor's direction, so
445            // the remainder becomes positive.
446            if rhs.is_negative() {
447                return q.wrapping_add(Self::ONE);
448            }
449            return q.wrapping_sub(Self::ONE);
450        }
451        q
452    }
453
454    /// The non-negative remainder of Euclidean division.
455    ///
456    /// # Panics
457    ///
458    /// As [`div_rem`](Self::div_rem).
459    #[inline]
460    pub const fn rem_euclid(self, rhs: Self) -> Self {
461        let (_, r) = self.div_rem(rhs);
462        if r.is_negative() {
463            // `|rhs|` is at most `2^255`, whose wrapped form is `MIN`; adding
464            // it to a negative `r` still lands in range.
465            return r.wrapping_add(rhs.unsigned_abs().cast_signed());
466        }
467        r
468    }
469
470    // -----------------------------------------------------------------------
471    // Shifts
472    // -----------------------------------------------------------------------
473
474    /// Left shift, masking the shift amount to `0..256`.
475    ///
476    /// Bit-identical to the unsigned shift: bits that fall off the top,
477    /// including the sign bit, are simply gone.
478    #[inline]
479    pub const fn wrapping_shl(self, n: u32) -> Self {
480        self.cast_unsigned().wrapping_shl(n).cast_signed()
481    }
482
483    /// Arithmetic right shift, masking the shift amount to `0..256`.
484    ///
485    /// The sign bit is replicated into the vacated positions, so this rounds
486    /// toward negative infinity: `(-1) >> 1` is `-1`, not `MAX`.
487    #[inline]
488    pub const fn wrapping_shr(self, n: u32) -> Self {
489        let n = n & (Self::BITS - 1);
490        let shifted = self.cast_unsigned().wrapping_shr(n);
491        if self.is_negative() {
492            // `!(MAX >> n)` is the top `n` bits, and is zero for `n == 0` --
493            // so no special case is needed there.
494            let sign_fill = U256::MAX.wrapping_shr(n).const_not();
495            shifted.const_bitor(sign_fill).cast_signed()
496        } else {
497            shifted.cast_signed()
498        }
499    }
500
501    /// Left shift, masking the shift amount and reporting whether the mask
502    /// changed it.
503    #[inline]
504    pub const fn overflowing_shl(self, n: u32) -> (Self, bool) {
505        (self.wrapping_shl(n), n >= Self::BITS)
506    }
507
508    /// Arithmetic right shift, masking the shift amount and reporting whether
509    /// the mask changed it.
510    #[inline]
511    pub const fn overflowing_shr(self, n: u32) -> (Self, bool) {
512        (self.wrapping_shr(n), n >= Self::BITS)
513    }
514
515    /// Left shift, returning `None` if the shift amount is at least 256.
516    #[inline]
517    pub const fn checked_shl(self, n: u32) -> Option<Self> {
518        if n >= Self::BITS {
519            None
520        } else {
521            Some(self.wrapping_shl(n))
522        }
523    }
524
525    /// Arithmetic right shift, returning `None` if the shift amount is at
526    /// least 256.
527    #[inline]
528    pub const fn checked_shr(self, n: u32) -> Option<Self> {
529        if n >= Self::BITS {
530            None
531        } else {
532            Some(self.wrapping_shr(n))
533        }
534    }
535
536    // -----------------------------------------------------------------------
537    // Bitwise, from `const fn`
538    // -----------------------------------------------------------------------
539
540    /// Bitwise AND, usable from a `const fn`.
541    #[inline]
542    pub const fn const_bitand(self, rhs: Self) -> Self {
543        self.cast_unsigned()
544            .const_bitand(rhs.cast_unsigned())
545            .cast_signed()
546    }
547
548    /// Bitwise OR, usable from a `const fn`.
549    #[inline]
550    pub const fn const_bitor(self, rhs: Self) -> Self {
551        self.cast_unsigned()
552            .const_bitor(rhs.cast_unsigned())
553            .cast_signed()
554    }
555
556    /// Bitwise XOR, usable from a `const fn`.
557    #[inline]
558    pub const fn const_bitxor(self, rhs: Self) -> Self {
559        self.cast_unsigned()
560            .const_bitxor(rhs.cast_unsigned())
561            .cast_signed()
562    }
563
564    /// Bitwise NOT, usable from a `const fn`. `!x` is `-x - 1`.
565    #[inline]
566    pub const fn const_not(self) -> Self {
567        self.cast_unsigned().const_not().cast_signed()
568    }
569
570    // -----------------------------------------------------------------------
571    // Exponentiation
572    // -----------------------------------------------------------------------
573
574    /// Exponentiation, with a flag reporting whether it overflowed.
575    ///
576    /// `x.pow(0)` is one for every `x`, matching the primitives.
577    pub const fn overflowing_pow(self, exp: u32) -> (Self, bool) {
578        let mut base = self;
579        let mut exp = exp;
580        let mut acc = Self::ONE;
581        let mut overflow = false;
582
583        while exp > 0 {
584            if exp & 1 == 1 {
585                let (v, o) = acc.overflowing_mul(base);
586                acc = v;
587                overflow |= o;
588            }
589            exp >>= 1;
590            if exp > 0 {
591                let (v, o) = base.overflowing_mul(base);
592                base = v;
593                overflow |= o;
594            }
595        }
596
597        (acc, overflow)
598    }
599
600    /// Exponentiation, returning `None` on overflow.
601    #[inline]
602    pub const fn checked_pow(self, exp: u32) -> Option<Self> {
603        match self.overflowing_pow(exp) {
604            (v, false) => Some(v),
605            (_, true) => None,
606        }
607    }
608
609    /// Exponentiation, wrapping on overflow.
610    #[inline]
611    pub const fn wrapping_pow(self, exp: u32) -> Self {
612        self.overflowing_pow(exp).0
613    }
614
615    /// Exponentiation, saturating at [`MIN`](Self::MIN) or
616    /// [`MAX`](Self::MAX).
617    #[inline]
618    pub const fn saturating_pow(self, exp: u32) -> Self {
619        match self.overflowing_pow(exp) {
620            (v, false) => v,
621            // An overflowing power is negative exactly when the base is
622            // negative and the exponent odd.
623            (_, true) => {
624                if self.is_negative() && exp % 2 == 1 {
625                    Self::MIN
626                } else {
627                    Self::MAX
628                }
629            }
630        }
631    }
632
633    /// Exponentiation.
634    ///
635    /// # Panics
636    ///
637    /// On overflow, if `overflow-checks` is on -- otherwise it wraps.
638    #[inline]
639    pub const fn pow(self, exp: u32) -> Self {
640        let (v, overflow) = self.overflowing_pow(exp);
641        if OVERFLOW_CHECKS && overflow {
642            panic!("attempt to multiply with overflow");
643        }
644        v
645    }
646}
647
648// ---------------------------------------------------------------------------
649// Operators
650// ---------------------------------------------------------------------------
651
652impl Add for I256 {
653    type Output = Self;
654
655    #[inline]
656    fn add(self, rhs: Self) -> Self {
657        let (v, overflow) = self.overflowing_add(rhs);
658        if OVERFLOW_CHECKS && overflow {
659            panic!("attempt to add with overflow");
660        }
661        v
662    }
663}
664
665impl Sub for I256 {
666    type Output = Self;
667
668    #[inline]
669    fn sub(self, rhs: Self) -> Self {
670        let (v, overflow) = self.overflowing_sub(rhs);
671        if OVERFLOW_CHECKS && overflow {
672            panic!("attempt to subtract with overflow");
673        }
674        v
675    }
676}
677
678impl Mul for I256 {
679    type Output = Self;
680
681    #[inline]
682    fn mul(self, rhs: Self) -> Self {
683        let (v, overflow) = self.overflowing_mul(rhs);
684        if OVERFLOW_CHECKS && overflow {
685            panic!("attempt to multiply with overflow");
686        }
687        v
688    }
689}
690
691impl Div for I256 {
692    type Output = Self;
693
694    /// Truncating division. Panics on a zero divisor regardless of
695    /// `overflow-checks`, matching the primitive integers.
696    #[inline]
697    fn div(self, rhs: Self) -> Self {
698        self.div_rem(rhs).0
699    }
700}
701
702impl Rem for I256 {
703    type Output = Self;
704
705    /// Remainder, taking the sign of the dividend. Panics on a zero divisor
706    /// regardless of `overflow-checks`, matching the primitive integers.
707    #[inline]
708    fn rem(self, rhs: Self) -> Self {
709        self.div_rem(rhs).1
710    }
711}
712
713impl Neg for I256 {
714    type Output = Self;
715
716    #[inline]
717    fn neg(self) -> Self {
718        let (v, overflow) = self.overflowing_neg();
719        if OVERFLOW_CHECKS && overflow {
720            panic!("attempt to negate with overflow");
721        }
722        v
723    }
724}
725
726impl Not for I256 {
727    type Output = Self;
728
729    #[inline]
730    fn not(self) -> Self {
731        self.const_not()
732    }
733}
734
735macro_rules! impl_assign {
736    ($trait:ident, $method:ident, $base:ident, $base_method:ident, $rhs:ty) => {
737        impl $trait<$rhs> for I256 {
738            #[inline]
739            fn $method(&mut self, rhs: $rhs) {
740                *self = <Self as $base<$rhs>>::$base_method(*self, rhs);
741            }
742        }
743    };
744}
745
746/// Shifts take every integer type, for the reason the unsigned side does: with
747/// a single `Shl<u32>` impl a bare `x << 112` builds, but a second impl makes
748/// the literal ambiguous and it falls back to `i32`.
749macro_rules! impl_shift {
750    ($($t:ty),* $(,)?) => {
751        $(
752            impl Shl<$t> for I256 {
753                type Output = Self;
754
755                #[inline]
756                fn shl(self, rhs: $t) -> Self {
757                    let (bits, overflow) = crate::arith::shift_bits(rhs as u128);
758                    if OVERFLOW_CHECKS && overflow {
759                        panic!("attempt to shift left with overflow");
760                    }
761                    self.wrapping_shl(bits)
762                }
763            }
764
765            impl Shr<$t> for I256 {
766                type Output = Self;
767
768                #[inline]
769                fn shr(self, rhs: $t) -> Self {
770                    let (bits, overflow) = crate::arith::shift_bits(rhs as u128);
771                    if OVERFLOW_CHECKS && overflow {
772                        panic!("attempt to shift right with overflow");
773                    }
774                    self.wrapping_shr(bits)
775                }
776            }
777
778            impl_assign!(ShlAssign, shl_assign, Shl, shl, $t);
779            impl_assign!(ShrAssign, shr_assign, Shr, shr, $t);
780        )*
781    };
782}
783
784impl_shift!(
785    u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize
786);
787
788macro_rules! impl_bitop {
789    ($trait:ident, $method:ident, $const_method:ident) => {
790        impl $trait for I256 {
791            type Output = Self;
792
793            #[inline]
794            fn $method(self, rhs: Self) -> Self {
795                self.$const_method(rhs)
796            }
797        }
798    };
799}
800
801impl_bitop!(BitAnd, bitand, const_bitand);
802impl_bitop!(BitOr, bitor, const_bitor);
803impl_bitop!(BitXor, bitxor, const_bitxor);
804
805impl_assign!(AddAssign, add_assign, Add, add, I256);
806impl_assign!(SubAssign, sub_assign, Sub, sub, I256);
807impl_assign!(MulAssign, mul_assign, Mul, mul, I256);
808impl_assign!(DivAssign, div_assign, Div, div, I256);
809impl_assign!(RemAssign, rem_assign, Rem, rem, I256);
810impl_assign!(BitAndAssign, bitand_assign, BitAnd, bitand, I256);
811impl_assign!(BitOrAssign, bitor_assign, BitOr, bitor, I256);
812impl_assign!(BitXorAssign, bitxor_assign, BitXor, bitxor, I256);