Skip to content

Commit 95fa6aa

Browse files
authored
Expand num_traits impls (#433)
Impls `num_traits::{Zero, One}` for: - `Limb` - `Uint` - `BoxedUint` - `Wrapping` To impl the traits for `Wrapping`, it required generic impls of `Add` and `Mul`, which are possible thanks to the `WrappingAdd`/`WrappingMul` traits. These subsume the per-type impls that existed previously.
1 parent 80c9029 commit 95fa6aa

File tree

17 files changed

+451
-325
lines changed

17 files changed

+451
-325
lines changed

src/limb.rs

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ mod rand;
2121

2222
use crate::{Bounded, Constants, ZeroConstant};
2323
use core::fmt;
24-
use subtle::{Choice, ConditionallySelectable};
24+
use subtle::{Choice, ConditionallySelectable, ConstantTimeEq};
2525

2626
#[cfg(feature = "serde")]
2727
use serdect::serde::{Deserialize, Deserializer, Serialize, Serializer};
@@ -103,17 +103,37 @@ impl Constants for Limb {
103103
const MAX: Self = Self::MAX;
104104
}
105105

106-
impl ZeroConstant for Limb {
107-
const ZERO: Self = Self::ZERO;
108-
}
109-
110106
impl ConditionallySelectable for Limb {
111107
#[inline]
112108
fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
113109
Self(Word::conditional_select(&a.0, &b.0, choice))
114110
}
115111
}
116112

113+
impl ZeroConstant for Limb {
114+
const ZERO: Self = Self::ZERO;
115+
}
116+
117+
impl num_traits::Zero for Limb {
118+
fn zero() -> Self {
119+
Self::ZERO
120+
}
121+
122+
fn is_zero(&self) -> bool {
123+
self.ct_eq(&Self::ZERO).into()
124+
}
125+
}
126+
127+
impl num_traits::One for Limb {
128+
fn one() -> Self {
129+
Self::ONE
130+
}
131+
132+
fn is_one(&self) -> bool {
133+
self.ct_eq(&Self::ONE).into()
134+
}
135+
}
136+
117137
impl fmt::Debug for Limb {
118138
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
119139
write!(f, "Limb(0x{self:X})")

src/limb/add.rs

Lines changed: 30 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
//! Limb addition
22
3-
use crate::{Checked, CheckedAdd, Limb, WideWord, Word, Wrapping, Zero};
3+
use crate::{Checked, CheckedAdd, Limb, WideWord, Word, Wrapping, WrappingAdd, Zero};
44
use core::ops::{Add, AddAssign};
55
use subtle::CtOption;
66

@@ -28,55 +28,25 @@ impl Limb {
2828
}
2929
}
3030

