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