1use super::{
2 FixedUInt, MachineWord, const_is_one, const_is_one_ct, const_is_zero, const_is_zero_ct,
3};
4use crate::machineword::ConstMachineWord;
5use const_num_traits::{Bounded, ConstOne, ConstZero, One, Zero};
6use const_num_traits::{Personality, PersonalityTag};
7
8c0nst::c0nst! {
9 c0nst impl<T: [c0nst] ConstMachineWord + MachineWord, const N: usize, P: Personality> Zero for FixedUInt<T, N, P> {
10 fn zero() -> Self {
11 FixedUInt::from_array([<T as Zero>::zero(); N])
12 }
13 fn is_zero(&self) -> bool {
14 match P::TAG {
15 PersonalityTag::Nct => const_is_zero(&self.array),
16 PersonalityTag::Ct => const_is_zero_ct(&self.array),
17 }
18 }
19 fn set_zero(&mut self) {
20 let mut i = 0;
21 while i < N {
22 <T as Zero>::set_zero(&mut self.array[i]);
23 i += 1;
24 }
25 }
26 }
27
28
29 c0nst impl<T: [c0nst] ConstMachineWord + MachineWord, const N: usize, P: Personality> One for FixedUInt<T, N, P> {
30 fn one() -> Self {
31 let mut ret = <Self as ConstZero>::ZERO;
32 if N > 0 {
33 ret.array[0] = <T as One>::one();
34 }
35 ret
36 }
37 fn is_one(&self) -> bool {
38 match P::TAG {
39 PersonalityTag::Nct => const_is_one(&self.array),
40 PersonalityTag::Ct => const_is_one_ct(&self.array),
41 }
42 }
43 fn set_one(&mut self) {
44 <Self as Zero>::set_zero(self);
45 if N > 0 {
46 <T as One>::set_one(&mut self.array[0]);
47 }
48 }
49 }
50
51
52 c0nst impl<T: [c0nst] ConstMachineWord + MachineWord, const N: usize, P: Personality> Bounded for FixedUInt<T, N, P> {
53 fn min_value() -> Self {
54 <Self as ConstZero>::ZERO
55 }
56 fn max_value() -> Self {
57 FixedUInt::from_array([<T as Bounded>::max_value(); N])
58 }
59 }
60}
61
62impl<T: ConstMachineWord + MachineWord, const N: usize, P: Personality> ConstZero
68 for FixedUInt<T, N, P>
69{
70 const ZERO: Self = FixedUInt::from_array([<T as ConstZero>::ZERO; N]);
71}
72
73impl<T: ConstMachineWord + MachineWord, const N: usize, P: Personality> ConstOne
74 for FixedUInt<T, N, P>
75{
76 const ONE: Self = {
77 let mut a = [<T as ConstZero>::ZERO; N];
78 if N > 0 {
79 a[0] = <T as ConstOne>::ONE;
80 }
81 FixedUInt::from_array(a)
82 };
83}
84
85#[cfg(feature = "num-traits")]
86impl<T: MachineWord, const N: usize, P: Personality> num_traits::Zero for FixedUInt<T, N, P> {
87 fn zero() -> Self {
88 <Self as ConstZero>::ZERO
89 }
90 fn is_zero(&self) -> bool {
91 <Self as Zero>::is_zero(self)
92 }
93}
94
95#[cfg(feature = "num-traits")]
96impl<T: MachineWord, const N: usize, P: Personality> num_traits::One for FixedUInt<T, N, P> {
97 fn one() -> Self {
98 <Self as ConstOne>::ONE
99 }
100}
101
102#[cfg(feature = "num-traits")]
103impl<T: MachineWord, const N: usize, P: Personality> num_traits::Bounded for FixedUInt<T, N, P> {
104 fn min_value() -> Self {
105 <Self as Bounded>::min_value()
106 }
107 fn max_value() -> Self {
108 <Self as Bounded>::max_value()
109 }
110}
111
112impl<T, const N: usize, P: Personality> const_num_traits::ops::ct::CtIsZero for FixedUInt<T, N, P>
121where
122 T: MachineWord + subtle::ConstantTimeEq,
123{
124 fn ct_is_zero(&self) -> subtle::Choice {
125 let mut choice = subtle::Choice::from(1u8);
126 let mut i = 0;
127 while i < N {
128 choice &= self.array[i].ct_eq(&<T as ConstZero>::ZERO);
129 i += 1;
130 }
131 choice
132 }
133}
134
135#[cfg(test)]
136mod tests {
137 use super::*;
138 use const_num_traits::Nct;
139
140 c0nst::c0nst! {
141 c0nst fn const_zero<T: [c0nst] ConstMachineWord + MachineWord, const N: usize, P: Personality>() -> FixedUInt<T, N, P> {
142 <FixedUInt<T, N, P> as ConstZero>::ZERO
143 }
144
145 c0nst fn const_one<T: [c0nst] ConstMachineWord + MachineWord, const N: usize, P: Personality>() -> FixedUInt<T, N, P> {
146 <FixedUInt<T, N, P> as ConstOne>::ONE
147 }
148
149 c0nst fn const_is_zero<T: [c0nst] ConstMachineWord + MachineWord, const N: usize, P: Personality>(v: &FixedUInt<T, N, P>) -> bool {
150 <FixedUInt<T, N, P> as Zero>::is_zero(v)
151 }
152
153 c0nst fn const_is_one<T: [c0nst] ConstMachineWord + MachineWord, const N: usize, P: Personality>(v: &FixedUInt<T, N, P>) -> bool {
154 <FixedUInt<T, N, P> as One>::is_one(v)
155 }
156
157 c0nst fn const_min_value<T: [c0nst] ConstMachineWord + MachineWord, const N: usize, P: Personality>() -> FixedUInt<T, N, P> {
158 <FixedUInt<T, N, P> as Bounded>::min_value()
159 }
160
161 c0nst fn const_max_value<T: [c0nst] ConstMachineWord + MachineWord, const N: usize, P: Personality>() -> FixedUInt<T, N, P> {
162 <FixedUInt<T, N, P> as Bounded>::max_value()
163 }
164
165 c0nst fn const_set_zero<T: [c0nst] ConstMachineWord + MachineWord, const N: usize, P: Personality>(v: &mut FixedUInt<T, N, P>) {
166 <FixedUInt<T, N, P> as Zero>::set_zero(v)
167 }
168
169 c0nst fn const_set_one<T: [c0nst] ConstMachineWord + MachineWord, const N: usize, P: Personality>(v: &mut FixedUInt<T, N, P>) {
170 <FixedUInt<T, N, P> as One>::set_one(v)
171 }
172 }
173
174 #[test]
175 fn test_const_identity_traits() {
176 type TestInt = FixedUInt<u8, 2>;
177
178 let zero = const_zero::<u8, 2, Nct>();
180 assert!(const_is_zero(&zero));
181 assert!(!const_is_one(&zero));
182
183 let one = const_one::<u8, 2, Nct>();
185 assert!(!const_is_zero(&one));
186 assert!(const_is_one(&one));
187
188 let min = const_min_value::<u8, 2, Nct>();
190 let max = const_max_value::<u8, 2, Nct>();
191 assert!(const_is_zero(&min));
192 assert_eq!(max.array, [255, 255]);
193
194 let mut val = TestInt::from(42u8);
196 const_set_zero(&mut val);
197 assert!(const_is_zero(&val));
198
199 const_set_one(&mut val);
200 assert!(const_is_one(&val));
201
202 #[cfg(feature = "nightly")]
203 {
204 const ZERO: TestInt = const_zero::<u8, 2, Nct>();
205 const ONE: TestInt = const_one::<u8, 2, Nct>();
206 const IS_ZERO_TRUE: bool = const_is_zero(&ZERO);
207 const IS_ZERO_FALSE: bool = const_is_zero(&ONE);
208 const IS_ONE_TRUE: bool = const_is_one(&ONE);
209 const IS_ONE_FALSE: bool = const_is_one(&ZERO);
210 const MIN: TestInt = const_min_value::<u8, 2, Nct>();
211 const MAX: TestInt = const_max_value::<u8, 2, Nct>();
212
213 assert_eq!(ZERO.array, [0, 0]);
214 assert_eq!(ONE.array, [1, 0]);
215 assert!(IS_ZERO_TRUE);
216 assert!(!IS_ZERO_FALSE);
217 assert!(IS_ONE_TRUE);
218 assert!(!IS_ONE_FALSE);
219 assert_eq!(MIN.array, [0, 0]);
220 assert_eq!(MAX.array, [255, 255]);
221
222 const SET_ZERO_RES: TestInt = {
223 let mut v = FixedUInt::from_array([42, 0]);
224 const_set_zero(&mut v);
225 v
226 };
227 const SET_ONE_RES: TestInt = {
228 let mut v = FixedUInt::from_array([0, 0]);
229 const_set_one(&mut v);
230 v
231 };
232 assert_eq!(SET_ZERO_RES.array, [0, 0]);
233 assert_eq!(SET_ONE_RES.array, [1, 0]);
234 }
235 }
236
237 #[test]
238 fn ct_is_zero_matches_is_zero() {
239 use const_num_traits::Ct;
240 use const_num_traits::ops::ct::CtIsZero;
241 type U16Nct = FixedUInt<u8, 2>;
242 type U16Ct = FixedUInt<u8, 2, Ct>;
243 assert!(bool::from(CtIsZero::ct_is_zero(&U16Nct::from(0u8))));
245 assert!(!bool::from(CtIsZero::ct_is_zero(&U16Nct::from(1u8))));
246 assert!(!bool::from(CtIsZero::ct_is_zero(&U16Nct::from(0xFFFFu16))));
247 assert!(!bool::from(CtIsZero::ct_is_zero(
249 &FixedUInt::<u8, 2>::from_array([0, 1])
250 )));
251 let z_ct: U16Ct = U16Nct::from(0u8).into();
253 let nz_ct: U16Ct = U16Nct::from(42u8).into();
254 assert!(bool::from(CtIsZero::ct_is_zero(&z_ct)));
255 assert!(!bool::from(CtIsZero::ct_is_zero(&nz_ct)));
256 }
257}