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