alloy_primitives/signed/
utils.rs

1use crate::signed::Signed;
2use ruint::Uint;
3
4/// Panic if overflow on debug mode.
5#[inline]
6#[track_caller]
7pub(super) const fn handle_overflow<T: Copy>((result, overflow): (T, bool)) -> T {
8    debug_assert!(!overflow, "overflow");
9    result
10}
11
12/// Compute the two's complement of a U256.
13#[inline]
14pub(super) fn twos_complement<const BITS: usize, const LIMBS: usize>(
15    u: Uint<BITS, LIMBS>,
16) -> Uint<BITS, LIMBS> {
17    if BITS == 0 {
18        return u;
19    }
20    (!u).overflowing_add(Uint::<BITS, LIMBS>::from(1)).0
21}
22
23/// Compile-time equality of signed integers.
24#[inline]
25pub(super) const fn const_eq<const BITS: usize, const LIMBS: usize>(
26    left: &Signed<BITS, LIMBS>,
27    right: &Signed<BITS, LIMBS>,
28) -> bool {
29    if BITS == 0 {
30        return true;
31    }
32
33    let mut i = 0;
34    let llimbs = left.0.as_limbs();
35    let rlimbs = right.0.as_limbs();
36    while i < LIMBS {
37        if llimbs[i] != rlimbs[i] {
38            return false;
39        }
40        i += 1;
41    }
42    true
43}
44
45/// Compute the max value at compile time.
46pub(super) const fn max<const BITS: usize, const LIMBS: usize>() -> Signed<BITS, LIMBS> {
47    if LIMBS == 0 {
48        return zero();
49    }
50
51    let mut limbs = [u64::MAX; LIMBS];
52    limbs[LIMBS - 1] &= Signed::<BITS, LIMBS>::MASK; // unset all high bits
53    limbs[LIMBS - 1] &= !Signed::<BITS, LIMBS>::SIGN_BIT; // unset the sign bit
54    Signed(Uint::from_limbs(limbs))
55}
56
57pub(super) const fn min<const BITS: usize, const LIMBS: usize>() -> Signed<BITS, LIMBS> {
58    if LIMBS == 0 {
59        return zero();
60    }
61
62    let mut limbs = [0; LIMBS];
63    limbs[LIMBS - 1] = Signed::<BITS, LIMBS>::SIGN_BIT;
64    Signed(Uint::from_limbs(limbs))
65}
66
67pub(super) const fn zero<const BITS: usize, const LIMBS: usize>() -> Signed<BITS, LIMBS> {
68    let limbs = [0; LIMBS];
69    Signed(Uint::from_limbs(limbs))
70}
71
72pub(super) const fn one<const BITS: usize, const LIMBS: usize>() -> Signed<BITS, LIMBS> {
73    if LIMBS == 0 {
74        return zero();
75    }
76
77    let mut limbs = [0; LIMBS];
78    limbs[0] = 1;
79    Signed(Uint::from_limbs(limbs))
80}
81
82/// Location of the sign bit within the highest limb.
83pub(super) const fn sign_bit(bits: usize) -> u64 {
84    if bits == 0 {
85        return 0;
86    }
87    let bits = bits % 64;
88    if bits == 0 {
89        1 << 63
90    } else {
91        1 << (bits - 1)
92    }
93}