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