-
Notifications
You must be signed in to change notification settings - Fork 167
Expand file tree
/
Copy pathct_neg.rs
More file actions
123 lines (107 loc) · 3.69 KB
/
Copy pathct_neg.rs
File metadata and controls
123 lines (107 loc) · 3.69 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
use crate::{Choice, CtAssign, CtSelect};
/// Constant-time conditional negation: negates a value when `choice` is [`Choice::TRUE`].
pub trait CtNeg: Sized {
/// Conditionally negate `self`, returning `-self` if `choice` is [`Choice::TRUE`], or `self`
/// otherwise.
fn ct_neg(&self, choice: Choice) -> Self;
/// Conditionally negate `self` in-place, replacing it with `-self` if `choice` is
/// [`Choice::TRUE`].
fn ct_neg_assign(&mut self, choice: Choice) {
*self = self.ct_neg(choice);
}
}
// Impl `CtNeg` for a signed integer (`i*`) type which impls `CtSelect`
macro_rules! impl_signed_ct_neg {
( $($int:ty),+ ) => {
$(
impl CtNeg for $int {
#[inline]
fn ct_neg(&self, choice: Choice) -> Self {
let neg = -*self;
self.ct_select(&neg, choice)
}
#[inline]
fn ct_neg_assign(&mut self, choice: Choice) {
let neg = -*self;
self.ct_assign(&neg, choice)
}
}
)+
};
}
// Impl `CtNeg` for an unsigned integer (`u*`) type which impls `CtSelect`
macro_rules! impl_unsigned_ct_neg {
( $($uint:ty),+ ) => {
$(
impl CtNeg for $uint {
#[inline]
fn ct_neg(&self, choice: Choice) -> Self {
let neg = self.wrapping_neg();
self.ct_select(&neg, choice)
}
#[inline]
fn ct_neg_assign(&mut self, choice: Choice) {
let neg = self.wrapping_neg();
self.ct_assign(&neg, choice)
}
}
)+
};
}
impl_signed_ct_neg!(i8, i16, i32, i64, i128);
impl_unsigned_ct_neg!(u8, u16, u32, u64, u128);
#[cfg(test)]
mod tests {
/// Test `CtNeg` impl on `i*`
macro_rules! signed_ct_neg_tests {
( $($int:ident),+ ) => {
$(
mod $int {
use crate::{Choice, CtNeg};
#[test]
fn ct_neg() {
let n: $int = 42;
assert_eq!(n, n.ct_neg(Choice::FALSE));
assert_eq!(-n, n.ct_neg(Choice::TRUE));
}
#[test]
fn ct_neg_assign() {
let n: $int = 42;
let mut x = n;
x.ct_neg_assign(Choice::FALSE);
assert_eq!(n, x);
x.ct_neg_assign(Choice::TRUE);
assert_eq!(-n, x);
}
}
)+
};
}
/// Test `CtNeg` impl on `u*`
macro_rules! unsigned_ct_neg_tests {
( $($uint:ident),+ ) => {
$(
mod $uint {
use crate::{Choice, CtNeg};
#[test]
fn u32_ct_neg() {
let n: $uint = 42;
assert_eq!(n, n.ct_neg(Choice::FALSE));
assert_eq!(<$uint>::MAX - n + 1, n.ct_neg(Choice::TRUE));
}
#[test]
fn u32_ct_neg_assign() {
let n: $uint = 42;
let mut x = n;
x.ct_neg_assign(Choice::FALSE);
assert_eq!(n, x);
x.ct_neg_assign(Choice::TRUE);
assert_eq!(<$uint>::MAX - n + 1, x);
}
}
)+
};
}
signed_ct_neg_tests!(i8, i16, i32, i64, i128);
unsigned_ct_neg_tests!(u8, u16, u32, u64, u128);
}