Skip to content

Commit 5bbbb9b

Browse files
authored
ctutils: unsigned CtNeg impls (#1306)
Uses `wrapping_neg` to perform (conditional) negation for: `u8`, `u16`, `u32`, `u64`, `u128` Also expands the tests using macros to test every integer type we write impls for
1 parent 228b20c commit 5bbbb9b

1 file changed

Lines changed: 83 additions & 18 deletions

File tree

ctutils/src/traits/ct_neg.rs

Lines changed: 83 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,11 @@ pub trait CtNeg: Sized {
1313
}
1414
}
1515

16-
// Impl `CtNeg` for an integer type which impls `CtSelect`
17-
macro_rules! impl_ct_neg {
18-
( $($ty:ty),+ ) => {
16+
// Impl `CtNeg` for a signed integer (`i*`) type which impls `CtSelect`
17+
macro_rules! impl_signed_ct_neg {
18+
( $($int:ty),+ ) => {
1919
$(
20-
impl CtNeg for $ty {
20+
impl CtNeg for $int {
2121
#[inline]
2222
fn ct_neg(&self, choice: Choice) -> Self {
2323
let neg = -*self;
@@ -34,26 +34,91 @@ macro_rules! impl_ct_neg {
3434
};
3535
}
3636

37-
impl_ct_neg!(i8, i16, i32, i64, i128);
37+
// Impl `CtNeg` for an unsigned integer (`u*`) type which impls `CtSelect`
38+
macro_rules! impl_unsigned_ct_neg {
39+
( $($uint:ty),+ ) => {
40+
$(
41+
impl CtNeg for $uint {
42+
#[inline]
43+
fn ct_neg(&self, choice: Choice) -> Self {
44+
let neg = self.wrapping_neg();
45+
self.ct_select(&neg, choice)
46+
}
47+
48+
#[inline]
49+
fn ct_neg_assign(&mut self, choice: Choice) {
50+
let neg = self.wrapping_neg();
51+
self.ct_assign(&neg, choice)
52+
}
53+
}
54+
)+
55+
};
56+
}
3857

39-
// TODO(tarcieri): test all signed integer types
58+
impl_signed_ct_neg!(i8, i16, i32, i64, i128);
59+
impl_unsigned_ct_neg!(u8, u16, u32, u64, u128);
60+
61+
// TODO(tarcieri): test all signed/unsigned integer types
4062
#[cfg(test)]
4163
mod tests {
42-
use super::{Choice, CtNeg};
64+
/// Test `CtNeg` impl on `i*`
65+
macro_rules! signed_ct_neg_tests {
66+
( $($int:ident),+ ) => {
67+
$(
68+
mod $int {
69+
use crate::{Choice, CtNeg};
70+
71+
#[test]
72+
fn ct_neg() {
73+
let n: $int = 42;
74+
assert_eq!(n, n.ct_neg(Choice::FALSE));
75+
assert_eq!(-n, n.ct_neg(Choice::TRUE));
76+
}
77+
78+
#[test]
79+
fn ct_neg_assign() {
80+
let n: $int = 42;
81+
let mut x = n;
82+
x.ct_neg_assign(Choice::FALSE);
83+
assert_eq!(n, x);
4384

44-
#[test]
45-
fn i64_ct_neg() {
46-
assert_eq!(42, 42.ct_neg(Choice::FALSE));
47-
assert_eq!(-42, 42.ct_neg(Choice::TRUE));
85+
x.ct_neg_assign(Choice::TRUE);
86+
assert_eq!(-n, x);
87+
}
88+
}
89+
)+
90+
};
4891
}
4992

50-
#[test]
51-
fn i64_ct_neg_assign() {
52-
let mut n = 42;
53-
n.ct_neg_assign(Choice::FALSE);
54-
assert_eq!(42, n);
93+
/// Test `CtNeg` impl on `u*`
94+
macro_rules! unsigned_ct_neg_tests {
95+
( $($uint:ident),+ ) => {
96+
$(
97+
mod $uint {
98+
use crate::{Choice, CtNeg};
99+
100+
#[test]
101+
fn u32_ct_neg() {
102+
let n: $uint = 42;
103+
assert_eq!(n, n.ct_neg(Choice::FALSE));
104+
assert_eq!(<$uint>::MAX - n + 1, n.ct_neg(Choice::TRUE));
105+
}
106+
107+
#[test]
108+
fn u32_ct_neg_assign() {
109+
let n: $uint = 42;
110+
let mut x = n;
111+
x.ct_neg_assign(Choice::FALSE);
112+
assert_eq!(n, x);
55113

56-
n.ct_neg_assign(Choice::TRUE);
57-
assert_eq!(-42, n);
114+
x.ct_neg_assign(Choice::TRUE);
115+
assert_eq!(<$uint>::MAX - n + 1, x);
116+
}
117+
}
118+
)+
119+
};
58120
}
121+
122+
signed_ct_neg_tests!(i8, i16, i32, i64, i128);
123+
unsigned_ct_neg_tests!(u8, u16, u32, u64, u128);
59124
}

0 commit comments

Comments
 (0)