1use crate::{Choice, CtAssign, CtSelect};
2use core::num::{
3 NonZeroI8, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI128, NonZeroU8, NonZeroU16, NonZeroU32,
4 NonZeroU64, NonZeroU128,
5};
6
7pub trait CtNeg: Sized {
9 #[must_use]
12 fn ct_neg(&self, choice: Choice) -> Self;
13
14 fn ct_neg_assign(&mut self, choice: Choice) {
17 *self = self.ct_neg(choice);
18 }
19}
20
21macro_rules! impl_signed_ct_neg {
23 ( $($int:ty),+ ) => {
24 $(
25 impl CtNeg for $int {
26 #[inline]
27 fn ct_neg(&self, choice: Choice) -> Self {
28 self.ct_select(&-*self, choice)
29 }
30
31 #[inline]
32 fn ct_neg_assign(&mut self, choice: Choice) {
33 self.ct_assign(&-*self, choice)
34 }
35 }
36 )+
37 };
38}
39
40macro_rules! impl_unsigned_ct_neg {
42 ( $($uint:ty),+ ) => {
43 $(
44 impl CtNeg for $uint {
45 #[inline]
46 fn ct_neg(&self, choice: Choice) -> Self {
47 self.ct_select(&self.wrapping_neg(), choice)
48 }
49
50 #[inline]
51 fn ct_neg_assign(&mut self, choice: Choice) {
52 self.ct_assign(&self.wrapping_neg(), choice)
53 }
54 }
55 )+
56 };
57}
58
59impl_signed_ct_neg!(
60 i8,
61 i16,
62 i32,
63 i64,
64 i128,
65 NonZeroI8,
66 NonZeroI16,
67 NonZeroI32,
68 NonZeroI64,
69 NonZeroI128
70);
71impl_unsigned_ct_neg!(u8, u16, u32, u64, u128);
72
73macro_rules! impl_ct_neg_for_unsigned_nonzero {
78 ( $($nzuint:ident),+ ) => {
79 $(
80 impl CtNeg for $nzuint {
81 #[inline]
82 fn ct_neg(&self, choice: Choice) -> Self {
83 let n = self.get().ct_select(&self.get().wrapping_neg(), choice);
85 $nzuint::new(n).expect("should be non-zero")
86 }
87 }
88 )+
89 };
90}
91
92impl_ct_neg_for_unsigned_nonzero!(NonZeroU8, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU128);
93
94#[cfg(test)]
95mod tests {
96 macro_rules! signed_ct_neg_tests {
98 ( $($int:ident),+ ) => {
99 $(
100 mod $int {
101 use crate::{Choice, CtNeg};
102
103 #[test]
104 fn ct_neg() {
105 let n: $int = 42;
106 assert_eq!(n, n.ct_neg(Choice::FALSE));
107 assert_eq!(-n, n.ct_neg(Choice::TRUE));
108 }
109
110 #[test]
111 fn ct_neg_assign() {
112 let n: $int = 42;
113 let mut x = n;
114 x.ct_neg_assign(Choice::FALSE);
115 assert_eq!(n, x);
116
117 x.ct_neg_assign(Choice::TRUE);
118 assert_eq!(-n, x);
119 }
120 }
121 )+
122 };
123 }
124
125 macro_rules! unsigned_ct_neg_tests {
127 ( $($uint:ident),+ ) => {
128 $(
129 mod $uint {
130 use crate::{Choice, CtNeg};
131
132 #[test]
133 fn u32_ct_neg() {
134 let n: $uint = 42;
135 assert_eq!(n, n.ct_neg(Choice::FALSE));
136 assert_eq!(<$uint>::MAX - n + 1, n.ct_neg(Choice::TRUE));
137 }
138
139 #[test]
140 fn u32_ct_neg_assign() {
141 let n: $uint = 42;
142 let mut x = n;
143 x.ct_neg_assign(Choice::FALSE);
144 assert_eq!(n, x);
145
146 x.ct_neg_assign(Choice::TRUE);
147 assert_eq!(<$uint>::MAX - n + 1, x);
148 }
149 }
150 )+
151 };
152 }
153
154 signed_ct_neg_tests!(i8, i16, i32, i64, i128);
155 unsigned_ct_neg_tests!(u8, u16, u32, u64, u128);
156}