Skip to content

Commit a4c3596

Browse files
authored
Bring Checked* traits in line with Wrapping* (#434)
This crate defines its own `Checked*` traits in order to use `CtOption<T>` rather than `Option<T>`, however it gets its `Wrapping*` traits from `num-bigint`. This brings the `Checked*` traits more in line with `Wrapping*`, automatically taking a reference to the `rhs` parameter, which eliminates the need to use HRTBs in `Integer`'s definition.
1 parent 95fa6aa commit a4c3596

File tree

13 files changed

+282
-383
lines changed

13 files changed

+282
-383
lines changed

src/checked.rs

Lines changed: 246 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
//! Checked arithmetic.
22
3+
use crate::{CheckedAdd, CheckedDiv, CheckedMul, CheckedSub};
4+
use core::ops::{Add, Div, Mul, Sub};
35
use subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption};
46

57
#[cfg(feature = "serde")]
@@ -19,12 +21,243 @@ impl<T> Checked<T> {
1921
}
2022
}
2123

22-
impl<T> Default for Checked<T>
24+
impl<T> Add<Self> for Checked<T>
2325
where
24-
T: Default,
26+
T: CheckedAdd + ConditionallySelectable + Default,
2527
{
26-
fn default() -> Self {
27-
Self::new(T::default())
28+
type Output = Checked<T>;
29+
30+
#[inline]
31+
fn add(self, rhs: Self) -> Self::Output {
32+
Checked(
33+
self.0
34+
.and_then(|lhs| rhs.0.and_then(|rhs| lhs.checked_add(&rhs))),
35+
)
36+
}
37+
}
38+
39+
impl<T> Add<&Self> for Checked<T>
40+
where
41+
T: CheckedAdd + ConditionallySelectable + Default,
42+
{
43+
type Output = Checked<T>;
44+
45+
#[inline]
46+
fn add(self, rhs: &Self) -> Self::Output {
47+
Checked(
48+
self.0
49+
.and_then(|lhs| rhs.0.and_then(|rhs| lhs.checked_add(&rhs))),
50+
)
51+
}
52+
}
53+
54+
impl<T> Add<Checked<T>> for &Checked<T>
55+
where
56+
T: CheckedAdd + ConditionallySelectable + Default,
57+
{
58+
type Output = Checked<T>;
59+
60+
#[inline]
61+
fn add(self, rhs: Checked<T>) -> Self::Output {
62+
Checked(
63+
self.0
64+
.and_then(|lhs| rhs.0.and_then(|rhs| lhs.checked_add(&rhs))),
65+
)
66+
}
67+
}
68+
69+
impl<T> Add<&Checked<T>> for &Checked<T>
70+
where
71+
T: CheckedAdd + ConditionallySelectable + Default,
72+
{
73+
type Output = Checked<T>;
74+
75+
#[inline]
76+
fn add(self, rhs: &Checked<T>) -> Self::Output {
77+
Checked(
78+
self.0
79+
.and_then(|lhs| rhs.0.and_then(|rhs| lhs.checked_add(&rhs))),
80+
)
81+
}
82+
}
83+
84+
impl<T> Sub<Self> for Checked<T>
85+
where
86+
T: CheckedSub + ConditionallySelectable + Default,
87+
{
88+
type Output = Checked<T>;
89+
90+
#[inline]
91+
fn sub(self, rhs: Self) -> Self::Output {
92+
Checked(
93+
self.0
94+
.and_then(|lhs| rhs.0.and_then(|rhs| lhs.checked_sub(&rhs))),
95+
)
96+
}
97+
}
98+
99+
impl<T> Sub<&Self> for Checked<T>
100+
where
101+
T: CheckedSub + ConditionallySelectable + Default,
102+
{
103+
type Output = Checked<T>;
104+
105+
#[inline]
106+
fn sub(self, rhs: &Self) -> Self::Output {
107+
Checked(
108+
self.0
109+
.and_then(|lhs| rhs.0.and_then(|rhs| lhs.checked_sub(&rhs))),
110+
)
111+
}
112+
}
113+
114+
impl<T> Sub<Checked<T>> for &Checked<T>
115+
where
116+
T: CheckedSub + ConditionallySelectable + Default,
117+
{
118+
type Output = Checked<T>;
119+
120+
#[inline]
121+
fn sub(self, rhs: Checked<T>) -> Self::Output {
122+
Checked(
123+
self.0
124+
.and_then(|lhs| rhs.0.and_then(|rhs| lhs.checked_sub(&rhs))),
125+
)
126+
}
127+
}
128+
129+
impl<T> Sub<&Checked<T>> for &Checked<T>
130+
where
131+
T: CheckedSub + ConditionallySelectable + Default,
132+
{
133+
type Output = Checked<T>;
134+
135+
#[inline]
136+
fn sub(self, rhs: &Checked<T>) -> Self::Output {
137+
Checked(
138+
self.0
139+
.and_then(|lhs| rhs.0.and_then(|rhs| lhs.checked_sub(&rhs))),
140+
)
141+
}
142+
}
143+
144+
impl<T> Mul<Self> for Checked<T>
145+
where
146+
T: CheckedMul + ConditionallySelectable + Default,
147+
{
148+
type Output = Checked<T>;
149+
150+
#[inline]
151+
fn mul(self, rhs: Self) -> Self::Output {
152+
Checked(
153+
self.0
154+
.and_then(|lhs| rhs.0.and_then(|rhs| lhs.checked_mul(&rhs))),
155+
)
156+
}
157+
}
158+
159+
impl<T> Mul<&Self> for Checked<T>
160+
where
161+
T: CheckedMul + ConditionallySelectable + Default,
162+
{
163+
type Output = Checked<T>;
164+
165+
#[inline]
166+
fn mul(self, rhs: &Self) -> Self::Output {
167+
Checked(
168+
self.0
169+
.and_then(|lhs| rhs.0.and_then(|rhs| lhs.checked_mul(&rhs))),
170+
)
171+
}
172+
}
173+
174+
impl<T> Mul<Checked<T>> for &Checked<T>
175+
where
176+
T: CheckedMul + ConditionallySelectable + Default,
177+
{
178+
type Output = Checked<T>;
179+
180+
#[inline]
181+
fn mul(self, rhs: Checked<T>) -> Self::Output {
182+
Checked(
183+
self.0
184+
.and_then(|lhs| rhs.0.and_then(|rhs| lhs.checked_mul(&rhs))),
185+
)
186+
}
187+
}
188+
189+
impl<T> Mul<&Checked<T>> for &Checked<T>
190+
where
191+
T: CheckedMul + ConditionallySelectable + Default,
192+
{
193+
type Output = Checked<T>;
194+
195+
#[inline]
196+
fn mul(self, rhs: &Checked<T>) -> Self::Output {
197+
Checked(
198+
self.0
199+
.and_then(|lhs| rhs.0.and_then(|rhs| lhs.checked_mul(&rhs))),
200+
)
201+
}
202+
}
203+
204+
impl<T> Div<Self> for Checked<T>
205+
where
206+
T: CheckedDiv + ConditionallySelectable + Default,
207+
{
208+
type Output = Checked<T>;
209+
210+
#[inline]
211+
fn div(self, rhs: Self) -> Self::Output {
212+
Checked(
213+
self.0
214+
.and_then(|lhs| rhs.0.and_then(|rhs| lhs.checked_div(&rhs))),
215+
)
216+
}
217+
}
218+
219+
impl<T> Div<&Self> for Checked<T>
220+
where
221+
T: CheckedDiv + ConditionallySelectable + Default,
222+
{
223+
type Output = Checked<T>;
224+
225+
#[inline]
226+
fn div(self, rhs: &Self) -> Self::Output {
227+
Checked(
228+
self.0
229+
.and_then(|lhs| rhs.0.and_then(|rhs| lhs.checked_div(&rhs))),
230+
)
231+
}
232+
}
233+
234+
impl<T> Div<Checked<T>> for &Checked<T>
235+
where
236+
T: CheckedDiv + ConditionallySelectable + Default,
237+
{
238+
type Output = Checked<T>;
239+
240+
#[inline]
241+
fn div(self, rhs: Checked<T>) -> Self::Output {
242+
Checked(
243+
self.0
244+
.and_then(|lhs| rhs.0.and_then(|rhs| lhs.checked_div(&rhs))),
245+
)
246+
}
247+
}
248+
249+
impl<T> Div<&Checked<T>> for &Checked<T>
250+
where
251+
T: CheckedDiv + ConditionallySelectable + Default,
252+
{
253+
type Output = Checked<T>;
254+
255+
#[inline]
256+
fn div(self, rhs: &Checked<T>) -> Self::Output {
257+
Checked(
258+
self.0
259+
.and_then(|lhs| rhs.0.and_then(|rhs| lhs.checked_div(&rhs))),
260+
)
28261
}
29262
}
30263

@@ -42,6 +275,15 @@ impl<T: ConstantTimeEq> ConstantTimeEq for Checked<T> {
42275
}
43276
}
44277

