1#[inline(always)]
13pub fn ct_select(choice: u64, a: u64, b: u64) -> u64 {
14 ct_select_u64(choice, a, b)
15}
16
17#[inline(always)]
19pub fn ct_select_u64(choice: u64, a: u64, b: u64) -> u64 {
20 let mask = choice.wrapping_neg();
21 (a & mask) | (b & !mask)
22}
23
24#[inline(always)]
26pub fn ct_select_u32(choice: u32, a: u32, b: u32) -> u32 {
27 let mask = choice.wrapping_neg();
28 (a & mask) | (b & !mask)
29}
30
31#[inline(always)]
36pub fn ct_lt(a: u64, b: u64) -> u64 {
37 let a128 = a as i128;
38 let b128 = b as i128;
39 let diff = a128 - b128;
40 ((diff >> 127) & 1) as u64
41}
42
43#[inline(always)]
48pub fn ct_eq(a: u64, b: u64) -> u64 {
49 let diff = a ^ b;
50 ((diff.wrapping_sub(1)) & !diff) >> 63
51}
52
53#[inline(always)]
58pub fn ct_gt(a: u64, b: u64) -> u64 {
59 ct_lt(b, a)
60}
61
62#[inline(always)]
67pub fn ct_le(a: u64, b: u64) -> u64 {
68 !ct_gt(a, b)
69}
70
71#[inline(always)]
76pub fn ct_ge(a: u64, b: u64) -> u64 {
77 !ct_lt(a, b)
78}
79
80#[inline(always)]
84pub fn ct_mask(mask: u64, value: u64) -> u64 {
85 mask & value
86}
87
88#[inline(always)]
93pub fn ct_swap(choice: u64, a: &mut u64, b: &mut u64) {
94 let mask = choice.wrapping_neg();
95 let diff = *a ^ *b;
96 *a ^= diff & mask;
97 *b ^= diff & mask;
98}
99
100#[inline(always)]
104pub fn ct_swap_slice(choice: u64, a: &mut [u64], b: &mut [u64]) {
105 let mask = choice.wrapping_neg();
106 let len = a.len().min(b.len());
107 for i in 0..len {
108 let diff = a[i] ^ b[i];
109 a[i] ^= diff & mask;
110 b[i] ^= diff & mask;
111 }
112}
113
114#[cfg(test)]
115mod tests {
116 use super::*;
117
118 #[test]
119 fn test_ct_select() {
120 assert_eq!(ct_select_u64(0, 10, 20), 20);
121 assert_eq!(ct_select_u64(1, 10, 20), 10);
122 assert_eq!(ct_select_u64(0, 0xFFFF, 0x0000), 0x0000);
123 assert_eq!(ct_select_u64(1, 0xFFFF, 0x0000), 0xFFFF);
124 }
125
126 #[test]
127 fn test_ct_lt() {
128 assert_eq!(ct_lt(5, 10), 1);
129 assert_eq!(ct_lt(10, 5), 0);
130 assert_eq!(ct_lt(10, 10), 0);
131 assert_eq!(ct_lt(0, u64::MAX), 1);
132 }
133
134 #[test]
135 fn test_ct_eq() {
136 assert_eq!(ct_eq(5, 5), 1);
137 assert_eq!(ct_eq(5, 10), 0);
138 assert_eq!(ct_eq(0, 0), 1);
139 assert_eq!(ct_eq(u64::MAX, u64::MAX), 1);
140 }
141
142 #[test]
143 fn test_ct_swap() {
144 let mut a = 10u64;
145 let mut b = 20u64;
146 ct_swap(0, &mut a, &mut b);
147 assert_eq!(a, 10);
148 assert_eq!(b, 20);
149
150 let mut a = 10u64;
151 let mut b = 20u64;
152 ct_swap(1, &mut a, &mut b);
153 assert_eq!(a, 20);
154 assert_eq!(b, 10);
155 }
156}