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);