Skip to content

Commit baef90b

Browse files
committed
feat: make add and sub const fns
1 parent 706ffd0 commit baef90b

File tree

2 files changed

+23
-19
lines changed

2 files changed

+23
-19
lines changed

src/add.rs

+22-18
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ impl<const BITS: usize, const LIMBS: usize> Uint<BITS, LIMBS> {
2121
/// Computes `self + rhs`, returning [`None`] if overflow occurred.
2222
#[inline(always)]
2323
#[must_use]
24-
pub fn checked_add(self, rhs: Self) -> Option<Self> {
24+
pub const fn checked_add(self, rhs: Self) -> Option<Self> {
2525
match self.overflowing_add(rhs) {
2626
(value, false) => Some(value),
2727
_ => None,
@@ -31,7 +31,7 @@ impl<const BITS: usize, const LIMBS: usize> Uint<BITS, LIMBS> {
3131
/// Computes `-self`, returning [`None`] unless `self == 0`.
3232
#[inline(always)]
3333
#[must_use]
34-
pub fn checked_neg(self) -> Option<Self> {
34+
pub const fn checked_neg(self) -> Option<Self> {
3535
match self.overflowing_neg() {
3636
(value, false) => Some(value),
3737
_ => None,
@@ -41,7 +41,7 @@ impl<const BITS: usize, const LIMBS: usize> Uint<BITS, LIMBS> {
4141
/// Computes `self - rhs`, returning [`None`] if overflow occurred.
4242
#[inline(always)]
4343
#[must_use]
44-
pub fn checked_sub(self, rhs: Self) -> Option<Self> {
44+
pub const fn checked_sub(self, rhs: Self) -> Option<Self> {
4545
match self.overflowing_sub(rhs) {
4646
(value, false) => Some(value),
4747
_ => None,
@@ -55,16 +55,18 @@ impl<const BITS: usize, const LIMBS: usize> Uint<BITS, LIMBS> {
5555
/// then the wrapped value is returned.
5656
#[inline]
5757
#[must_use]
58-
pub fn overflowing_add(mut self, rhs: Self) -> (Self, bool) {
58+
pub const fn overflowing_add(mut self, rhs: Self) -> (Self, bool) {
5959
if BITS == 0 {
6060
return (Self::ZERO, false);
6161
}
6262
let mut carry = 0_u128;
63+
let mut i = 0;
6364
#[allow(clippy::cast_possible_truncation)] // Intentional
64-
for (lhs, &rhs) in self.limbs.iter_mut().zip(rhs.as_limbs()) {
65-
carry += u128::from(*lhs) + u128::from(rhs);
66-
*lhs = carry as u64;
65+
while i < LIMBS {
66+
carry += self.limbs[i] as u128 + rhs.limbs[i] as u128;
67+
self.limbs[i] = carry as u64;
6768
carry >>= 64;
69+
i += 1;
6870
}
6971
let overflow = carry != 0 || self.limbs[LIMBS - 1] > Self::MASK;
7072
self.limbs[LIMBS - 1] &= Self::MASK;
@@ -79,7 +81,7 @@ impl<const BITS: usize, const LIMBS: usize> Uint<BITS, LIMBS> {
7981
/// overflow.
8082
#[inline(always)]
8183
#[must_use]
82-
pub fn overflowing_neg(self) -> (Self, bool) {
84+
pub const fn overflowing_neg(self) -> (Self, bool) {
8385
Self::ZERO.overflowing_sub(self)
8486
}
8587

@@ -90,17 +92,19 @@ impl<const BITS: usize, const LIMBS: usize> Uint<BITS, LIMBS> {
9092
/// occurred then the wrapped value is returned.
9193
#[inline]
9294
#[must_use]
93-
pub fn overflowing_sub(mut self, rhs: Self) -> (Self, bool) {
95+
pub const fn overflowing_sub(mut self, rhs: Self) -> (Self, bool) {
9496
if BITS == 0 {
9597
return (Self::ZERO, false);
9698
}
9799
let mut carry = 0_i128;
100+
let mut i = 0;
98101
#[allow(clippy::cast_possible_truncation)] // Intentional
99102
#[allow(clippy::cast_sign_loss)] // Intentional
100-
for (lhs, &rhs) in self.limbs.iter_mut().zip(rhs.as_limbs()) {
101-
carry += i128::from(*lhs) - i128::from(rhs);
102-
*lhs = carry as u64;
103-
carry >>= 64; // Sign extending shift
103+
while i < LIMBS {
104+
carry += self.limbs[i] as i128 - rhs.limbs[i] as i128;
105+
self.limbs[i] = carry as u64;
106+
carry >>= 64;
107+
i += 1;
104108
}
105109
let overflow = carry != 0 || self.limbs[LIMBS - 1] > Self::MASK;
106110
self.limbs[LIMBS - 1] &= Self::MASK;
@@ -111,7 +115,7 @@ impl<const BITS: usize, const LIMBS: usize> Uint<BITS, LIMBS> {
111115
/// overflowing.
112116
#[inline(always)]
113117
#[must_use]
114-
pub fn saturating_add(self, rhs: Self) -> Self {
118+
pub const fn saturating_add(self, rhs: Self) -> Self {
115119
match self.overflowing_add(rhs) {
116120
(value, false) => value,
117121
_ => Self::MAX,
@@ -122,7 +126,7 @@ impl<const BITS: usize, const LIMBS: usize> Uint<BITS, LIMBS> {
122126
/// overflowing
123127
#[inline(always)]
124128
#[must_use]
125-
pub fn saturating_sub(self, rhs: Self) -> Self {
129+
pub const fn saturating_sub(self, rhs: Self) -> Self {
126130
match self.overflowing_sub(rhs) {
127131
(value, false) => value,
128132
_ => Self::ZERO,
@@ -132,21 +136,21 @@ impl<const BITS: usize, const LIMBS: usize> Uint<BITS, LIMBS> {
132136
/// Computes `self + rhs`, wrapping around at the boundary of the type.
133137
#[inline(always)]
134138
#[must_use]
135-
pub fn wrapping_add(self, rhs: Self) -> Self {
139+
pub const fn wrapping_add(self, rhs: Self) -> Self {
136140
self.overflowing_add(rhs).0
137141
}
138142

139143
/// Computes `-self`, wrapping around at the boundary of the type.
140144
#[inline(always)]
141145
#[must_use]
142-
pub fn wrapping_neg(self) -> Self {
146+
pub const fn wrapping_neg(self) -> Self {
143147
self.overflowing_neg().0
144148
}
145149

146150
/// Computes `self - rhs`, wrapping around at the boundary of the type.
147151
#[inline(always)]
148152
#[must_use]
149-
pub fn wrapping_sub(self, rhs: Self) -> Self {
153+
pub const fn wrapping_sub(self, rhs: Self) -> Self {
150154
self.overflowing_sub(rhs).0
151155
}
152156
}

src/cmp.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ impl<const BITS: usize, const LIMBS: usize> PartialOrd for Uint<BITS, LIMBS> {
1616
}
1717

1818
impl<const BITS: usize, const LIMBS: usize> Uint<BITS, LIMBS> {
19-
/// Check if this uint is zero
19+
/// Returns true if the value is zero.
2020
#[inline]
2121
#[must_use]
2222
pub fn is_zero(&self) -> bool {

0 commit comments

Comments
 (0)