cosmwasm_std/math/
int256.rs

1use alloc::string::{String, ToString};
2use core::fmt;
3use core::ops::{
4    Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Not, Rem, RemAssign, Shl, ShlAssign, Shr,
5    ShrAssign, Sub, SubAssign,
6};
7use core::str::FromStr;
8
9use crate::errors::{DivideByZeroError, DivisionError, OverflowError, OverflowOperation, StdError};
10use crate::forward_ref::{forward_ref_binop, forward_ref_op_assign};
11use crate::{
12    CheckedMultiplyRatioError, Int128, Int512, Int64, Uint128, Uint256, Uint512, Uint64,
13    __internal::forward_ref_partial_eq,
14};
15
16/// Used internally - we don't want to leak this type since we might change
17/// the implementation in the future.
18use bnum::types::{I256, U256};
19
20use super::conversion::{
21    grow_be_int, primitive_to_wrapped_int, try_from_int_to_int, try_from_uint_to_int,
22};
23use super::impl_int_serde;
24use super::num_consts::NumConsts;
25
26/// An implementation of i256 that is using strings for JSON encoding/decoding,
27/// such that the full i256 range can be used for clients that convert JSON numbers to floats,
28/// like JavaScript and jq.
29///
30/// # Examples
31///
32/// Use `new` to create instances out of i128, `from` for other primitive uint/int types
33/// or `from_be_bytes` to provide big endian bytes:
34///
35/// ```
36/// # use cosmwasm_std::Int256;
37/// let a = Int256::new(258i128);
38/// let b = Int256::from(258u16);
39/// let c = Int256::from_be_bytes([
40///     0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
41///     0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
42///     0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
43///     0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 2u8,
44/// ]);
45/// assert_eq!(a, b);
46/// assert_eq!(a, c);
47/// ```
48#[derive(Copy, Clone, Default, Debug, PartialEq, Eq, PartialOrd, Ord, schemars::JsonSchema)]
49pub struct Int256(#[schemars(with = "String")] pub(crate) I256);
50
51impl_int_serde!(Int256);
52forward_ref_partial_eq!(Int256, Int256);
53
54impl Int256 {
55    pub const MAX: Int256 = Int256(I256::MAX);
56    pub const MIN: Int256 = Int256(I256::MIN);
57
58    /// Creates a Int256(value).
59    ///
60    /// This method is less flexible than `from` but can be called in a const context.
61    ///
62    /// Before CosmWasm 3 this took a byte array as an argument. You can get this behaviour
63    /// with [`from_be_bytes`].
64    ///
65    /// [`from_be_bytes`]: Self::from_be_bytes
66    #[inline]
67    #[must_use]
68    pub const fn new(value: i128) -> Self {
69        Self::from_be_bytes(grow_be_int(value.to_be_bytes()))
70    }
71
72    /// Creates a Int256(0)
73    #[inline]
74    pub const fn zero() -> Self {
75        Int256(I256::ZERO)
76    }
77
78    /// Creates a Int256(1)
79    #[inline]
80    pub const fn one() -> Self {
81        Self(I256::ONE)
82    }
83
84    /// A conversion from `i128` that, unlike the one provided by the `From` trait,
85    /// can be used in a `const` context.
86    #[deprecated(since = "3.0.0", note = "Use Int256::new(value) instead")]
87    pub const fn from_i128(value: i128) -> Self {
88        Self::new(value)
89    }
90
91    #[must_use]
92    pub const fn from_be_bytes(data: [u8; 32]) -> Self {
93        let words: [u64; 4] = [
94            u64::from_le_bytes([
95                data[31], data[30], data[29], data[28], data[27], data[26], data[25], data[24],
96            ]),
97            u64::from_le_bytes([
98                data[23], data[22], data[21], data[20], data[19], data[18], data[17], data[16],
99            ]),
100            u64::from_le_bytes([
101                data[15], data[14], data[13], data[12], data[11], data[10], data[9], data[8],
102            ]),
103            u64::from_le_bytes([
104                data[7], data[6], data[5], data[4], data[3], data[2], data[1], data[0],
105            ]),
106        ];
107        Self(I256::from_bits(U256::from_digits(words)))
108    }
109
110    #[must_use]
111    pub const fn from_le_bytes(data: [u8; 32]) -> Self {
112        let words: [u64; 4] = [
113            u64::from_le_bytes([
114                data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7],
115            ]),
116            u64::from_le_bytes([
117                data[8], data[9], data[10], data[11], data[12], data[13], data[14], data[15],
118            ]),
119            u64::from_le_bytes([
120                data[16], data[17], data[18], data[19], data[20], data[21], data[22], data[23],
121            ]),
122            u64::from_le_bytes([
123                data[24], data[25], data[26], data[27], data[28], data[29], data[30], data[31],
124            ]),
125        ];
126        Self(I256::from_bits(U256::from_digits(words)))
127    }
128
129    /// Returns a copy of the number as big endian bytes.
130    #[must_use = "this returns the result of the operation, without modifying the original"]
131    pub const fn to_be_bytes(self) -> [u8; 32] {
132        let bits = self.0.to_bits();
133        let words = bits.digits();
134        let words = [
135            words[3].to_be_bytes(),
136            words[2].to_be_bytes(),
137            words[1].to_be_bytes(),
138            words[0].to_be_bytes(),
139        ];
140        unsafe { core::mem::transmute::<[[u8; 8]; 4], [u8; 32]>(words) }
141    }
142
143    /// Returns a copy of the number as little endian bytes.
144    #[must_use = "this returns the result of the operation, without modifying the original"]
145    pub const fn to_le_bytes(self) -> [u8; 32] {
146        let bits = self.0.to_bits();
147        let words = bits.digits();
148        let words = [
149            words[0].to_le_bytes(),
150            words[1].to_le_bytes(),
151            words[2].to_le_bytes(),
152            words[3].to_le_bytes(),
153        ];
154        unsafe { core::mem::transmute::<[[u8; 8]; 4], [u8; 32]>(words) }
155    }
156
157    #[must_use]
158    pub const fn is_zero(&self) -> bool {
159        self.0.is_zero()
160    }
161
162    #[must_use]
163    pub const fn is_negative(&self) -> bool {
164        self.0.is_negative()
165    }
166
167    #[must_use = "this returns the result of the operation, without modifying the original"]
168    pub const fn pow(self, exp: u32) -> Self {
169        match self.0.checked_pow(exp) {
170            Some(val) => Self(val),
171            None => panic!("attempt to exponentiate with overflow"),
172        }
173    }
174
175    /// Returns `self * numerator / denominator`.
176    ///
177    /// Due to the nature of the integer division involved, the result is always floored.
178    /// E.g. 5 * 99/100 = 4.
179    pub fn checked_multiply_ratio<A: Into<Self>, B: Into<Self>>(
180        &self,
181        numerator: A,
182        denominator: B,
183    ) -> Result<Self, CheckedMultiplyRatioError> {
184        let numerator = numerator.into();
185        let denominator = denominator.into();
186        if denominator.is_zero() {
187            return Err(CheckedMultiplyRatioError::DivideByZero);
188        }
189        match (self.full_mul(numerator) / Int512::from(denominator)).try_into() {
190            Ok(ratio) => Ok(ratio),
191            Err(_) => Err(CheckedMultiplyRatioError::Overflow),
192        }
193    }
194
195    /// Multiplies two [`Int256`] values without overflow, producing an
196    /// [`Int512`].
197    ///
198    /// # Examples
199    ///
200    /// ```
201    /// use cosmwasm_std::Int256;
202    ///
203    /// let a = Int256::MAX;
204    /// let result = a.full_mul(2i32);
205    /// assert_eq!(
206    ///     result.to_string(),
207    ///     "115792089237316195423570985008687907853269984665640564039457584007913129639934"
208    /// );
209    /// ```
210    #[must_use = "this returns the result of the operation, without modifying the original"]
211    pub fn full_mul(self, rhs: impl Into<Self>) -> Int512 {
212        Int512::from(self)
213            .checked_mul(Int512::from(rhs.into()))
214            .unwrap()
215    }
216
217    pub fn checked_add(self, other: Self) -> Result<Self, OverflowError> {
218        self.0
219            .checked_add(other.0)
220            .map(Self)
221            .ok_or_else(|| OverflowError::new(OverflowOperation::Add))
222    }
223
224    pub fn checked_sub(self, other: Self) -> Result<Self, OverflowError> {
225        self.0
226            .checked_sub(other.0)
227            .map(Self)
228            .ok_or_else(|| OverflowError::new(OverflowOperation::Sub))
229    }
230
231    pub fn checked_mul(self, other: Self) -> Result<Self, OverflowError> {
232        self.0
233            .checked_mul(other.0)
234            .map(Self)
235            .ok_or_else(|| OverflowError::new(OverflowOperation::Mul))
236    }
237
238    pub fn checked_pow(self, exp: u32) -> Result<Self, OverflowError> {
239        self.0
240            .checked_pow(exp)
241            .map(Self)
242            .ok_or_else(|| OverflowError::new(OverflowOperation::Pow))
243    }
244
245    pub fn checked_div(self, other: Self) -> Result<Self, DivisionError> {
246        if other.is_zero() {
247            return Err(DivisionError::DivideByZero);
248        }
249        self.0
250            .checked_div(other.0)
251            .map(Self)
252            .ok_or(DivisionError::Overflow)
253    }
254
255    pub fn checked_div_euclid(self, other: Self) -> Result<Self, DivisionError> {
256        if other.is_zero() {
257            return Err(DivisionError::DivideByZero);
258        }
259        self.0
260            .checked_div_euclid(other.0)
261            .map(Self)
262            .ok_or(DivisionError::Overflow)
263    }
264
265    pub fn checked_rem(self, other: Self) -> Result<Self, DivideByZeroError> {
266        self.0
267            .checked_rem(other.0)
268            .map(Self)
269            .ok_or(DivideByZeroError)
270    }
271
272    pub fn checked_shr(self, other: u32) -> Result<Self, OverflowError> {
273        if other >= 256 {
274            return Err(OverflowError::new(OverflowOperation::Shr));
275        }
276
277        Ok(Self(self.0.shr(other)))
278    }
279
280    pub fn checked_shl(self, other: u32) -> Result<Self, OverflowError> {
281        if other >= 256 {
282            return Err(OverflowError::new(OverflowOperation::Shl));
283        }
284
285        Ok(Self(self.0.shl(other)))
286    }
287
288    #[must_use = "this returns the result of the operation, without modifying the original"]
289    #[inline]
290    pub fn wrapping_add(self, other: Self) -> Self {
291        Self(self.0.wrapping_add(other.0))
292    }
293
294    #[must_use = "this returns the result of the operation, without modifying the original"]
295    #[inline]
296    pub fn wrapping_sub(self, other: Self) -> Self {
297        Self(self.0.wrapping_sub(other.0))
298    }
299
300    #[must_use = "this returns the result of the operation, without modifying the original"]
301    #[inline]
302    pub fn wrapping_mul(self, other: Self) -> Self {
303        Self(self.0.wrapping_mul(other.0))
304    }
305
306    #[must_use = "this returns the result of the operation, without modifying the original"]
307    #[inline]
308    pub fn wrapping_pow(self, other: u32) -> Self {
309        Self(self.0.wrapping_pow(other))
310    }
311
312    #[must_use = "this returns the result of the operation, without modifying the original"]
313    pub fn saturating_add(self, other: Self) -> Self {
314        Self(self.0.saturating_add(other.0))
315    }
316
317    #[must_use = "this returns the result of the operation, without modifying the original"]
318    pub fn saturating_sub(self, other: Self) -> Self {
319        Self(self.0.saturating_sub(other.0))
320    }
321
322    #[must_use = "this returns the result of the operation, without modifying the original"]
323    pub fn saturating_mul(self, other: Self) -> Self {
324        Self(self.0.saturating_mul(other.0))
325    }
326
327    #[must_use = "this returns the result of the operation, without modifying the original"]
328    pub fn saturating_pow(self, exp: u32) -> Self {
329        Self(self.0.saturating_pow(exp))
330    }
331
332    #[must_use = "this returns the result of the operation, without modifying the original"]
333    pub const fn abs_diff(self, other: Self) -> Uint256 {
334        Uint256(self.0.abs_diff(other.0))
335    }
336
337    #[must_use = "this returns the result of the operation, without modifying the original"]
338    pub const fn abs(self) -> Self {
339        match self.0.checked_abs() {
340            Some(val) => Self(val),
341            None => panic!("attempt to calculate absolute value with overflow"),
342        }
343    }
344
345    #[must_use = "this returns the result of the operation, without modifying the original"]
346    pub const fn unsigned_abs(self) -> Uint256 {
347        Uint256(self.0.unsigned_abs())
348    }
349
350    /// Strict negation. Computes -self, panicking if self == MIN.
351    ///
352    /// This is the same as [`Int256::neg`] but const.
353    pub const fn strict_neg(self) -> Self {
354        match self.0.checked_neg() {
355            Some(val) => Self(val),
356            None => panic!("attempt to negate with overflow"),
357        }
358    }
359}
360
361impl NumConsts for Int256 {
362    const ZERO: Self = Self::zero();
363    const ONE: Self = Self::one();
364    const MAX: Self = Self::MAX;
365    const MIN: Self = Self::MIN;
366}
367
368// Uint to Int
369try_from_uint_to_int!(Uint512, Int256);
370try_from_uint_to_int!(Uint256, Int256);
371
372impl From<Uint128> for Int256 {
373    fn from(val: Uint128) -> Self {
374        val.u128().into()
375    }
376}
377
378impl From<Uint64> for Int256 {
379    fn from(val: Uint64) -> Self {
380        val.u64().into()
381    }
382}
383
384// uint to Int
385primitive_to_wrapped_int!(u8, Int256);
386primitive_to_wrapped_int!(u16, Int256);
387primitive_to_wrapped_int!(u32, Int256);
388primitive_to_wrapped_int!(u64, Int256);
389primitive_to_wrapped_int!(u128, Int256);
390
391// Int to Int
392try_from_int_to_int!(Int512, Int256);
393
394impl From<Int128> for Int256 {
395    fn from(val: Int128) -> Self {
396        val.i128().into()
397    }
398}
399
400impl From<Int64> for Int256 {
401    fn from(val: Int64) -> Self {
402        val.i64().into()
403    }
404}
405
406// int to Int
407primitive_to_wrapped_int!(i8, Int256);
408primitive_to_wrapped_int!(i16, Int256);
409primitive_to_wrapped_int!(i32, Int256);
410primitive_to_wrapped_int!(i64, Int256);
411primitive_to_wrapped_int!(i128, Int256);
412
413impl TryFrom<&str> for Int256 {
414    type Error = StdError;
415
416    fn try_from(val: &str) -> Result<Self, Self::Error> {
417        Self::from_str(val)
418    }
419}
420
421impl FromStr for Int256 {
422    type Err = StdError;
423
424    fn from_str(s: &str) -> Result<Self, Self::Err> {
425        match I256::from_str_radix(s, 10) {
426            Ok(u) => Ok(Self(u)),
427            Err(e) => Err(StdError::generic_err(format!("Parsing Int256: {e}"))),
428        }
429    }
430}
431
432impl From<Int256> for String {
433    fn from(original: Int256) -> Self {
434        original.to_string()
435    }
436}
437
438impl fmt::Display for Int256 {
439    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
440        self.0.fmt(f)
441    }
442}
443
444impl Add<Int256> for Int256 {
445    type Output = Self;
446
447    fn add(self, rhs: Self) -> Self {
448        Int256(self.0.checked_add(rhs.0).unwrap())
449    }
450}
451forward_ref_binop!(impl Add, add for Int256, Int256);
452
453impl Sub<Int256> for Int256 {
454    type Output = Self;
455
456    fn sub(self, rhs: Self) -> Self {
457        Int256(self.0.checked_sub(rhs.0).unwrap())
458    }
459}
460forward_ref_binop!(impl Sub, sub for Int256, Int256);
461
462impl SubAssign<Int256> for Int256 {
463    fn sub_assign(&mut self, rhs: Int256) {
464        self.0 = self.0.checked_sub(rhs.0).unwrap();
465    }
466}
467forward_ref_op_assign!(impl SubAssign, sub_assign for Int256, Int256);
468
469impl Div<Int256> for Int256 {
470    type Output = Self;
471
472    fn div(self, rhs: Self) -> Self::Output {
473        Self(self.0.checked_div(rhs.0).unwrap())
474    }
475}
476forward_ref_binop!(impl Div, div for Int256, Int256);
477
478impl Rem for Int256 {
479    type Output = Self;
480
481    /// # Panics
482    ///
483    /// This operation will panic if `rhs` is zero.
484    #[inline]
485    fn rem(self, rhs: Self) -> Self {
486        Self(self.0.rem(rhs.0))
487    }
488}
489forward_ref_binop!(impl Rem, rem for Int256, Int256);
490
491impl Not for Int256 {
492    type Output = Self;
493
494    fn not(self) -> Self::Output {
495        Self(!self.0)
496    }
497}
498
499impl Neg for Int256 {
500    type Output = Self;
501
502    fn neg(self) -> Self::Output {
503        self.strict_neg()
504    }
505}
506
507impl RemAssign<Int256> for Int256 {
508    fn rem_assign(&mut self, rhs: Int256) {
509        *self = *self % rhs;
510    }
511}
512forward_ref_op_assign!(impl RemAssign, rem_assign for Int256, Int256);
513
514impl Mul<Int256> for Int256 {
515    type Output = Self;
516
517    fn mul(self, rhs: Self) -> Self::Output {
518        Self(self.0.checked_mul(rhs.0).unwrap())
519    }
520}
521forward_ref_binop!(impl Mul, mul for Int256, Int256);
522
523impl MulAssign<Int256> for Int256 {
524    fn mul_assign(&mut self, rhs: Self) {
525        self.0 = self.0.checked_mul(rhs.0).unwrap();
526    }
527}
528forward_ref_op_assign!(impl MulAssign, mul_assign for Int256, Int256);
529
530impl Shr<u32> for Int256 {
531    type Output = Self;
532
533    fn shr(self, rhs: u32) -> Self::Output {
534        self.checked_shr(rhs).unwrap_or_else(|_| {
535            panic!("right shift error: {rhs} is larger or equal than the number of bits in Int256",)
536        })
537    }
538}
539forward_ref_binop!(impl Shr, shr for Int256, u32);
540
541impl Shl<u32> for Int256 {
542    type Output = Self;
543
544    fn shl(self, rhs: u32) -> Self::Output {
545        self.checked_shl(rhs).unwrap_or_else(|_| {
546            panic!("left shift error: {rhs} is larger or equal than the number of bits in Int256",)
547        })
548    }
549}
550forward_ref_binop!(impl Shl, shl for Int256, u32);
551
552impl AddAssign<Int256> for Int256 {
553    fn add_assign(&mut self, rhs: Int256) {
554        self.0 = self.0.checked_add(rhs.0).unwrap();
555    }
556}
557forward_ref_op_assign!(impl AddAssign, add_assign for Int256, Int256);
558
559impl DivAssign<Int256> for Int256 {
560    fn div_assign(&mut self, rhs: Self) {
561        self.0 = self.0.checked_div(rhs.0).unwrap();
562    }
563}
564forward_ref_op_assign!(impl DivAssign, div_assign for Int256, Int256);
565
566impl ShrAssign<u32> for Int256 {
567    fn shr_assign(&mut self, rhs: u32) {
568        *self = Shr::<u32>::shr(*self, rhs);
569    }
570}
571forward_ref_op_assign!(impl ShrAssign, shr_assign for Int256, u32);
572
573impl ShlAssign<u32> for Int256 {
574    fn shl_assign(&mut self, rhs: u32) {
575        *self = Shl::<u32>::shl(*self, rhs);
576    }
577}
578forward_ref_op_assign!(impl ShlAssign, shl_assign for Int256, u32);
579
580impl<A> core::iter::Sum<A> for Int256
581where
582    Self: Add<A, Output = Self>,
583{
584    fn sum<I: Iterator<Item = A>>(iter: I) -> Self {
585        iter.fold(Self::zero(), Add::add)
586    }
587}
588
589#[cfg(test)]
590mod tests {
591    use super::*;
592    use crate::math::conversion::test_try_from_uint_to_int;
593
594    #[test]
595    fn size_of_works() {
596        assert_eq!(core::mem::size_of::<Int256>(), 32);
597    }
598
599    #[test]
600    fn int256_new_works() {
601        let num = Int256::new(1);
602        assert_eq!(
603            num.to_be_bytes(),
604            [
605                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
606                0, 0, 0, 1
607            ]
608        );
609
610        let num = Int256::new(-1);
611        assert_eq!(
612            num.to_be_bytes(),
613            [
614                255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
615                255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
616            ]
617        );
618
619        for v in [0, 1, -4, 18, 875786576, -11763498739, i128::MAX, i128::MIN] {
620            // From is implemented by bnum, so we test two independent implementations against each other
621            let uut = Int256::new(v);
622            assert_eq!(uut, Int256::from(v));
623        }
624    }
625
626    #[test]
627    fn int256_from_be_bytes_works() {
628        let num = Int256::from_be_bytes([1; 32]);
629        let a: [u8; 32] = num.to_be_bytes();
630        assert_eq!(a, [1; 32]);
631
632        let be_bytes = [
633            0u8, 222u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
634            0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 2u8, 3u8,
635        ];
636        let num = Int256::from_be_bytes(be_bytes);
637        let resulting_bytes: [u8; 32] = num.to_be_bytes();
638        assert_eq!(be_bytes, resulting_bytes);
639    }
640
641    #[test]
642    fn int256_not_works() {
643        let num = Int256::from_be_bytes([1; 32]);
644        let a = (!num).to_be_bytes();
645        assert_eq!(a, [254; 32]);
646
647        assert_eq!(!Int256::from(-1234806i128), Int256::from(!-1234806i128));
648
649        assert_eq!(!Int256::MAX, Int256::MIN);
650        assert_eq!(!Int256::MIN, Int256::MAX);
651    }
652
653    #[test]
654    fn int256_zero_works() {
655        let zero = Int256::zero();
656        assert_eq!(zero.to_be_bytes(), [0; 32]);
657    }
658
659    #[test]
660    fn uint256_one_works() {
661        let one = Int256::one();
662        let mut one_be = [0; 32];
663        one_be[31] = 1;
664
665        assert_eq!(one.to_be_bytes(), one_be);
666    }
667
668    #[test]
669    fn int256_endianness() {
670        let be_bytes = [
671            0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
672            0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 2u8, 3u8,
673        ];
674        let le_bytes = [
675            3u8, 2u8, 1u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
676            0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
677        ];
678
679        // These should all be the same.
680        let a = Int256::from_be_bytes(be_bytes);
681        let b = Int256::from_le_bytes(le_bytes);
682        assert_eq!(a, Int256::from(65536u32 + 512 + 3));
683        assert_eq!(a, b);
684    }
685
686    #[test]
687    fn int256_convert_from() {
688        let a = Int256::from(5u128);
689        assert_eq!(a.0, I256::from(5u32));
690
691        let a = Int256::from(5u64);
692        assert_eq!(a.0, I256::from(5u32));
693
694        let a = Int256::from(5u32);
695        assert_eq!(a.0, I256::from(5u32));
696
697        let a = Int256::from(5u16);
698        assert_eq!(a.0, I256::from(5u32));
699
700        let a = Int256::from(5u8);
701        assert_eq!(a.0, I256::from(5u32));
702
703        let a = Int256::from(-5i128);
704        assert_eq!(a.0, I256::from(-5i32));
705
706        let a = Int256::from(-5i64);
707        assert_eq!(a.0, I256::from(-5i32));
708
709        let a = Int256::from(-5i32);
710        assert_eq!(a.0, I256::from(-5i32));
711
712        let a = Int256::from(-5i16);
713        assert_eq!(a.0, I256::from(-5i32));
714
715        let a = Int256::from(-5i8);
716        assert_eq!(a.0, I256::from(-5i32));
717
718        let result = Int256::try_from("34567");
719        assert_eq!(
720            result.unwrap().0,
721            I256::from_str_radix("34567", 10).unwrap()
722        );
723
724        let result = Int256::try_from("1.23");
725        assert!(result.is_err());
726    }
727
728    #[test]
729    fn int256_try_from_unsigned_works() {
730        test_try_from_uint_to_int::<Uint256, Int256>("Uint256", "Int256");
731        test_try_from_uint_to_int::<Uint512, Int256>("Uint512", "Int256");
732    }
733
734    #[test]
735    #[allow(deprecated)]
736    fn int256_from_i128() {
737        assert_eq!(Int256::from_i128(123i128), Int256::from_str("123").unwrap());
738
739        assert_eq!(
740            Int256::from_i128(9785746283745i128),
741            Int256::from_str("9785746283745").unwrap()
742        );
743
744        assert_eq!(
745            Int256::from_i128(i128::MAX).to_string(),
746            i128::MAX.to_string()
747        );
748        assert_eq!(
749            Int256::from_i128(i128::MIN).to_string(),
750            i128::MIN.to_string()
751        );
752    }
753
754    #[test]
755    fn int256_implements_display() {
756        let a = Int256::from(12345u32);
757        assert_eq!(format!("Embedded: {a}"), "Embedded: 12345");
758        assert_eq!(a.to_string(), "12345");
759
760        let a = Int256::from(-12345i32);
761        assert_eq!(format!("Embedded: {a}"), "Embedded: -12345");
762        assert_eq!(a.to_string(), "-12345");
763
764        let a = Int256::zero();
765        assert_eq!(format!("Embedded: {a}"), "Embedded: 0");
766        assert_eq!(a.to_string(), "0");
767    }
768
769    #[test]
770    fn int256_display_padding_works() {
771        // width > natural representation
772        let a = Int256::from(123u64);
773        assert_eq!(format!("Embedded: {a:05}"), "Embedded: 00123");
774        let a = Int256::from(-123i64);
775        assert_eq!(format!("Embedded: {a:05}"), "Embedded: -0123");
776
777        // width < natural representation
778        let a = Int256::from(123u64);
779        assert_eq!(format!("Embedded: {a:02}"), "Embedded: 123");
780        let a = Int256::from(-123i64);
781        assert_eq!(format!("Embedded: {a:02}"), "Embedded: -123");
782    }
783
784    #[test]
785    fn int256_to_be_bytes_works() {
786        assert_eq!(Int256::zero().to_be_bytes(), [0; 32]);
787
788        let mut max = [0xff; 32];
789        max[0] = 0x7f;
790        assert_eq!(Int256::MAX.to_be_bytes(), max);
791
792        let mut one = [0; 32];
793        one[31] = 1;
794        assert_eq!(Int256::from(1u128).to_be_bytes(), one);
795        // Python: `[b for b in (240282366920938463463374607431768124608).to_bytes(32, "big")]`
796        assert_eq!(
797            Int256::from(240282366920938463463374607431768124608u128).to_be_bytes(),
798            [
799                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 180, 196, 179, 87, 165, 121, 59,
800                133, 246, 117, 221, 191, 255, 254, 172, 192
801            ]
802        );
803        assert_eq!(
804            Int256::from_be_bytes([
805                17, 4, 23, 32, 87, 67, 123, 200, 58, 91, 0, 38, 33, 21, 67, 78, 87, 76, 65, 54,
806                211, 201, 192, 7, 42, 233, 2, 240, 200, 115, 150, 240
807            ])
808            .to_be_bytes(),
809            [
810                17, 4, 23, 32, 87, 67, 123, 200, 58, 91, 0, 38, 33, 21, 67, 78, 87, 76, 65, 54,
811                211, 201, 192, 7, 42, 233, 2, 240, 200, 115, 150, 240
812            ]
813        );
814    }
815
816    #[test]
817    fn int256_to_le_bytes_works() {
818        assert_eq!(Int256::zero().to_le_bytes(), [0; 32]);
819
820        let mut max = [0xff; 32];
821        max[31] = 0x7f;
822        assert_eq!(Int256::MAX.to_le_bytes(), max);
823
824        let mut one = [0; 32];
825        one[0] = 1;
826        assert_eq!(Int256::from(1u128).to_le_bytes(), one);
827        // Python: `[b for b in (240282366920938463463374607431768124608).to_bytes(64, "little")]`
828        assert_eq!(
829            Int256::from(240282366920938463463374607431768124608u128).to_le_bytes(),
830            [
831                192, 172, 254, 255, 191, 221, 117, 246, 133, 59, 121, 165, 87, 179, 196, 180, 0, 0,
832                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
833            ]
834        );
835        assert_eq!(
836            Int256::from_be_bytes([
837                17, 4, 23, 32, 87, 67, 123, 200, 58, 91, 0, 38, 33, 21, 67, 78, 87, 76, 65, 54,
838                211, 201, 192, 7, 42, 233, 2, 240, 200, 115, 150, 240
839            ])
840            .to_le_bytes(),
841            [
842                240, 150, 115, 200, 240, 2, 233, 42, 7, 192, 201, 211, 54, 65, 76, 87, 78, 67, 21,
843                33, 38, 0, 91, 58, 200, 123, 67, 87, 32, 23, 4, 17
844            ]
845        );
846    }
847
848    #[test]
849    fn int256_is_zero_works() {
850        assert!(Int256::zero().is_zero());
851        assert!(Int256(I256::from(0u32)).is_zero());
852
853        assert!(!Int256::from(1u32).is_zero());
854        assert!(!Int256::from(123u32).is_zero());
855        assert!(!Int256::from(-123i32).is_zero());
856    }
857
858    #[test]
859    fn int256_is_negative_works() {
860        assert!(Int256::MIN.is_negative());
861        assert!(Int256::from(-123i32).is_negative());
862
863        assert!(!Int256::MAX.is_negative());
864        assert!(!Int256::zero().is_negative());
865        assert!(!Int256::from(123u32).is_negative());
866    }
867
868    #[test]
869    fn int256_wrapping_methods() {
870        // wrapping_add
871        assert_eq!(
872            Int256::from(2u32).wrapping_add(Int256::from(2u32)),
873            Int256::from(4u32)
874        ); // non-wrapping
875        assert_eq!(Int256::MAX.wrapping_add(Int256::from(1u32)), Int256::MIN); // wrapping
876
877        // wrapping_sub
878        assert_eq!(
879            Int256::from(7u32).wrapping_sub(Int256::from(5u32)),
880            Int256::from(2u32)
881        ); // non-wrapping
882        assert_eq!(Int256::MIN.wrapping_sub(Int256::from(1u32)), Int256::MAX); // wrapping
883
884        // wrapping_mul
885        assert_eq!(
886            Int256::from(3u32).wrapping_mul(Int256::from(2u32)),
887            Int256::from(6u32)
888        ); // non-wrapping
889        assert_eq!(
890            Int256::MAX.wrapping_mul(Int256::from(2u32)),
891            Int256::from(-2i32)
892        ); // wrapping
893
894        // wrapping_pow
895        assert_eq!(Int256::from(2u32).wrapping_pow(3), Int256::from(8u32)); // non-wrapping
896        assert_eq!(Int256::MAX.wrapping_pow(2), Int256::from(1u32)); // wrapping
897    }
898
899    #[test]
900    fn int256_json() {
901        let orig = Int256::from(1234567890987654321u128);
902        let serialized = serde_json::to_vec(&orig).unwrap();
903        assert_eq!(serialized.as_slice(), b"\"1234567890987654321\"");
904        let parsed: Int256 = serde_json::from_slice(&serialized).unwrap();
905        assert_eq!(parsed, orig);
906    }
907
908    #[test]
909    fn int256_compare() {
910        let a = Int256::from(12345u32);
911        let b = Int256::from(23456u32);
912
913        assert!(a < b);
914        assert!(b > a);
915        assert_eq!(a, Int256::from(12345u32));
916    }
917
918    #[test]
919    #[allow(clippy::op_ref)]
920    fn int256_math() {
921        let a = Int256::from(-12345i32);
922        let b = Int256::from(23456u32);
923
924        // test + with owned and reference right hand side
925        assert_eq!(a + b, Int256::from(11111u32));
926        assert_eq!(a + &b, Int256::from(11111u32));
927
928        // test - with owned and reference right hand side
929        assert_eq!(b - a, Int256::from(35801u32));
930        assert_eq!(b - &a, Int256::from(35801u32));
931
932        // test += with owned and reference right hand side
933        let mut c = Int256::from(300000u32);
934        c += b;
935        assert_eq!(c, Int256::from(323456u32));
936        let mut d = Int256::from(300000u32);
937        d += &b;
938        assert_eq!(d, Int256::from(323456u32));
939
940        // test -= with owned and reference right hand side
941        let mut c = Int256::from(300000u32);
942        c -= b;
943        assert_eq!(c, Int256::from(276544u32));
944        let mut d = Int256::from(300000u32);
945        d -= &b;
946        assert_eq!(d, Int256::from(276544u32));
947
948        // test - with negative result
949        assert_eq!(a - b, Int256::from(-35801i32));
950    }
951
952    #[test]
953    #[should_panic]
954    fn int256_add_overflow_panics() {
955        let _ = Int256::MAX + Int256::from(12u32);
956    }
957
958    #[test]
959    #[allow(clippy::op_ref)]
960    fn int256_sub_works() {
961        assert_eq!(Int256::from(2u32) - Int256::from(1u32), Int256::from(1u32));
962        assert_eq!(Int256::from(2u32) - Int256::from(0u32), Int256::from(2u32));
963        assert_eq!(Int256::from(2u32) - Int256::from(2u32), Int256::from(0u32));
964        assert_eq!(Int256::from(2u32) - Int256::from(3u32), Int256::from(-1i32));
965
966        // works for refs
967        let a = Int256::from(10u32);
968        let b = Int256::from(3u32);
969        let expected = Int256::from(7u32);
970        assert_eq!(a - b, expected);
971        assert_eq!(a - &b, expected);
972        assert_eq!(&a - b, expected);
973        assert_eq!(&a - &b, expected);
974    }
975
976    #[test]
977    #[should_panic]
978    fn int256_sub_overflow_panics() {
979        let _ = Int256::MIN + Int256::one() - Int256::from(2u32);
980    }
981
982    #[test]
983    fn int256_sub_assign_works() {
984        let mut a = Int256::from(14u32);
985        a -= Int256::from(2u32);
986        assert_eq!(a, Int256::from(12u32));
987
988        // works for refs
989        let mut a = Int256::from(10u32);
990        let b = Int256::from(3u32);
991        let expected = Int256::from(7u32);
992        a -= &b;
993        assert_eq!(a, expected);
994    }
995
996    #[test]
997    #[allow(clippy::op_ref)]
998    fn int256_mul_works() {
999        assert_eq!(Int256::from(2u32) * Int256::from(3u32), Int256::from(6u32));
1000        assert_eq!(Int256::from(2u32) * Int256::zero(), Int256::zero());
1001
1002        // works for refs
1003        let a = Int256::from(11u32);
1004        let b = Int256::from(3u32);
1005        let expected = Int256::from(33u32);
1006        assert_eq!(a * b, expected);
1007        assert_eq!(a * &b, expected);
1008        assert_eq!(&a * b, expected);
1009        assert_eq!(&a * &b, expected);
1010    }
1011
1012    #[test]
1013    fn int256_mul_assign_works() {
1014        let mut a = Int256::from(14u32);
1015        a *= Int256::from(2u32);
1016        assert_eq!(a, Int256::from(28u32));
1017
1018        // works for refs
1019        let mut a = Int256::from(10u32);
1020        let b = Int256::from(3u32);
1021        a *= &b;
1022        assert_eq!(a, Int256::from(30u32));
1023    }
1024
1025    #[test]
1026    fn int256_pow_works() {
1027        assert_eq!(Int256::from(2u32).pow(2), Int256::from(4u32));
1028        assert_eq!(Int256::from(2u32).pow(10), Int256::from(1024u32));
1029    }
1030
1031    #[test]
1032    #[should_panic]
1033    fn int256_pow_overflow_panics() {
1034        _ = Int256::MAX.pow(2u32);
1035    }
1036
1037    #[test]
1038    fn int256_checked_multiply_ratio_works() {
1039        let base = Int256::new(500);
1040
1041        // factor 1/1
1042        assert_eq!(base.checked_multiply_ratio(1i128, 1i128).unwrap(), base);
1043        assert_eq!(base.checked_multiply_ratio(3i128, 3i128).unwrap(), base);
1044        assert_eq!(
1045            base.checked_multiply_ratio(654321i128, 654321i128).unwrap(),
1046            base
1047        );
1048        assert_eq!(
1049            base.checked_multiply_ratio(i128::MAX, i128::MAX).unwrap(),
1050            base
1051        );
1052
1053        // factor 3/2
1054        assert_eq!(
1055            base.checked_multiply_ratio(3i128, 2i128).unwrap(),
1056            Int256::new(750)
1057        );
1058        assert_eq!(
1059            base.checked_multiply_ratio(333333i128, 222222i128).unwrap(),
1060            Int256::new(750)
1061        );
1062
1063        // factor 2/3 (integer division always floors the result)
1064        assert_eq!(
1065            base.checked_multiply_ratio(2i128, 3i128).unwrap(),
1066            Int256::new(333)
1067        );
1068        assert_eq!(
1069            base.checked_multiply_ratio(222222i128, 333333i128).unwrap(),
1070            Int256::new(333)
1071        );
1072
1073        // factor 5/6 (integer division always floors the result)
1074        assert_eq!(
1075            base.checked_multiply_ratio(5i128, 6i128).unwrap(),
1076            Int256::new(416)
1077        );
1078        assert_eq!(
1079            base.checked_multiply_ratio(100i128, 120i128).unwrap(),
1080            Int256::new(416)
1081        );
1082    }
1083
1084    #[test]
1085    fn int256_checked_multiply_ratio_does_not_panic() {
1086        assert_eq!(
1087            Int256::new(500i128).checked_multiply_ratio(1i128, 0i128),
1088            Err(CheckedMultiplyRatioError::DivideByZero),
1089        );
1090        assert_eq!(
1091            Int256::MAX.checked_multiply_ratio(Int256::MAX, 1i128),
1092            Err(CheckedMultiplyRatioError::Overflow),
1093        );
1094    }
1095
1096    #[test]
1097    fn int256_shr_works() {
1098        let original = Int256::from_be_bytes([
1099            0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
1100            0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 2u8, 0u8, 4u8, 2u8,
1101        ]);
1102
1103        let shifted = Int256::from_be_bytes([
1104            0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
1105            0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 128u8, 1u8, 0u8,
1106        ]);
1107
1108        assert_eq!(original >> 2u32, shifted);
1109    }
1110
1111    #[test]
1112    #[should_panic]
1113    fn int256_shr_overflow_panics() {
1114        let _ = Int256::from(1u32) >> 256u32;
1115    }
1116
1117    #[test]
1118    fn sum_works() {
1119        let nums = vec![
1120            Int256::from(17u32),
1121            Int256::from(123u32),
1122            Int256::from(540u32),
1123            Int256::from(82u32),
1124        ];
1125        let expected = Int256::from(762u32);
1126
1127        let sum_as_ref: Int256 = nums.iter().sum();
1128        assert_eq!(expected, sum_as_ref);
1129
1130        let sum_as_owned: Int256 = nums.into_iter().sum();
1131        assert_eq!(expected, sum_as_owned);
1132    }
1133
1134    #[test]
1135    fn int256_methods() {
1136        // checked_*
1137        assert!(matches!(
1138            Int256::MAX.checked_add(Int256::from(1u32)),
1139            Err(OverflowError { .. })
1140        ));
1141        assert_eq!(
1142            Int256::from(1u32).checked_add(Int256::from(1u32)),
1143            Ok(Int256::from(2u32)),
1144        );
1145        assert!(matches!(
1146            Int256::MIN.checked_sub(Int256::from(1u32)),
1147            Err(OverflowError { .. })
1148        ));
1149        assert_eq!(
1150            Int256::from(2u32).checked_sub(Int256::from(1u32)),
1151            Ok(Int256::from(1u32)),
1152        );
1153        assert!(matches!(
1154            Int256::MAX.checked_mul(Int256::from(2u32)),
1155            Err(OverflowError { .. })
1156        ));
1157        assert_eq!(
1158            Int256::from(2u32).checked_mul(Int256::from(2u32)),
1159            Ok(Int256::from(4u32)),
1160        );
1161        assert!(matches!(
1162            Int256::MAX.checked_pow(2u32),
1163            Err(OverflowError { .. })
1164        ));
1165        assert_eq!(Int256::from(2u32).checked_pow(3u32), Ok(Int256::from(8u32)),);
1166        assert_eq!(
1167            Int256::MAX.checked_div(Int256::from(0u32)),
1168            Err(DivisionError::DivideByZero)
1169        );
1170        assert_eq!(
1171            Int256::from(6u32).checked_div(Int256::from(2u32)),
1172            Ok(Int256::from(3u32)),
1173        );
1174        assert_eq!(
1175            Int256::MAX.checked_div_euclid(Int256::from(0u32)),
1176            Err(DivisionError::DivideByZero)
1177        );
1178        assert_eq!(
1179            Int256::from(6u32).checked_div_euclid(Int256::from(2u32)),
1180            Ok(Int256::from(3u32)),
1181        );
1182        assert_eq!(
1183            Int256::from(7u32).checked_div_euclid(Int256::from(2u32)),
1184            Ok(Int256::from(3u32)),
1185        );
1186        assert!(matches!(
1187            Int256::MAX.checked_rem(Int256::from(0u32)),
1188            Err(DivideByZeroError { .. })
1189        ));
1190        // checked_* with negative numbers
1191        assert_eq!(
1192            Int256::from(-12i32).checked_div(Int256::from(10i32)),
1193            Ok(Int256::from(-1i32)),
1194        );
1195        assert_eq!(
1196            Int256::from(-2i32).checked_pow(3u32),
1197            Ok(Int256::from(-8i32)),
1198        );
1199        assert_eq!(
1200            Int256::from(-6i32).checked_mul(Int256::from(-7i32)),
1201            Ok(Int256::from(42i32)),
1202        );
1203        assert_eq!(
1204            Int256::from(-2i32).checked_add(Int256::from(3i32)),
1205            Ok(Int256::from(1i32)),
1206        );
1207        assert_eq!(
1208            Int256::from(-1i32).checked_div_euclid(Int256::from(-2i32)),
1209            Ok(Int256::from(1u32)),
1210        );
1211
1212        // saturating_*
1213        assert_eq!(Int256::MAX.saturating_add(Int256::from(1u32)), Int256::MAX);
1214        assert_eq!(Int256::MIN.saturating_sub(Int256::from(1u32)), Int256::MIN);
1215        assert_eq!(Int256::MAX.saturating_mul(Int256::from(2u32)), Int256::MAX);
1216        assert_eq!(Int256::from(4u32).saturating_pow(2u32), Int256::from(16u32));
1217        assert_eq!(Int256::MAX.saturating_pow(2u32), Int256::MAX);
1218    }
1219
1220    #[test]
1221    #[allow(clippy::op_ref)]
1222    fn int256_implements_rem() {
1223        let a = Int256::from(10u32);
1224        assert_eq!(a % Int256::from(10u32), Int256::zero());
1225        assert_eq!(a % Int256::from(2u32), Int256::zero());
1226        assert_eq!(a % Int256::from(1u32), Int256::zero());
1227        assert_eq!(a % Int256::from(3u32), Int256::from(1u32));
1228        assert_eq!(a % Int256::from(4u32), Int256::from(2u32));
1229
1230        assert_eq!(
1231            Int256::from(-12i32) % Int256::from(10i32),
1232            Int256::from(-2i32)
1233        );
1234        assert_eq!(
1235            Int256::from(12i32) % Int256::from(-10i32),
1236            Int256::from(2i32)
1237        );
1238        assert_eq!(
1239            Int256::from(-12i32) % Int256::from(-10i32),
1240            Int256::from(-2i32)
1241        );
1242
1243        // works for refs
1244        let a = Int256::from(10u32);
1245        let b = Int256::from(3u32);
1246        let expected = Int256::from(1u32);
1247        assert_eq!(a % b, expected);
1248        assert_eq!(a % &b, expected);
1249        assert_eq!(&a % b, expected);
1250        assert_eq!(&a % &b, expected);
1251    }
1252
1253    #[test]
1254    #[should_panic(expected = "divisor of zero")]
1255    fn int256_rem_panics_for_zero() {
1256        let _ = Int256::from(10u32) % Int256::zero();
1257    }
1258
1259    #[test]
1260    fn int256_rem_assign_works() {
1261        let mut a = Int256::from(30u32);
1262        a %= Int256::from(4u32);
1263        assert_eq!(a, Int256::from(2u32));
1264
1265        // works for refs
1266        let mut a = Int256::from(25u32);
1267        let b = Int256::from(6u32);
1268        a %= &b;
1269        assert_eq!(a, Int256::from(1u32));
1270    }
1271
1272    #[test]
1273    fn int256_shr() {
1274        let x: Int256 = 0x8000_0000_0000_0000_0000_0000_0000_0000u128.into();
1275        assert_eq!(x >> 0, x); // right shift by 0 should be no-op
1276        assert_eq!(
1277            x >> 1,
1278            Int256::from(0x4000_0000_0000_0000_0000_0000_0000_0000u128)
1279        );
1280        assert_eq!(
1281            x >> 4,
1282            Int256::from(0x0800_0000_0000_0000_0000_0000_0000_0000u128)
1283        );
1284        // right shift of MIN value by the maximum shift value should result in -1 (filled with 1s)
1285        assert_eq!(
1286            Int256::MIN >> (core::mem::size_of::<Int256>() as u32 * 8 - 1),
1287            -Int256::one()
1288        );
1289    }
1290
1291    #[test]
1292    fn int256_shl() {
1293        let x: Int256 = 0x0800_0000_0000_0000_0000_0000_0000_0000u128.into();
1294        assert_eq!(x << 0, x); // left shift by 0 should be no-op
1295        assert_eq!(
1296            x << 1,
1297            Int256::from(0x1000_0000_0000_0000_0000_0000_0000_0000u128)
1298        );
1299        assert_eq!(
1300            x << 4,
1301            Int256::from(0x8000_0000_0000_0000_0000_0000_0000_0000u128)
1302        );
1303        // left shift by by the maximum shift value should result in MIN
1304        assert_eq!(
1305            Int256::one() << (core::mem::size_of::<Int256>() as u32 * 8 - 1),
1306            Int256::MIN
1307        );
1308    }
1309
1310    #[test]
1311    fn int256_abs_diff_works() {
1312        let a = Int256::from(42u32);
1313        let b = Int256::from(5u32);
1314        let expected = Uint256::from(37u32);
1315        assert_eq!(a.abs_diff(b), expected);
1316        assert_eq!(b.abs_diff(a), expected);
1317
1318        let c = Int256::from(-5i32);
1319        assert_eq!(b.abs_diff(c), Uint256::from(10u32));
1320        assert_eq!(c.abs_diff(b), Uint256::from(10u32));
1321    }
1322
1323    #[test]
1324    fn int256_abs_works() {
1325        let a = Int256::from(42i32);
1326        assert_eq!(a.abs(), a);
1327
1328        let b = Int256::from(-42i32);
1329        assert_eq!(b.abs(), a);
1330
1331        assert_eq!(Int256::zero().abs(), Int256::zero());
1332        assert_eq!((Int256::MIN + Int256::one()).abs(), Int256::MAX);
1333    }
1334
1335    #[test]
1336    fn int256_unsigned_abs_works() {
1337        assert_eq!(Int256::zero().unsigned_abs(), Uint256::zero());
1338        assert_eq!(Int256::one().unsigned_abs(), Uint256::one());
1339        assert_eq!(
1340            Int256::MIN.unsigned_abs(),
1341            Uint256::from_be_bytes(Int256::MAX.to_be_bytes()) + Uint256::one()
1342        );
1343
1344        let v = Int256::from(-42i32);
1345        assert_eq!(v.unsigned_abs(), v.abs_diff(Int256::zero()));
1346    }
1347
1348    #[test]
1349    #[should_panic = "attempt to calculate absolute value with overflow"]
1350    fn int256_abs_min_panics() {
1351        _ = Int256::MIN.abs();
1352    }
1353
1354    #[test]
1355    #[should_panic = "attempt to negate with overflow"]
1356    fn int256_neg_min_panics() {
1357        _ = -Int256::MIN;
1358    }
1359
1360    #[test]
1361    fn int256_partial_eq() {
1362        let test_cases = [(1, 1, true), (42, 42, true), (42, 24, false), (0, 0, true)]
1363            .into_iter()
1364            .map(|(lhs, rhs, expected): (u64, u64, bool)| {
1365                (Int256::from(lhs), Int256::from(rhs), expected)
1366            });
1367
1368        #[allow(clippy::op_ref)]
1369        for (lhs, rhs, expected) in test_cases {
1370            assert_eq!(lhs == rhs, expected);
1371            assert_eq!(&lhs == rhs, expected);
1372            assert_eq!(lhs == &rhs, expected);
1373            assert_eq!(&lhs == &rhs, expected);
1374        }
1375    }
1376}