278+
impl<T> Default for Checked<T>
279+
where
280+
T: Default,
281+
{
282+
fn default() -> Self {
283+
Self::new(T::default())
284+
}
285+
}
286+
45287
impl<T> From<Checked<T>> for CtOption<T> {
46288
fn from(checked: Checked<T>) -> CtOption<T> {
47289
checked.0

src/limb/add.rs

Lines changed: 5 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ impl Add for Limb {
3333

3434
#[inline]
3535
fn add(self, rhs: Self) -> Self {
36-
self.checked_add(rhs)
36+
self.checked_add(&rhs)
3737
.expect("attempted to add with overflow")
3838
}
3939
}
@@ -52,54 +52,6 @@ impl AddAssign<&Wrapping<Limb>> for Wrapping<Limb> {
5252
}
5353
}
5454

55-
impl Add for Checked<Limb> {
56-
type Output = Self;
57-
58-
#[inline]
59-
fn add(self, rhs: Self) -> Checked<Limb> {
60-
Checked(
61-
self.0
62-
.and_then(|lhs| rhs.0.and_then(|rhs| lhs.checked_add(rhs))),
63-
)
64-
}
65-
}
66-
67-
impl Add<&Checked<Limb>> for Checked<Limb> {
68-
type Output = Checked<Limb>;
69-
70-
#[inline]
71-
fn add(self, rhs: &Checked<Limb>) -> Checked<Limb> {
72-
Checked(
73-
self.0
74-
.and_then(|lhs| rhs.0.and_then(|rhs| lhs.checked_add(rhs))),
75-
)
76-
}
77-
}
78-
79-
impl Add<Checked<Limb>> for &Checked<Limb> {
80-
type Output = Checked<Limb>;
81-
82-
#[inline]
83-
fn add(self, rhs: Checked<Limb>) -> Checked<Limb> {
84-
Checked(
85-
self.0
86-
.and_then(|lhs| rhs.0.and_then(|rhs| lhs.checked_add(rhs))),
87-
)
88-
}
89-
}
90-
91-
impl Add<&Checked<Limb>> for &Checked<Limb> {
92-
type Output = Checked<Limb>;
93-
94-
#[inline]
95-
fn add(self, rhs: &Checked<Limb>) -> Checked<Limb> {
96-
Checked(
97-
self.0
98-
.and_then(|lhs| rhs.0.and_then(|rhs| lhs.checked_add(rhs))),
99-
)
100-
}
101-
}
102-
10355
impl AddAssign for Checked<Limb> {
10456
#[inline]
10557
fn add_assign(&mut self, other: Self) {
@@ -115,11 +67,9 @@ impl AddAssign<&Checked<Limb>> for Checked<Limb> {
11567
}
11668

11769
impl CheckedAdd for Limb {
118-
type Output = Self;
119-
12070
#[inline]
121-
fn checked_add(&self, rhs: Self) -> CtOption<Self> {
122-
let (result, carry) = self.adc(rhs, Limb::ZERO);
71+
fn checked_add(&self, rhs: &Self) -> CtOption<Self> {
72+
let (result, carry) = self.adc(*rhs, Limb::ZERO);
12373
CtOption::new(result, carry.is_zero())
12474
}
12575
}
@@ -161,13 +111,13 @@ mod tests {
161111

162112
#[test]
163113
fn checked_add_ok() {
164-
let result = Limb::ZERO.checked_add(Limb::ONE);
114+
let result = Limb::ZERO.checked_add(&Limb::ONE);
165115
assert_eq!(result.unwrap(), Limb::ONE);
166116
}
167117

168118
#[test]
169119
fn checked_add_overflow() {
170-
let result = Limb::MAX.checked_add(Limb::ONE);
120+
let result = Limb::MAX.checked_add(&Limb::ONE);
171121
assert!(!bool::from(result.is_some()));
172122
}
173123
}

0 commit comments

Comments
 (0)