31-
impl CheckedAdd for Limb {
31+
impl Add for Limb {
3232
type Output = Self;
3333

3434
#[inline]
35-
fn checked_add(&self, rhs: Self) -> CtOption<Self> {
36-
let (result, carry) = self.adc(rhs, Limb::ZERO);
37-
CtOption::new(result, carry.is_zero())
38-
}
39-
}
40-
41-
impl Add for Wrapping<Limb> {
42-
type Output = Self;
43-
44-
fn add(self, rhs: Self) -> Wrapping<Limb> {
45-
Wrapping(self.0.wrapping_add(rhs.0))
46-
}
47-
}
48-
49-
impl Add<&Wrapping<Limb>> for Wrapping<Limb> {
50-
type Output = Wrapping<Limb>;
51-
52-
fn add(self, rhs: &Wrapping<Limb>) -> Wrapping<Limb> {
53-
Wrapping(self.0.wrapping_add(rhs.0))
54-
}
55-
}
56-
57-
impl Add<Wrapping<Limb>> for &Wrapping<Limb> {
58-
type Output = Wrapping<Limb>;
59-
60-
fn add(self, rhs: Wrapping<Limb>) -> Wrapping<Limb> {
61-
Wrapping(self.0.wrapping_add(rhs.0))
62-
}
63-
}
64-
65-
impl Add<&Wrapping<Limb>> for &Wrapping<Limb> {
66-
type Output = Wrapping<Limb>;
67-
68-
fn add(self, rhs: &Wrapping<Limb>) -> Wrapping<Limb> {
69-
Wrapping(self.0.wrapping_add(rhs.0))
35+
fn add(self, rhs: Self) -> Self {
36+
self.checked_add(rhs)
37+
.expect("attempted to add with overflow")
7038
}
7139
}
7240

7341
impl AddAssign for Wrapping<Limb> {
42+
#[inline]
7443
fn add_assign(&mut self, other: Self) {
7544
*self = *self + other;
7645
}
7746
}
7847

7948
impl AddAssign<&Wrapping<Limb>> for Wrapping<Limb> {
49+
#[inline]
8050
fn add_assign(&mut self, other: &Self) {
8151
*self = *self + other;
8252
}
@@ -85,6 +55,7 @@ impl AddAssign<&Wrapping<Limb>> for Wrapping<Limb> {
8555
impl Add for Checked<Limb> {
8656
type Output = Self;
8757

58+
#[inline]
8859
fn add(self, rhs: Self) -> Checked<Limb> {
8960
Checked(
9061
self.0
@@ -96,6 +67,7 @@ impl Add for Checked<Limb> {
9667
impl Add<&Checked<Limb>> for Checked<Limb> {
9768
type Output = Checked<Limb>;
9869

70+
#[inline]
9971
fn add(self, rhs: &Checked<Limb>) -> Checked<Limb> {
10072
Checked(
10173
self.0
@@ -107,6 +79,7 @@ impl Add<&Checked<Limb>> for Checked<Limb> {
10779
impl Add<Checked<Limb>> for &Checked<Limb> {
10880
type Output = Checked<Limb>;
10981

82+
#[inline]
11083
fn add(self, rhs: Checked<Limb>) -> Checked<Limb> {
11184
Checked(
11285
self.0
@@ -118,6 +91,7 @@ impl Add<Checked<Limb>> for &Checked<Limb> {
11891
impl Add<&Checked<Limb>> for &Checked<Limb> {
11992
type Output = Checked<Limb>;
12093

94+
#[inline]
12195
fn add(self, rhs: &Checked<Limb>) -> Checked<Limb> {
12296
Checked(
12397
self.0
@@ -127,17 +101,36 @@ impl Add<&Checked<Limb>> for &Checked<Limb> {
127101
}
128102

129103
impl AddAssign for Checked<Limb> {
104+
#[inline]
130105
fn add_assign(&mut self, other: Self) {
131106
*self = *self + other;
132107
}
133108
}
134109

135110
impl AddAssign<&Checked<Limb>> for Checked<Limb> {
111+
#[inline]
136112
fn add_assign(&mut self, other: &Self) {
137113
*self = *self + other;
138114
}
139115
}
140116

117+
impl CheckedAdd for Limb {
118+
type Output = Self;
119+
120+
#[inline]
121+
fn checked_add(&self, rhs: Self) -> CtOption<Self> {
122+
let (result, carry) = self.adc(rhs, Limb::ZERO);
123+
CtOption::new(result, carry.is_zero())
124+
}
125+
}
126+
127+
impl WrappingAdd for Limb {
128+
#[inline]
129+
fn wrapping_add(&self, v: &Self) -> Self {
130+
self.wrapping_add(*v)
131+
}
132+
}
133+
141134
#[cfg(test)]
142135
mod tests {
143136
use crate::{CheckedAdd, Limb};

src/limb/mul.rs

Lines changed: 37 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
33
use crate::{Checked, CheckedMul, Limb, WideWord, Word, Wrapping, Zero};
44
use core::ops::{Mul, MulAssign};
5+
use num_traits::WrappingMul;
56
use subtle::CtOption;
67

78
impl Limb {
@@ -45,45 +46,52 @@ impl CheckedMul for Limb {
4546
}
4647
}
4748

48-
impl Mul for Wrapping<Limb> {
49-
type Output = Self;
49+
impl Mul<Limb> for Limb {
50+
type Output = Limb;
5051

51-
fn mul(self, rhs: Self) -> Wrapping<Limb> {
52-
Wrapping(self.0.wrapping_mul(rhs.0))
52+
#[inline]
53+
fn mul(self, rhs: Limb) -> Self {
54+
self.checked_mul(rhs)
55+
.expect("attempted to multiply with overflow")
5356
}
5457
}
5558

56-
impl Mul<&Wrapping<Limb>> for Wrapping<Limb> {
57-
type Output = Wrapping<Limb>;
59+
impl Mul<&Limb> for Limb {
60+
type Output = Limb;
5861

59-
fn mul(self, rhs: &Wrapping<Limb>) -> Wrapping<Limb> {
60-
Wrapping(self.0.wrapping_mul(rhs.0))
62+
#[inline]
63+
fn mul(self, rhs: &Limb) -> Self {
64+
self * *rhs
6165
}
6266
}
6367

64-
impl Mul<Wrapping<Limb>> for &Wrapping<Limb> {
65-
type Output = Wrapping<Limb>;
68+
impl Mul<Limb> for &Limb {
69+
type Output = Limb;
6670

67-
fn mul(self, rhs: Wrapping<Limb>) -> Wrapping<Limb> {
68-
Wrapping(self.0.wrapping_mul(rhs.0))
71+
#[inline]
72+
fn mul(self, rhs: Limb) -> Self::Output {
73+
*self * rhs
6974
}
7075
}
7176

72-
impl Mul<&Wrapping<Limb>> for &Wrapping<Limb> {
73-
type Output = Wrapping<Limb>;
77+
impl Mul<&Limb> for &Limb {
78+
type Output = Limb;
7479

75-
fn mul(self, rhs: &Wrapping<Limb>) -> Wrapping<Limb> {
76-
Wrapping(self.0.wrapping_mul(rhs.0))
80+
#[inline]
81+
fn mul(self, rhs: &Limb) -> Self::Output {
82+
*self * *rhs
7783
}
7884
}
7985

8086
impl MulAssign for Wrapping<Limb> {
87+
#[inline]
8188
fn mul_assign(&mut self, other: Self) {
8289
*self = *self * other;
8390
}
8491
}
8592

8693
impl MulAssign<&Wrapping<Limb>> for Wrapping<Limb> {
94+
#[inline]
8795
fn mul_assign(&mut self, other: &Self) {
8896
*self = *self * other;
8997
}
@@ -92,6 +100,7 @@ impl MulAssign<&Wrapping<Limb>> for Wrapping<Limb> {
92100
impl Mul for Checked<Limb> {
93101
type Output = Self;
94102

103+
#[inline]
95104
fn mul(self, rhs: Self) -> Checked<Limb> {
96105
Checked(
97106
self.0
@@ -103,6 +112,7 @@ impl Mul for Checked<Limb> {
103112
impl Mul<&Checked<Limb>> for Checked<Limb> {
104113
type Output = Checked<Limb>;
105114

115+
#[inline]
106116
fn mul(self, rhs: &Checked<Limb>) -> Checked<Limb> {
107117
Checked(
108118
self.0
@@ -114,6 +124,7 @@ impl Mul<&Checked<Limb>> for Checked<Limb> {
114124
impl Mul<Checked<Limb>> for &Checked<Limb> {
115125
type Output = Checked<Limb>;
116126

127+
#[inline]
117128
fn mul(self, rhs: Checked<Limb>) -> Checked<Limb> {
118129
Checked(
119130
self.0
@@ -125,6 +136,7 @@ impl Mul<Checked<Limb>> for &Checked<Limb> {
125136
impl Mul<&Checked<Limb>> for &Checked<Limb> {
126137
type Output = Checked<Limb>;
127138

139+
#[inline]
128140
fn mul(self, rhs: &Checked<Limb>) -> Checked<Limb> {
129141
Checked(
130142
self.0
@@ -134,17 +146,26 @@ impl Mul<&Checked<Limb>> for &Checked<Limb> {
134146
}
135147

136148
impl MulAssign for Checked<Limb> {
149+
#[inline]
137150
fn mul_assign(&mut self, other: Self) {
138151
*self = *self * other;
139152
}
140153
}
141154

142155
impl MulAssign<&Checked<Limb>> for Checked<Limb> {
156+
#[inline]
143157
fn mul_assign(&mut self, other: &Self) {
144158
*self = *self * other;
145159
}
146160
}
147161

162+
impl WrappingMul for Limb {
163+
#[inline]
164+
fn wrapping_mul(&self, v: &Self) -> Self {
165+
self.wrapping_mul(*v)
166+
}
167+
}
168+
148169
#[cfg(test)]
149170
mod tests {
150171
use super::{CheckedMul, Limb, WideWord};

src/limb/neg.rs

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,7 @@
11
//! Limb negation
22
3-
use crate::{Limb, Wrapping};
4-
use core::ops::Neg;
5-
6-
impl Neg for Wrapping<Limb> {
7-
type Output = Self;
8-
9-
fn neg(self) -> Self::Output {
10-
Self(self.0.wrapping_neg())
11-
}
12-
}
3+
use crate::Limb;
4+
use num_traits::WrappingNeg;
135

146
impl Limb {
157
/// Perform wrapping negation.
@@ -18,3 +10,10 @@ impl Limb {
1810
Limb(self.0.wrapping_neg())
1911
}
2012
}
13+
14+
impl WrappingNeg for Limb {
15+
#[inline]
16+
fn wrapping_neg(&self) -> Self {
17+
Self(self.0.wrapping_neg())
18+
}
19+
}

0 commit comments

Comments
 (0)