bobcat_maths/
lib.rs

1#![cfg_attr(not(feature = "std"), no_std)]
2
3use core::{
4    cmp::{Eq, Ordering},
5    fmt::{Debug, Error as FmtError, Formatter},
6    ops::{
7        Add, AddAssign, BitAnd, BitOr, BitOrAssign, BitXor, Deref, DerefMut, Div, Index, IndexMut,
8        Mul, MulAssign, Neg, Not, Rem, Shl, ShlAssign, Shr, ShrAssign, Sub, SubAssign,
9    },
10};
11
12use num_traits::{One, Zero};
13
14#[cfg(feature = "borsh")]
15use borsh::{BorshDeserialize, BorshSerialize};
16
17#[cfg(feature = "alloc")]
18extern crate alloc;
19
20#[cfg(feature = "alloc")]
21use alloc::{string::String, vec};
22
23pub type Address = [u8; 20];
24
25#[link(wasm_import_module = "vm_hooks")]
26#[cfg(not(feature = "alloy-enabled"))]
27unsafe extern "C" {
28    fn math_div(x: *mut u8, y: *const u8);
29    fn math_mod(x: *mut u8, y: *const u8);
30    fn math_add_mod(a: *mut u8, b: *const u8, c: *const u8);
31    fn math_mul_mod(a: *mut u8, b: *const u8, c: *const u8);
32}
33
34#[cfg(feature = "ruint-enabled")]
35use alloy_primitives::{ruint, U256};
36
37#[cfg(feature = "alloy-enabled")]
38mod alloy {
39    use core::ptr::copy_nonoverlapping;
40
41    pub(crate) use alloy_primitives::U256;
42
43    #[cfg(test)]
44    pub(crate) use alloy_primitives::I256;
45
46    pub(crate) unsafe fn math_div(out: *mut u8, y: *const u8) {
47        unsafe {
48            let x = U256::from_be_slice(&*(out as *const [u8; 32]));
49            let y = U256::from_be_slice(&*(y as *const [u8; 32]));
50            let z = if y.is_zero() {
51                // TODO: I think the node returns 0 when this is the case.
52                U256::ZERO
53            } else {
54                x / y
55            };
56            copy_nonoverlapping(z.to_be_bytes::<32>().as_ptr(), out, 32);
57        }
58    }
59
60    pub(crate) unsafe fn math_mod(out: *mut u8, y: *const u8) {
61        unsafe {
62            let x = U256::from_be_slice(&*(out as *const [u8; 32]));
63            let y = U256::from_be_slice(&*(y as *const [u8; 32]));
64            let z = x % y;
65            copy_nonoverlapping(z.to_be_bytes::<32>().as_ptr(), out, 32);
66        }
67    }
68
69    pub(crate) unsafe fn math_add_mod(a: *mut u8, b: *const u8, c: *const u8) {
70        unsafe {
71            let x = U256::from_be_slice(&*(a as *const [u8; 32]));
72            let y = U256::from_be_slice(&*(b as *const [u8; 32]));
73            let z = U256::from_be_slice(&*(c as *const [u8; 32]));
74            let x = x.add_mod(y, z);
75            copy_nonoverlapping(x.to_be_bytes::<32>().as_ptr(), a, 32);
76        }
77    }
78
79    pub(crate) unsafe fn math_mul_mod(a: *mut u8, b: *const u8, c: *const u8) {
80        unsafe {
81            let x = U256::from_be_slice(&*(a as *const [u8; 32]));
82            let y = U256::from_be_slice(&*(b as *const [u8; 32]));
83            let z = U256::from_be_slice(&*(c as *const [u8; 32]));
84            let x = x.mul_mod(y, z);
85            copy_nonoverlapping(x.to_be_bytes::<32>().as_ptr(), a, 32);
86        }
87    }
88}
89
90#[cfg(feature = "alloy-enabled")]
91use alloy::*;
92
93#[derive(Copy, Clone, PartialEq, Hash)]
94#[cfg_attr(feature = "proptest", derive(proptest_derive::Arbitrary))]
95#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
96#[cfg_attr(feature = "borsh", derive(BorshDeserialize, BorshSerialize))]
97#[repr(transparent)]
98pub struct U(pub [u8; 32]);
99
100#[derive(Copy, Clone, PartialEq, Hash, Debug)]
101#[cfg_attr(feature = "proptest", derive(proptest_derive::Arbitrary))]
102#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
103#[cfg_attr(feature = "borsh", derive(BorshDeserialize, BorshSerialize))]
104#[repr(transparent)]
105pub struct I(pub [u8; 32]);
106
107pub fn wrapping_div(x: &U, y: &U) -> U {
108    assert!(y.is_some(), "divide by zero");
109    let mut b = *x;
110    unsafe { math_div(b.as_mut_ptr(), y.as_ptr()) }
111    b
112}
113
114fn wrapping_div_quo_rem_b<const C: usize>(x: &[u8; C], denom: &[u8; C]) -> ([u8; C], [u8; C]) {
115    if denom == &[0u8; C] {
116        return ([0u8; C], [0u8; C]);
117    }
118    let mut q = [0u8; C];
119    let mut r = [0u8; C];
120    let mut one = [0u8; C];
121    one[C - 1] = 1;
122    let mut two = [0u8; C];
123    two[C - 1] = 2;
124    let mut i = 0;
125    while i < C * 8 {
126        let bit = (x[i / 8] >> (7 - (i % 8))) & 1;
127        r = wrapping_mul_b::<C>(&r, &two);
128        if bit == 1 {
129            r = wrapping_add_b::<C>(&r, &one);
130        }
131        if r >= *denom {
132            r = wrapping_sub_b::<C>(&r, denom);
133            q[i / 8] |= 1 << (7 - (i % 8));
134        }
135        i += 1;
136    }
137    (q, r)
138}
139
140pub fn const_wrapping_div(x: &U, y: &U) -> U {
141    U(wrapping_div_quo_rem_b::<32>(&x.0, &y.0).0)
142}
143
144#[cfg_attr(test, mutants::skip)]
145pub fn checked_div(x: &U, y: &U) -> Option<U> {
146    if y.is_zero() {
147        None
148    } else {
149        Some(wrapping_div(x, y))
150    }
151}
152
153pub fn modd(x: &U, y: &U) -> U {
154    let mut b = *x;
155    unsafe { math_mod(b.as_mut_ptr(), y.as_ptr()) }
156    b
157}
158
159pub fn mul_mod(mut x: U, y: &U, z: &U) -> U {
160    unsafe { math_mul_mod(x.as_mut_ptr(), y.as_ptr(), z.as_ptr()) }
161    x
162}
163
164const fn wrapping_add_b<const C: usize>(x: &[u8; C], y: &[u8; C]) -> [u8; C] {
165    let mut r = [0u8; C];
166    let mut c = 0;
167    let mut i = C - 1;
168    loop {
169        let s = x[i] as u16 + y[i] as u16 + c;
170        r[i] = s as u8;
171        c = s >> 8;
172        if i == 0 {
173            break;
174        }
175        i -= 1;
176    }
177    r
178}
179
180pub const fn wrapping_add(x: &U, y: &U) -> U {
181    U(wrapping_add_b(&x.0, &y.0))
182}
183
184#[cfg_attr(test, mutants::skip)]
185pub fn checked_add(x: &U, y: &U) -> Option<U> {
186    if x > &(U::MAX - *y) {
187        None
188    } else {
189        let z = x.add_mod(y, &U::MAX);
190        if z.is_zero() && (x.is_some() || y.is_some()) {
191            Some(U::MAX)
192        } else {
193            Some(z)
194        }
195    }
196}
197
198#[cfg_attr(test, mutants::skip)]
199pub fn saturating_add(x: &U, y: &U) -> U {
200    checked_add(x, y).unwrap_or(U::MAX)
201}
202
203const fn wrapping_sub_b<const C: usize>(x: &[u8; C], y: &[u8; C]) -> [u8; C] {
204    let mut neg_y = *y;
205    let mut i = 0;
206    while i < C {
207        neg_y[i] = !neg_y[i];
208        i += 1;
209    }
210    let mut c = 1u16;
211    let mut i = C - 1;
212    loop {
213        let sum = neg_y[i] as u16 + c;
214        neg_y[i] = sum as u8;
215        c = sum >> 8;
216        if i == 0 {
217            break;
218        }
219        i -= 1;
220    }
221    wrapping_add_b(x, &neg_y)
222}
223
224pub const fn wrapping_sub(x: &U, y: &U) -> U {
225    U(wrapping_sub_b::<32>(&x.0, &y.0))
226}
227
228pub fn saturating_sub(x: &U, y: &U) -> U {
229    checked_sub(x, y).unwrap_or(U::ZERO)
230}
231
232#[cfg_attr(test, mutants::skip)]
233pub fn checked_sub(x: &U, y: &U) -> Option<U> {
234    if x < y {
235        None
236    } else {
237        Some(wrapping_sub(x, y))
238    }
239}
240
241pub const fn wrapping_mul_b<const C: usize>(x: &[u8; C], y: &[u8; C]) -> [u8; C] {
242    let mut r = [0u8; C];
243    let mut i = 0;
244    while i < C {
245        let mut c = 0u16;
246        let mut j = 0;
247        while j < C {
248            let i_r = i + j;
249            if i_r >= C {
250                break;
251            }
252            let r_idx = C - 1 - i_r;
253            let xi = x[C - 1 - i] as u16;
254            let yj = y[C - 1 - j] as u16;
255            let prod = xi * yj + r[r_idx] as u16 + c;
256            r[r_idx] = prod as u8;
257            c = prod >> 8;
258            j += 1;
259        }
260        if i + j < C {
261            let idx = 31 - (i + j);
262            r[idx] = r[idx] + c as u8;
263        }
264        i += 1;
265    }
266    r
267}
268
269pub const fn wrapping_mul(x: &U, y: &U) -> U {
270    U(wrapping_mul_b(&x.0, &y.0))
271}
272
273#[cfg_attr(test, mutants::skip)]
274pub fn checked_mul(x: &U, y: &U) -> Option<U> {
275    if x.is_zero() || y.is_zero() {
276        return Some(U::ZERO);
277    }
278    if x > &(U::MAX / *y) {
279        None
280    } else {
281        let z = x.mul_mod(y, &U::MAX);
282        if z.is_zero() {
283            Some(U::MAX)
284        } else {
285            Some(z)
286        }
287    }
288}
289
290pub fn saturating_mul(x: &U, y: &U) -> U {
291    checked_mul(x, y).unwrap_or(U::MAX)
292}
293
294fn gcd(mut x: U, mut y: U) -> U {
295    while y.is_some() {
296        (x, y) = (y, x % y);
297    }
298    x
299}
300
301pub fn gcd_mul_div(x: &U, y: &U, denom: U) -> Option<(U, bool)> {
302    if denom.is_zero() {
303        return None;
304    }
305    let g1 = gcd(*x, denom);
306    let x_reduced = x / &g1;
307    let denom_reduced = denom / g1;
308    let g2 = gcd(*y, denom_reduced);
309    let y_reduced = y / &g2;
310    let denom_final = denom_reduced / g2;
311    let product = x_reduced.checked_mul(&y_reduced)?;
312    let result = (x_reduced * y_reduced) / denom_final;
313    let remainder = product % denom_final;
314    Some((result, remainder.is_some()))
315}
316
317pub fn gcd_mul_div_round_up(x: &U, y: &U, denom: U) -> Option<U> {
318    let (x, y) = gcd_mul_div(x, y, denom)?;
319    if x.is_max() && y {
320        return None;
321    }
322    Some(if y { x + U::ONE } else { x })
323}
324
325pub fn widening_mul(x: &U, y: &U) -> [u8; 64] {
326    let shift_128 = &U([
327        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
328        0, 0,
329    ]);
330    let x_hi = x / shift_128;
331    let x_lo = x % shift_128;
332    let y_hi = y / shift_128;
333    let y_lo = y % shift_128;
334    let t0 = x_lo.mul_mod(&y_lo, &U::MAX);
335    let t1 = x_hi.mul_mod(&y_lo, &U::MAX);
336    let t2 = x_lo.mul_mod(&y_hi, &U::MAX);
337    let t3 = x_hi.mul_mod(&y_hi, &U::MAX);
338    let t0_hi = &t0 / shift_128;
339    let t0_lo = &t0 % shift_128;
340    let t1_hi = &t1 / shift_128;
341    let t1_lo = &t1 % shift_128;
342    let t2_hi = &t2 / shift_128;
343    let t2_lo = &t2 % shift_128;
344    let mid = (t0_hi + t1_lo) + t2_lo;
345    let mid_hi = &mid / shift_128;
346    let mid_lo = &mid % shift_128;
347    let mid_lo_shifted = mid_lo.mul_mod(shift_128, &U::MAX);
348    let out_low = t0_lo + mid_lo_shifted;
349    let out_high = t3 + t1_hi + t2_hi + mid_hi;
350    let mut o = [0u8; 64];
351    o[..32].copy_from_slice(&out_high.0);
352    o[32..].copy_from_slice(&out_low.0);
353    o
354}
355
356/// Widening then truncate mul div that's cheaper in codesize that's safe for cold
357/// operations. The most expensive in gas costs.
358pub fn widening_mul_div(x: &U, y: &U, denom: U) -> Option<(U, bool)> {
359    if denom.is_zero() {
360        return None;
361    }
362    if x.is_zero() {
363        return Some((U::ZERO, false));
364    }
365    // We use a boring method if the overflow wouldn't happen:
366    if wrapping_div(&U::MAX, x) >= *y {
367        let l = wrapping_mul(x, y);
368        let carry = x.mul_mod(y, &denom).is_some();
369        return Some((wrapping_div(&l, &denom), carry));
370    }
371    let x = widening_mul(x, y);
372    let mut d = [0u8; 64];
373    d[32..].copy_from_slice(&denom.0);
374    let (q, rem) = wrapping_div_quo_rem_b::<64>(&x, &d);
375    if q[..32] != [0u8; 32] {
376        return None;
377    }
378    let l: [u8; 32] = q[32..].try_into().unwrap();
379    let l = U::from(l);
380    let has_carry = rem[32..] != [0u8; 32];
381    Some((l, has_carry))
382}
383
384pub fn widening_mul_div_round_up(x: &U, y: &U, denom: U) -> Option<U> {
385    let (x, y) = widening_mul_div(x, y, denom)?;
386    if x.is_max() && y {
387        return None;
388    }
389    Some(if y { x + U::ONE } else { x })
390}
391
392/// Muldiv that's used in practice by Uniswap and other on-chain dapps.
393/// Middling in gas costs.
394pub fn mul_div(x: &U, y: &U, mut denom: U) -> Option<(U, bool)> {
395    // Implemented from https://xn--2-umb.com/21/muldiv/
396    if denom.is_zero() {
397        return None;
398    }
399    if x.is_zero() {
400        return Some((U::ZERO, false));
401    }
402    let mut prod0 = wrapping_mul(x, y);
403    let mm = mul_mod(*x, y, &U::MAX);
404    let mut prod1 = wrapping_sub(
405        &wrapping_sub(&mm, &prod0),
406        &if prod0 > mm { U::ONE } else { U::ZERO },
407    );
408    if prod1.is_zero() {
409        let carry = mul_mod(*x, y, &denom).is_some();
410        return Some((wrapping_div(&prod0, &denom), carry));
411    }
412    if prod1 >= denom {
413        return None;
414    }
415    let remainder = mul_mod(*x, y, &denom);
416    let carry = remainder.is_some();
417    if remainder > prod0 {
418        prod1 -= U::ONE;
419    }
420    prod0 = wrapping_sub(&prod0, &remainder);
421    let mut twos = wrapping_sub(&U::ZERO, &denom) & denom;
422    denom = wrapping_div(&denom, &twos);
423    prod0 = wrapping_div(&prod0, &twos);
424    twos = wrapping_add(
425        &wrapping_div(&wrapping_sub(&U::ZERO, &twos), &twos),
426        &U::ONE,
427    );
428    prod0 = prod0 | wrapping_mul(&prod1, &twos);
429    let mut inv = wrapping_mul(&U::from(3u32), &denom) ^ U::from(2u32);
430    for _ in 0..6 {
431        inv = wrapping_mul(
432            &inv,
433            &wrapping_sub(&U::from(2u32), &wrapping_mul(&denom, &inv)),
434        );
435    }
436    Some((wrapping_mul(&prod0, &inv), carry))
437}
438
439pub fn mul_div_round_up(x: &U, y: &U, denom_and_rem: U) -> Option<U> {
440    let (x, y) = mul_div(x, y, denom_and_rem)?;
441    if x.is_max() && y {
442        return None;
443    }
444    Some(if y { x + U::ONE } else { x })
445}
446
447/// The cheapest muldiv operation, but the most expensive in codesize muldiv.
448#[cfg(feature = "ruint-enabled")]
449pub fn ruint_mul_div(x: &U, y: &U, denom: U) -> Option<(U, bool)> {
450    if denom.is_zero() {
451        return None;
452    }
453    let x = U256::from_be_slice(x.as_slice());
454    let y = U256::from_be_slice(y.as_slice());
455    let mut denom = U256::from_be_slice(denom.as_slice());
456    let mut mul_and_quo = x.widening_mul::<256, 4, 512, 8>(y);
457    unsafe {
458        ruint::algorithms::div(mul_and_quo.as_limbs_mut(), denom.as_limbs_mut());
459    }
460    let limbs = mul_and_quo.into_limbs();
461    if limbs[4..] != [0_u64; 4] {
462        return None;
463    }
464    let has_carry = !denom.is_zero();
465    let r = U(U256::from_limbs_slice(&limbs[0..4]).to_be_bytes::<32>());
466    Some((r, has_carry))
467}
468
469#[cfg(feature = "ruint-enabled")]
470pub fn ruint_mul_div_round_up(x: &U, y: &U, denom: U) -> Option<U> {
471    let (x, y) = ruint_mul_div(x, y, denom)?;
472    if x.is_max() && y {
473        return None;
474    }
475    Some(if y { x + U::ONE } else { x })
476}
477
478/// Rooti iterative method based on the 9lives implementation. Using this
479/// operation is the equivalent of pow(x, 1/n).
480pub fn checked_rooti(x: U, n: u32) -> Option<U> {
481    if n == 0 {
482        return None;
483    }
484    if x.is_zero() {
485        return Some(U::ZERO);
486    }
487    if n == 1 {
488        return Some(x);
489    }
490    // Due to the nature of this iterative method, we hardcode some
491    // values to have consistency with the 9lives reference.
492    if x == U::from(4u32) && n == 2 {
493        return Some(U::from(2u32));
494    }
495    let n_u256 = U::from(n);
496    let n_1 = n_u256 - U::ONE;
497    // Initial guess: 2^ceil(bits(x)/n)
498    let mut b = 0;
499    let mut t = x;
500    while t.is_some() {
501        b += 1;
502        t >>= 1;
503    }
504    let shift = (b + n as usize - 1) / n as usize;
505    let mut z = U::ONE << shift;
506    let mut y = x;
507    // Newton's method:
508    while z < y {
509        y = z;
510        let p = z.checked_pow(&n_1)?;
511        z = ((x / p) + (z * n_1)) / n_u256;
512    }
513    // Correct overshoot:
514    if y.checked_pow(&n_u256)? > x {
515        y -= U::ONE;
516    }
517    Some(y)
518}
519
520pub fn wrapping_pow(x: &U, exp: &U) -> U {
521    let mut r = U::ONE;
522    let mut i = U::ZERO;
523    while &i < exp {
524        r = wrapping_mul(&r, x);
525        i += U::ONE;
526    }
527    r
528}
529
530pub fn checked_pow(x: &U, exp: &U) -> Option<U> {
531    let mut r = U::ONE;
532    let mut i = U::ZERO;
533    while &i < exp {
534        r = checked_mul(&r, x)?;
535        i += U::ONE;
536    }
537    Some(r)
538}
539
540impl Add for U {
541    type Output = U;
542
543    fn add(self, rhs: U) -> U {
544        cfg_if::cfg_if! {
545            if #[cfg(debug_assertions)] {
546                checked_add(&self, &rhs).expect("overflow when add")
547            } else {
548                wrapping_add(&self, &rhs)
549            }
550        }
551    }
552}
553
554impl Add for &U {
555    type Output = U;
556
557    fn add(self, rhs: &U) -> U {
558        cfg_if::cfg_if! {
559            if #[cfg(debug_assertions)] {
560                checked_add(self, rhs).expect("overflow when add")
561            } else {
562                wrapping_add(self, rhs)
563            }
564        }
565    }
566}
567
568impl AddAssign for U {
569    fn add_assign(&mut self, o: Self) {
570        *self = *self + o;
571    }
572}
573
574impl Sub for U {
575    type Output = U;
576
577    fn sub(self, rhs: U) -> U {
578        cfg_if::cfg_if! {
579            if #[cfg(debug_assertions)] {
580                checked_sub(&self, &rhs).expect("overflow when sub")
581            } else {
582                wrapping_sub(&self, &rhs)
583            }
584        }
585    }
586}
587
588impl Sub for &U {
589    type Output = U;
590
591    fn sub(self, rhs: &U) -> U {
592        cfg_if::cfg_if! {
593            if #[cfg(debug_assertions)] {
594                checked_sub(self, rhs).expect("overflow when sub")
595            } else {
596                wrapping_sub(self, rhs)
597            }
598        }
599    }
600}
601
602impl SubAssign for U {
603    fn sub_assign(&mut self, o: Self) {
604        *self = *self - o;
605    }
606}
607
608impl Mul for U {
609    type Output = U;
610
611    fn mul(self, rhs: U) -> U {
612        cfg_if::cfg_if! {
613            if #[cfg(debug_assertions)] {
614                checked_mul(&self, &rhs).expect("overflow when mul")
615            } else {
616                wrapping_mul(&self, &rhs)
617            }
618        }
619    }
620}
621
622impl Mul for &U {
623    type Output = U;
624
625    fn mul(self, rhs: &U) -> U {
626        cfg_if::cfg_if! {
627            if #[cfg(debug_assertions)] {
628                checked_mul(self, rhs).expect("overflow when mul")
629            } else {
630                wrapping_mul(self, rhs)
631            }
632        }
633    }
634}
635
636impl MulAssign for U {
637    fn mul_assign(&mut self, rhs: Self) {
638        *self = *self * rhs
639    }
640}
641
642impl Div for U {
643    type Output = U;
644
645    fn div(self, rhs: U) -> U {
646        cfg_if::cfg_if! {
647            if #[cfg(debug_assertions)] {
648                checked_div(&self, &rhs).expect("overflow when div")
649            } else {
650                wrapping_div(&self, &rhs)
651            }
652        }
653    }
654}
655
656impl Div for &U {
657    type Output = U;
658
659    fn div(self, rhs: &U) -> U {
660        cfg_if::cfg_if! {
661            if #[cfg(debug_assertions)] {
662                checked_div(self, rhs).expect("overflow when div")
663            } else {
664                wrapping_div(self, rhs)
665            }
666        }
667    }
668}
669
670impl Rem for U {
671    type Output = U;
672
673    fn rem(self, rhs: U) -> U {
674        modd(&self, &rhs)
675    }
676}
677
678impl Rem for &U {
679    type Output = U;
680
681    fn rem(self, rhs: &U) -> U {
682        modd(self, rhs)
683    }
684}
685
686impl Shl<usize> for U {
687    type Output = Self;
688
689    fn shl(self, shift: usize) -> Self::Output {
690        if shift >= 256 {
691            return U::ZERO;
692        }
693        let mut result = [0u8; 32];
694        let byte_shift = shift / 8;
695        let bit_shift = shift % 8;
696        if bit_shift == 0 {
697            for i in 0..(32 - byte_shift) {
698                result[i] = self.0[i + byte_shift];
699            }
700        } else {
701            let mut carry = 0u8;
702            for i in (byte_shift..32).rev() {
703                let src_idx = i;
704                let dst_idx = i - byte_shift;
705                let byte = self.0[src_idx];
706                result[dst_idx] = (byte << bit_shift) | carry;
707                carry = byte >> (8 - bit_shift);
708            }
709        }
710        U(result)
711    }
712}
713
714impl ShlAssign<usize> for U {
715    fn shl_assign(&mut self, rhs: usize) {
716        *self = *self << rhs
717    }
718}
719
720impl BitAnd for U {
721    type Output = Self;
722
723    fn bitand(self, rhs: Self) -> Self::Output {
724        let mut r = U::ZERO;
725        for i in 0..32 {
726            r[i] = self[i] & rhs[i];
727        }
728        r
729    }
730}
731
732impl BitOr for U {
733    type Output = Self;
734
735    fn bitor(self, rhs: Self) -> Self::Output {
736        let mut r = U::ZERO;
737        for i in 0..32 {
738            r[i] = self[i] | rhs[i];
739        }
740        r
741    }
742}
743
744impl BitXor for U {
745    type Output = Self;
746    fn bitxor(self, rhs: Self) -> Self::Output {
747        let mut r = U::ZERO;
748        for i in 0..32 {
749            r[i] = self[i] ^ rhs[i];
750        }
751        r
752    }
753}
754
755impl BitOrAssign for U {
756    fn bitor_assign(&mut self, rhs: Self) {
757        *self = *self | rhs
758    }
759}
760
761impl Shr<usize> for U {
762    type Output = Self;
763
764    fn shr(self, shift: usize) -> Self::Output {
765        if shift >= 256 {
766            return U::ZERO;
767        }
768        let mut result = U::ZERO;
769        let byte_shift = shift / 8;
770        let bit_shift = shift % 8;
771        if bit_shift == 0 {
772            for i in byte_shift..32 {
773                result[i] = self.0[i - byte_shift];
774            }
775        } else {
776            let mut carry = 0u8;
777            for i in 0..(32 - byte_shift) {
778                let src_idx = i;
779                let dst_idx = i + byte_shift;
780                let byte = self.0[src_idx];
781                result[dst_idx] = (byte >> bit_shift) | carry;
782                carry = byte << (8 - bit_shift);
783            }
784        }
785        result
786    }
787}
788
789impl ShrAssign<usize> for U {
790    fn shr_assign(&mut self, rhs: usize) {
791        *self = *self >> rhs
792    }
793}
794
795impl Eq for U {}
796
797impl PartialOrd for U {
798    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
799        Some(self.cmp(other))
800    }
801}
802
803impl Ord for U {
804    fn cmp(&self, other: &Self) -> Ordering {
805        self.0.cmp(&other.0)
806    }
807}
808
809impl Debug for U {
810    fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
811        let mut b = [0u8; 20 * 2];
812        let Ok(s) = const_hex::encode_to_str(self.0, &mut b) else {
813            return Err(FmtError);
814        };
815        write!(f, "{s}")
816    }
817}
818
819impl Not for U {
820    type Output = Self;
821
822    fn not(mut self) -> Self::Output {
823        for i in 0..32 {
824            self[i] = !self[i]
825        }
826        self
827    }
828}
829
830impl Neg for U {
831    type Output = Self;
832
833    fn neg(self) -> Self {
834        let mut r = U::ZERO;
835        let mut carry = 1u16;
836        for i in (0..32).rev() {
837            let inverted = !self.0[i] as u16;
838            let sum = inverted + carry;
839            r[i] = sum as u8;
840            carry = sum >> 8;
841        }
842        r
843    }
844}
845
846impl U {
847    pub const ZERO: Self = U([0u8; 32]);
848
849    pub const MAX: Self = U([u8::MAX; 32]);
850
851    pub const ONE: Self = U([
852        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, 0, 0,
853        0, 1,
854    ]);
855
856    pub fn is_true(&self) -> bool {
857        self.0[31] == 1
858    }
859
860    pub const fn is_zero(&self) -> bool {
861        let mut i = 0;
862        while i < 32 {
863            if self.0[i] != 0 {
864                return false;
865            }
866            i += 1;
867        }
868        true
869    }
870
871    pub const fn is_max(&self) -> bool {
872        let mut i = 0;
873        while i < 32 {
874            if self.0[i] != u8::MAX {
875                return false;
876            }
877            i += 1;
878        }
879        true
880    }
881
882    pub fn is_some(&self) -> bool {
883        !self.is_zero()
884    }
885
886    pub fn trailing_zeros(&self) -> usize {
887        let mut count = 0;
888        for i in (0..32).rev() {
889            if self[i] == 0 {
890                count += 8;
891            } else {
892                count += self[i].trailing_zeros() as usize;
893                break;
894            }
895        }
896        count
897    }
898
899    pub fn as_slice(&self) -> &[u8; 32] {
900        &self.0
901    }
902
903    pub fn checked_add(&self, y: &Self) -> Option<Self> {
904        checked_add(self, y)
905    }
906
907    pub fn checked_mul(&self, y: &Self) -> Option<Self> {
908        checked_mul(self, y)
909    }
910
911    pub fn checked_sub(&self, y: &Self) -> Option<Self> {
912        checked_sub(self, y)
913    }
914
915    pub fn checked_div(&self, y: &Self) -> Option<Self> {
916        checked_div(self, y)
917    }
918
919    pub fn checked_pow(&self, exp: &U) -> Option<Self> {
920        checked_pow(self, exp)
921    }
922
923    pub fn wrapping_add(&self, y: &Self) -> U {
924        wrapping_add(self, y)
925    }
926
927    pub fn wrapping_sub(&self, y: &Self) -> U {
928        wrapping_sub(self, y)
929    }
930
931    pub fn wrapping_mul(&self, y: &Self) -> U {
932        wrapping_mul(self, y)
933    }
934
935    pub fn wrapping_div(&self, y: &Self) -> U {
936        wrapping_div(self, y)
937    }
938
939    pub fn saturating_add(&self, y: &Self) -> U {
940        saturating_add(self, y)
941    }
942
943    pub fn saturating_sub(&self, y: &Self) -> U {
944        saturating_sub(self, y)
945    }
946
947    pub fn saturating_mul(&self, y: &Self) -> U {
948        saturating_mul(self, y)
949    }
950
951    pub fn wrapping_neg(self) -> Self {
952        let mut x = self;
953        let mut carry = 1u8;
954        for b in x.iter_mut().rev() {
955            *b = (!*b).wrapping_add(carry);
956            carry = b.is_zero() as u8;
957        }
958        x
959    }
960
961    pub fn mul_div(&self, y: &Self, z: Self) -> Option<(Self, bool)> {
962        mul_div(self, y, z)
963    }
964
965    pub fn mul_div_round_up(&self, y: &Self, z: Self) -> Option<Self> {
966        mul_div_round_up(self, y, z)
967    }
968
969    pub fn widening_mul_div(&self, y: &Self, z: Self) -> Option<(Self, bool)> {
970        widening_mul_div(self, y, z)
971    }
972
973    pub fn widening_mul_div_round_up(&self, y: &Self, z: Self) -> Option<Self> {
974        widening_mul_div_round_up(self, y, z)
975    }
976
977    #[cfg(feature = "ruint-enabled")]
978    pub fn ruint_mul_div(&self, y: &Self, z: Self) -> Option<(Self, bool)> {
979        ruint_mul_div(self, y, z)
980    }
981
982    #[cfg(feature = "ruint-enabled")]
983    pub fn ruint_mul_div_round_up(&self, y: &Self, z: Self) -> Option<Self> {
984        ruint_mul_div_round_up(self, y, z)
985    }
986
987    pub fn gcd_mul_div(&self, y: &Self, z: Self) -> Option<(Self, bool)> {
988        gcd_mul_div(self, y, z)
989    }
990
991    pub fn gcd_mul_div_round_up(&self, y: &Self, z: Self) -> Option<Self> {
992        gcd_mul_div_round_up(self, y, z)
993    }
994
995    pub fn mul_mod(&self, y: &Self, z: &Self) -> Self {
996        mul_mod(*self, y, z)
997    }
998
999    pub fn add_mod(&self, y: &Self, z: &Self) -> Self {
1000        let mut b = self.0;
1001        unsafe { math_add_mod(b.as_mut_ptr(), y.as_ptr(), z.as_ptr()) }
1002        Self(b)
1003    }
1004
1005    pub fn checked_rooti(self, x: u32) -> Option<Self> {
1006        checked_rooti(self, x)
1007    }
1008}
1009
1010#[cfg(feature = "alloc")]
1011impl core::fmt::Display for U {
1012    fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
1013        let mut result = vec![0u8];
1014        for &byte in &self.0 {
1015            let mut carry = byte as u32;
1016            for digit in result.iter_mut() {
1017                let temp = (*digit as u32) * 256 + carry;
1018                *digit = (temp % 10) as u8;
1019                carry = temp / 10;
1020            }
1021            while carry > 0 {
1022                result.push((carry % 10) as u8);
1023                carry /= 10;
1024            }
1025        }
1026        if result.iter().all(|&d| d == 0) {
1027            return write!(f, "0");
1028        }
1029        write!(
1030            f,
1031            "{}",
1032            result
1033                .iter()
1034                .rev()
1035                .skip_while(|&&d| d == 0)
1036                .map(|&d| (d + b'0') as char)
1037                .collect::<String>()
1038        )
1039    }
1040}
1041
1042impl From<U> for [u8; 32] {
1043    fn from(x: U) -> Self {
1044        x.0
1045    }
1046}
1047
1048impl From<U> for bool {
1049    fn from(x: U) -> Self {
1050        x.0[31] == 1
1051    }
1052}
1053
1054impl From<&[u8; 32]> for &U {
1055    fn from(x: &[u8; 32]) -> Self {
1056        unsafe { &*(x as *const [u8; 32] as *const U) }
1057    }
1058}
1059
1060impl From<[u8; 32]> for U {
1061    fn from(x: [u8; 32]) -> Self {
1062        U(x)
1063    }
1064}
1065
1066impl Deref for U {
1067    type Target = [u8; 32];
1068
1069    fn deref(&self) -> &Self::Target {
1070        &self.0
1071    }
1072}
1073
1074impl DerefMut for U {
1075    fn deref_mut(&mut self) -> &mut Self::Target {
1076        &mut self.0
1077    }
1078}
1079
1080impl From<bool> for U {
1081    fn from(x: bool) -> Self {
1082        U::from(&[x as u8])
1083    }
1084}
1085
1086impl Zero for U {
1087    fn zero() -> Self {
1088        U::ZERO
1089    }
1090
1091    fn is_zero(&self) -> bool {
1092        self.0.iter().all(|&b| b == 0)
1093    }
1094}
1095
1096impl Default for U {
1097    fn default() -> Self {
1098        U::ZERO
1099    }
1100}
1101
1102impl One for U {
1103    fn one() -> Self {
1104        U::ONE
1105    }
1106}
1107
1108impl Index<usize> for U {
1109    type Output = u8;
1110
1111    fn index(&self, index: usize) -> &Self::Output {
1112        &self.0[index]
1113    }
1114}
1115
1116impl IndexMut<usize> for U {
1117    fn index_mut(&mut self, index: usize) -> &mut Self::Output {
1118        &mut self.0[index]
1119    }
1120}
1121
1122impl I {
1123    fn is_neg(&self) -> bool {
1124        self.0[0] & 0x80 != 0
1125    }
1126
1127    pub fn is_zero(&self) -> bool {
1128        *self == Self::ZERO
1129    }
1130
1131    pub fn is_some(&self) -> bool {
1132        !self.is_zero()
1133    }
1134
1135    pub fn as_slice(&self) -> &[u8; 32] {
1136        &self.0
1137    }
1138
1139    fn neg(&self) -> Self {
1140        let x = wrapping_add(&U(self.0.map(|b| !b)), &U::ONE);
1141        I(x.0)
1142    }
1143
1144    fn abs(self) -> U {
1145        if self.is_neg() {
1146            U(self.neg().0)
1147        } else {
1148            U(self.0)
1149        }
1150    }
1151}
1152
1153macro_rules! from_slices {
1154    ($($n:expr),+ $(,)?) => {
1155        $(
1156            impl From<&[u8; $n]> for U {
1157                fn from(x: &[u8; $n]) -> Self {
1158                    let mut b = [0u8; 32];
1159                    b[32 - $n..].copy_from_slice(x);
1160                    U(b)
1161                }
1162            }
1163
1164            impl From<[u8; $n]> for U {
1165                fn from(x: [u8; $n]) -> Self {
1166                    U::from(&x)
1167                }
1168            }
1169
1170            impl From<U> for [u8; $n] {
1171                fn from(x: U) -> Self {
1172                    unsafe { *(x.as_ptr().add(32 - $n) as *const [u8; $n]) }
1173                }
1174            }
1175        )+
1176    };
1177}
1178
1179from_slices!(
1180    1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26,
1181    27, 28, 29, 30, 31
1182);
1183
1184impl From<&U> for Address {
1185    fn from(x: &U) -> Self {
1186        (*x).into()
1187    }
1188}
1189
1190macro_rules! from_ints {
1191    ($($t:ty),+ $(,)?) => {
1192        $(
1193            paste::paste! {
1194                impl U {
1195                    pub const fn [<from_ $t>](x: $t) -> U {
1196                        U(array_concat::concat_arrays!(
1197                            [0u8; 32-core::mem::size_of::<$t>()],
1198                            x.to_be_bytes())
1199                        )
1200                    }
1201                }
1202
1203                impl From<$t> for U {
1204                    fn from(x: $t) -> Self {
1205                        U::[<from_ $t>](x)
1206                    }
1207                }
1208
1209                impl From<U> for $t {
1210                    fn from(x: U) -> Self {
1211                        Self::from_be_bytes(x.into())
1212                    }
1213                }
1214            }
1215        )+
1216    };
1217}
1218
1219from_ints! { u8, u16, u32, u64, u128, usize }
1220
1221impl From<I> for [u8; 32] {
1222    fn from(x: I) -> Self {
1223        x.0
1224    }
1225}
1226
1227impl From<[u8; 32]> for I {
1228    fn from(x: [u8; 32]) -> Self {
1229        I(x)
1230    }
1231}
1232
1233fn i_add(x: &I, y: &I) -> I {
1234    I(wrapping_add(&U(x.0), &U(y.0)).0)
1235}
1236
1237fn i_sub(x: &I, y: &I) -> I {
1238    I(wrapping_sub(&U(x.0), &U(y.0)).0)
1239}
1240
1241fn i_mul(x: &I, y: &I) -> I {
1242    let result = wrapping_mul(&U(x.0), &U(y.0));
1243    I(result.0)
1244}
1245
1246fn i_div(x: &I, y: &I) -> I {
1247    let r = wrapping_div(&x.abs(), &y.abs());
1248    if x.is_neg() ^ y.is_neg() {
1249        I(r.0).neg()
1250    } else {
1251        I(r.0)
1252    }
1253}
1254
1255fn i_rem(x: &I, y: &I) -> I {
1256    let r = modd(&x.abs(), &y.abs());
1257    if x.is_neg() {
1258        I(r.0).neg()
1259    } else {
1260        I(r.0)
1261    }
1262}
1263
1264impl Add for I {
1265    type Output = I;
1266    fn add(self, rhs: I) -> I {
1267        i_add(&self, &rhs)
1268    }
1269}
1270
1271impl Add for &I {
1272    type Output = I;
1273    fn add(self, rhs: &I) -> I {
1274        i_add(self, rhs)
1275    }
1276}
1277
1278impl Sub for I {
1279    type Output = I;
1280    fn sub(self, rhs: I) -> I {
1281        i_sub(&self, &rhs)
1282    }
1283}
1284
1285impl Sub for &I {
1286    type Output = I;
1287    fn sub(self, rhs: &I) -> I {
1288        i_sub(self, rhs)
1289    }
1290}
1291
1292impl Mul for I {
1293    type Output = I;
1294    fn mul(self, rhs: I) -> I {
1295        i_mul(&self, &rhs)
1296    }
1297}
1298
1299impl Mul for &I {
1300    type Output = I;
1301    fn mul(self, rhs: &I) -> I {
1302        i_mul(self, rhs)
1303    }
1304}
1305
1306impl Div for I {
1307    type Output = I;
1308    fn div(self, rhs: I) -> I {
1309        i_div(&self, &rhs)
1310    }
1311}
1312
1313impl Div for &I {
1314    type Output = I;
1315    fn div(self, rhs: &I) -> I {
1316        i_div(self, rhs)
1317    }
1318}
1319
1320impl Rem for I {
1321    type Output = I;
1322    fn rem(self, rhs: I) -> I {
1323        i_rem(&self, &rhs)
1324    }
1325}
1326
1327impl Eq for I {}
1328
1329impl PartialOrd for I {
1330    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
1331        Some(self.cmp(other))
1332    }
1333}
1334
1335impl Ord for I {
1336    fn cmp(&self, other: &Self) -> Ordering {
1337        let self_sign = self.0[0] & 0x80;
1338        let other_sign = other.0[0] & 0x80;
1339        match (self_sign, other_sign) {
1340            (0, 0x80) => Ordering::Greater,
1341            (0x80, 0) => Ordering::Less,
1342            _ => self.0.cmp(&other.0),
1343        }
1344    }
1345}
1346
1347impl Rem for &I {
1348    type Output = I;
1349    fn rem(self, rhs: &I) -> I {
1350        i_rem(self, rhs)
1351    }
1352}
1353
1354impl I {
1355    pub const ZERO: Self = I([0u8; 32]);
1356
1357    pub const ONE: Self = I([
1358        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, 0, 0,
1359        0, 1,
1360    ]);
1361}
1362
1363impl Zero for I {
1364    fn zero() -> Self {
1365        I::ZERO
1366    }
1367    fn is_zero(&self) -> bool {
1368        self.0.iter().all(|&b| b == 0)
1369    }
1370}
1371
1372impl Default for I {
1373    fn default() -> Self {
1374        I::ZERO
1375    }
1376}
1377
1378impl One for I {
1379    fn one() -> Self {
1380        I::ONE
1381    }
1382}
1383
1384#[test]
1385fn test_is_zeroes() {
1386    assert!(U::ZERO.is_zero());
1387    assert!(U::ONE.is_some());
1388    assert!(I::ZERO.is_zero());
1389    assert!(I::ONE.is_some());
1390}
1391
1392#[cfg(all(
1393    test,
1394    feature = "alloy-enabled",
1395    feature = "proptest-enabled",
1396    feature = "std",
1397    not(target_arch = "wasm32")
1398))]
1399mod test {
1400    use proptest::prelude::*;
1401
1402    use super::*;
1403
1404    proptest! {
1405        #[test]
1406        fn wrapping_div_b_zero_denominator_yields_zero(numerator in any::<[u8; 4]>()) {
1407            let zero = [0u8; 4];
1408            prop_assert_eq!(wrapping_div_quo_rem_b::<4>(&numerator, &zero).0, zero);
1409        }
1410
1411        #[test]
1412        fn wrapping_div_b_matches_integer_division(
1413            numerator in any::<[u8; 4]>(),
1414            denominator in any::<[u8; 4]>().prop_filter("denominator must be non-zero", |d| *d != [0u8; 4])
1415        ) {
1416            let numerator_u32 = u32::from_be_bytes(numerator);
1417            let denominator_u32 = u32::from_be_bytes(denominator);
1418            let expected = numerator_u32 / denominator_u32;
1419            prop_assert_eq!(
1420                wrapping_div_quo_rem_b::<4>(&numerator, &denominator).0,
1421                expected.to_be_bytes()
1422            );
1423        }
1424
1425        #[test]
1426        fn wrapping_mod_b_matches_integer_modulo(
1427            numerator in any::<[u8; 4]>(),
1428            denominator in any::<[u8; 4]>().prop_filter("denominator must be non-zero", |d| *d != [0u8; 4])
1429        ) {
1430            let numerator_u32 = u32::from_be_bytes(numerator);
1431            let denominator_u32 = u32::from_be_bytes(denominator);
1432            let expected = numerator_u32 % denominator_u32;
1433            prop_assert_eq!(
1434                wrapping_div_quo_rem_b::<4>(&numerator, &denominator).1,
1435                expected.to_be_bytes()
1436            );
1437        }
1438
1439        #[test]
1440        fn wrapping_add_b_handles_carry(lhs in any::<[u8; 4]>(), rhs in any::<[u8; 4]>()) {
1441            let lhs_u32 = u32::from_be_bytes(lhs);
1442            let rhs_u32 = u32::from_be_bytes(rhs);
1443            let expected = lhs_u32.wrapping_add(rhs_u32);
1444            prop_assert_eq!(wrapping_add_b::<4>(&lhs, &rhs), expected.to_be_bytes());
1445        }
1446
1447        #[test]
1448        fn wrapping_sub_b_handles_borrow(lhs in any::<[u8; 4]>(), rhs in any::<[u8; 4]>()) {
1449            let lhs_u32 = u32::from_be_bytes(lhs);
1450            let rhs_u32 = u32::from_be_bytes(rhs);
1451            let expected = lhs_u32.wrapping_sub(rhs_u32);
1452            prop_assert_eq!(wrapping_sub_b::<4>(&lhs, &rhs), expected.to_be_bytes());
1453        }
1454
1455        #[test]
1456        fn wrapping_mul_b_matches_wrapping_arithmetic(lhs in any::<[u8; 32]>(), rhs in any::<[u8; 32]>()) {
1457            let lhs_u = U::from(lhs);
1458            let rhs_u = U::from(rhs);
1459            let expected = lhs_u.wrapping_mul(&rhs_u);
1460            prop_assert_eq!(wrapping_mul_b::<32>(&lhs, &rhs), expected.0);
1461        }
1462
1463        #[test]
1464        fn const_wrapping_div_agrees_with_wrapping_div_b(
1465            numerator in any::<[u8; 32]>(),
1466            denominator in any::<[u8; 32]>().prop_filter("denominator must be non-zero", |d| *d != [0u8; 32])
1467        ) {
1468            let numerator_u = U::from(numerator);
1469            let denominator_u = U::from(denominator);
1470            prop_assert_eq!(
1471                const_wrapping_div(&numerator_u, &denominator_u).0,
1472                wrapping_div_quo_rem_b::<32>(&numerator, &denominator).0
1473            );
1474        }
1475
1476        #[test]
1477        fn u_predicates_track_zero_and_true(bytes in any::<[u8; 32]>()) {
1478            let value = U::from(bytes);
1479            let is_zero = bytes.iter().all(|&b| b == 0);
1480            prop_assert_eq!(value.is_zero(), is_zero);
1481            prop_assert_eq!(value.is_some(), !is_zero);
1482            prop_assert_eq!(value.is_true(), bytes[31] == 1);
1483        }
1484
1485        #[test]
1486        fn test_u_is_zero(x in any::<[u8; 32]>()) {
1487            let x = U::from(x);
1488            let ex = U256::from_be_bytes(x.0);
1489            assert_eq!(ex.is_zero(), x.is_zero());
1490        }
1491
1492        #[test]
1493        fn test_u_div(x in any::<U>(), y in any::<U>()) {
1494            let ex = U256::from_be_bytes(x.0);
1495            let ey = U256::from_be_bytes(y.0);
1496            assert_eq!((ex.wrapping_div(ey)).to_be_bytes(), x.wrapping_div(&y).0);
1497        }
1498
1499        #[test]
1500        fn test_u_mul(x in any::<U>(), y in any::<U>()) {
1501            let ex = U256::from_be_bytes(x.0);
1502            let ey = U256::from_be_bytes(y.0);
1503            assert_eq!((ex.wrapping_mul(ey)).to_be_bytes(), wrapping_mul(&x,  &y).0);
1504        }
1505
1506        #[test]
1507        fn test_u_mod(x in any::<U>(), y in any::<U>()) {
1508            let ex = U256::from_be_bytes(x.0);
1509            let ey = U256::from_be_bytes(y.0);
1510            assert_eq!((ex % ey).to_be_bytes(), (x % y).0);
1511        }
1512
1513        #[test]
1514        fn test_u_add(x in any::<U>(), y in any::<U>()) {
1515            let ex = U256::from_be_bytes(x.0);
1516            let ey = U256::from_be_bytes(y.0);
1517            let e = U::from(ex.wrapping_add(ey).to_be_bytes::<32>());
1518            assert_eq!(e, x.wrapping_add(&y), "{e} != {}", x + y);
1519        }
1520
1521        #[test]
1522        fn test_u_sub(x in any::<U>(), y in any::<U>()) {
1523            let ex = U256::from_be_bytes(x.0);
1524            let ey = U256::from_be_bytes(y.0);
1525            assert_eq!((ex.wrapping_sub(ey)).to_be_bytes(), x.wrapping_sub(&y).0);
1526        }
1527
1528        #[test]
1529        fn test_u_cmp(x in any::<U>(), y in any::<U>()) {
1530            let ex = U256::from_be_bytes(x.0);
1531            let ey = U256::from_be_bytes(y.0);
1532            assert_eq!(ex.cmp(&ey), x.cmp(&y));
1533        }
1534
1535        #[test]
1536        #[cfg(feature = "alloc")]
1537        fn test_u_str(x in any::<U>()) {
1538            assert_eq!(U256::from_be_bytes(x.0).to_string(), x.to_string());
1539        }
1540
1541        #[test]
1542        fn test_u_shl(x in any::<U>(), i in any::<usize>()) {
1543            let l = U((U256::from_be_bytes(x.0) << i).to_be_bytes::<32>());
1544            assert_eq!(l, x << i);
1545        }
1546
1547        #[test]
1548        fn test_u_shr(x in any::<U>(), i in any::<usize>()) {
1549            let l = U((U256::from_be_bytes(x.0) >> i).to_be_bytes::<32>());
1550            assert_eq!(l, x >> i);
1551        }
1552
1553        #[test]
1554        fn test_trailing_zeros(x in any::<U>()) {
1555            assert_eq!(U256::from_be_bytes(x.0).trailing_zeros(), x.trailing_zeros());
1556        }
1557
1558        #[test]
1559        fn test_i_is_zero(x in any::<U>()) {
1560            let ex = I256::from_be_bytes(x.0);
1561            assert_eq!(ex.is_zero(), x.is_zero());
1562        }
1563
1564        #[test]
1565        fn test_i_div(x in any::<I>(), y in any::<I>()) {
1566            let ex = I256::from_be_bytes(x.0);
1567            let ey = I256::from_be_bytes(y.0);
1568            assert_eq!((ex / ey).to_be_bytes(), (x / y).0);
1569        }
1570
1571        #[test]
1572        fn test_i_mul(x in any::<I>(), y in any::<I>()) {
1573            let ex = I256::from_be_bytes(x.0);
1574            let ey = I256::from_be_bytes(y.0);
1575            assert_eq!((ex.wrapping_mul(ey)).to_be_bytes(), (x * y).0);
1576        }
1577
1578        #[test]
1579        fn test_i_mod(x in any::<I>(), y in any::<I>()) {
1580            let ex = I256::from_be_bytes(x.0);
1581            let ey = I256::from_be_bytes(y.0);
1582            assert_eq!((ex % ey).to_be_bytes(), (x % y).0);
1583        }
1584
1585        #[test]
1586        fn test_i_add(x in any::<I>(), y in any::<I>()) {
1587            let ex = I256::from_be_bytes(x.0);
1588            let ey = I256::from_be_bytes(y.0);
1589            assert_eq!((ex.wrapping_add(ey)).to_be_bytes(), (x + y).0);
1590        }
1591
1592        #[test]
1593        fn test_i_sub(x in any::<I>(), y in any::<I>()) {
1594            let ex = I256::from_be_bytes(x.0);
1595            let ey = I256::from_be_bytes(y.0);
1596            assert_eq!((ex.wrapping_sub(ey)).to_be_bytes(), (x - y).0);
1597        }
1598
1599        #[test]
1600        fn test_i_cmp(x in any::<I>(), y in any::<I>()) {
1601            let ex = I256::from_be_bytes(x.0);
1602            let ey = I256::from_be_bytes(y.0);
1603            assert_eq!(ex.cmp(&ey), x.cmp(&y));
1604        }
1605
1606        #[test]
1607        fn test_u_u8(x in any::<u8>()) {
1608            let mut b = [0u8; 32];
1609            b[32-std::mem::size_of::<u8>()..].copy_from_slice(&x.to_be_bytes());
1610            assert_eq!(&U256::from_be_bytes(b).to_be_bytes(), U::from(x).as_slice());
1611        }
1612
1613        #[test]
1614        fn test_u_u16(x in any::<u16>()) {
1615            let mut b = [0u8; 32];
1616            b[32-std::mem::size_of::<u16>()..].copy_from_slice(&x.to_be_bytes());
1617            assert_eq!(&U256::from_be_bytes(b).to_be_bytes(), U::from(x).as_slice());
1618        }
1619
1620        #[test]
1621        fn test_u_u32(x in any::<u32>()) {
1622            let mut b = [0u8; 32];
1623            b[32-std::mem::size_of::<u32>()..].copy_from_slice(&x.to_be_bytes());
1624            assert_eq!(&U256::from_be_bytes(b).to_be_bytes(), U::from(x).as_slice());
1625        }
1626
1627        #[test]
1628        fn test_u_u64(x in any::<u64>()) {
1629            let mut b = [0u8; 32];
1630            b[32-std::mem::size_of::<u64>()..].copy_from_slice(&x.to_be_bytes());
1631            assert_eq!(&U256::from_be_bytes(b).to_be_bytes(), U::from(x).as_slice());
1632        }
1633
1634        #[test]
1635        fn test_u_u128(x in any::<u128>()) {
1636            let mut b = [0u8; 32];
1637            b[32-std::mem::size_of::<u128>()..].copy_from_slice(&x.to_be_bytes());
1638            assert_eq!(&U256::from_be_bytes(b).to_be_bytes(), U::from(x).as_slice());
1639        }
1640
1641        #[test]
1642        fn test_to_and_from_addrs(x in any::<Address>()) {
1643            let y: Address = U::from(x).into();
1644            assert_eq!(x, y)
1645        }
1646
1647        #[test]
1648        fn test_u_conv_to_and_from_u8(x in any::<u8>()) {
1649            assert_eq!(x.wrapping_add(1), U::from(x).wrapping_add(&U::ONE).into());
1650        }
1651    }
1652}