1#![allow(unused_imports)]
2use super::super::prelude::*;
3
4use core::cmp::Ordering;
5
6macro_rules! num_specs {
7 ($uN: ty, $iN: ty, $modname_u:ident, $modname_i:ident, $range:expr) => {
8 verus! {
9
10 mod $modname_u {
15 use super::*;
16
17 pub assume_specification[<$uN as Clone>::clone](x: &$uN) -> (res: $uN)
18 ensures res == x;
19
20 impl super::super::cmp::PartialEqSpecImpl for $uN {
21 open spec fn obeys_eq_spec() -> bool {
22 true
23 }
24
25 open spec fn eq_spec(&self, other: &$uN) -> bool {
26 *self == *other
27 }
28 }
29
30 impl super::super::cmp::PartialOrdSpecImpl for $uN {
31 open spec fn obeys_partial_cmp_spec() -> bool {
32 true
33 }
34
35 open spec fn partial_cmp_spec(&self, other: &$uN) -> Option<Ordering> {
36 if *self < *other {
37 Some(Ordering::Less)
38 } else if *self > *other {
39 Some(Ordering::Greater)
40 } else {
41 Some(Ordering::Equal)
42 }
43 }
44 }
45
46 impl super::super::cmp::OrdSpecImpl for $uN {
47 open spec fn obeys_cmp_spec() -> bool {
48 true
49 }
50
51 open spec fn cmp_spec(&self, other: &$uN) -> Ordering {
52 if *self < *other {
53 Ordering::Less
54 } else if *self > *other {
55 Ordering::Greater
56 } else {
57 Ordering::Equal
58 }
59 }
60 }
61
62 pub assume_specification[<$uN as PartialEq<$uN>>::eq](x: &$uN, y: &$uN) -> bool;
63
64 pub assume_specification[<$uN as PartialEq<$uN>>::ne](x: &$uN, y: &$uN) -> bool;
65
66 pub assume_specification[<$uN as Ord>::cmp](x: &$uN, y: &$uN) -> Ordering;
67
68 pub assume_specification[<$uN as PartialOrd<$uN>>::partial_cmp](x: &$uN, y: &$uN) -> Option<Ordering>;
69
70 pub assume_specification[<$uN as PartialOrd<$uN>>::lt](x: &$uN, y: &$uN) -> bool;
71
72 pub assume_specification[<$uN as PartialOrd<$uN>>::le](x: &$uN, y: &$uN) -> bool;
73
74 pub assume_specification[<$uN as PartialOrd<$uN>>::gt](x: &$uN, y: &$uN) -> bool;
75
76 pub assume_specification[<$uN as PartialOrd<$uN>>::ge](x: &$uN, y: &$uN) -> bool;
77
78 #[verifier::allow_in_spec]
79 pub assume_specification[<$uN>::wrapping_add](x: $uN, y: $uN) -> $uN
80 returns (
81 if x + y > <$uN>::MAX {
82 (x + y - $range) as $uN
83 } else {
84 (x + y) as $uN
85 }
86 );
87
88 #[verifier::allow_in_spec]
89 pub assume_specification[<$uN>::wrapping_add_signed](x: $uN, y: $iN) -> $uN
90 returns (
91 if x + y > <$uN>::MAX {
92 (x + y - $range) as $uN
93 } else if x + y < 0 {
94 (x + y + $range) as $uN
95 } else {
96 (x + y) as $uN
97 }
98 );
99
100 #[verifier::allow_in_spec]
101 pub assume_specification[<$uN>::wrapping_sub](x: $uN, y: $uN) -> $uN
102 returns (
103 if x - y < 0 {
104 (x - y + $range) as $uN
105 } else {
106 (x - y) as $uN
107 }
108 );
109
110 #[verifier::allow_in_spec]
111 pub assume_specification[<$uN>::wrapping_mul](x: $uN, y: $uN) -> $uN
112 returns ((x as nat * y as nat) % $range as nat) as $uN;
113
114 #[verifier::allow_in_spec]
115 pub assume_specification[<$uN>::checked_add](x: $uN, y: $uN) -> Option<$uN>
116 returns (
117 if x + y > <$uN>::MAX {
118 None
119 } else {
120 Some((x + y) as $uN)
121 }
122 );
123
124 #[verifier::allow_in_spec]
125 pub assume_specification[<$uN>::checked_add_signed](x: $uN, y: $iN) -> Option<$uN>
126 returns (
127 if x + y > <$uN>::MAX || x + y < 0 {
128 None
129 } else {
130 Some((x + y) as $uN)
131 }
132 );
133
134 #[verifier::allow_in_spec]
135 pub assume_specification[<$uN>::checked_sub](x: $uN, y: $uN) -> Option<$uN>
136 returns (
137 if x - y < 0 {
138 None
139 } else {
140 Some((x - y) as $uN)
141 }
142 );
143
144 #[verifier::allow_in_spec]
145 pub assume_specification[<$uN>::checked_mul](x: $uN, y: $uN) -> Option<$uN>
146 returns (
147 if x * y > <$uN>::MAX {
148 None
149 } else {
150 Some((x * y) as $uN)
151 }
152 );
153
154 pub open spec fn checked_div(x: $uN, y: $uN) -> Option<$uN> {
155 if y == 0 {
156 None
157 } else {
158 Some(x / y)
159 }
160 }
161
162 #[verifier::when_used_as_spec(checked_div)]
163 pub assume_specification[<$uN>::checked_div](lhs: $uN, rhs: $uN) -> (result: Option<$uN>)
164 ensures
165 result == checked_div(lhs, rhs);
166
167 #[verifier::when_used_as_spec(checked_div)]
168 pub assume_specification[<$uN>::checked_div_euclid](lhs: $uN, rhs: $uN) -> (result: Option<$uN>)
169 ensures
170 result == checked_div(lhs, rhs);
172
173 #[verifier::allow_in_spec]
174 pub assume_specification[<$uN>::is_multiple_of](x: $uN, y: $uN) -> bool
175 returns (
176 if y == 0 { x == 0 } else { x % y == 0 }
177 );
178 }
179
180 mod $modname_i {
183 use super::*;
184
185 pub assume_specification[<$iN as Clone>::clone](x: &$iN) -> (res: $iN)
186 ensures res == x;
187
188 impl super::super::cmp::PartialEqSpecImpl for $iN {
189 open spec fn obeys_eq_spec() -> bool {
190 true
191 }
192
193 open spec fn eq_spec(&self, other: &$iN) -> bool {
194 *self == *other
195 }
196 }
197
198 impl super::super::cmp::PartialOrdSpecImpl for $iN {
199 open spec fn obeys_partial_cmp_spec() -> bool {
200 true
201 }
202
203 open spec fn partial_cmp_spec(&self, other: &$iN) -> Option<Ordering> {
204 if *self < *other {
205 Some(Ordering::Less)
206 } else if *self > *other {
207 Some(Ordering::Greater)
208 } else {
209 Some(Ordering::Equal)
210 }
211 }
212 }
213
214 impl super::super::cmp::OrdSpecImpl for $iN {
215 open spec fn obeys_cmp_spec() -> bool {
216 true
217 }
218
219 open spec fn cmp_spec(&self, other: &$iN) -> Ordering {
220 if *self < *other {
221 Ordering::Less
222 } else if *self > *other {
223 Ordering::Greater
224 } else {
225 Ordering::Equal
226 }
227 }
228 }
229
230 pub assume_specification[<$iN as PartialEq<$iN>>::eq](x: &$iN, y: &$iN) -> bool;
231
232 pub assume_specification[<$iN as PartialEq<$iN>>::ne](x: &$iN, y: &$iN) -> bool;
233
234 pub assume_specification[<$iN as Ord>::cmp](x: &$iN, y: &$iN) -> Ordering;
235
236 pub assume_specification[<$iN as PartialOrd<$iN>>::partial_cmp](x: &$iN, y: &$iN) -> Option<Ordering>;
237
238 pub assume_specification[<$iN as PartialOrd<$iN>>::lt](x: &$iN, y: &$iN) -> bool;
239
240 pub assume_specification[<$iN as PartialOrd<$iN>>::le](x: &$iN, y: &$iN) -> bool;
241
242 pub assume_specification[<$iN as PartialOrd<$iN>>::gt](x: &$iN, y: &$iN) -> bool;
243
244 pub assume_specification[<$iN as PartialOrd<$iN>>::ge](x: &$iN, y: &$iN) -> bool;
245
246 #[verifier::allow_in_spec]
247 pub assume_specification[<$iN>::wrapping_add](x: $iN, y: $iN) -> $iN
248 returns (
249 if x + y > <$iN>::MAX {
250 (x + y - $range) as $iN
251 } else if x + y < <$iN>::MIN {
252 (x + y + $range) as $iN
253 } else {
254 (x + y) as $iN
255 }
256 );
257
258 #[verifier::allow_in_spec]
259 pub assume_specification[<$iN>::wrapping_add_unsigned](x: $iN, y: $uN) -> $iN
260 returns (
261 if x + y > <$iN>::MAX {
262 (x + y - $range) as $iN
263 } else {
264 (x + y) as $iN
265 }
266 );
267
268 #[verifier::allow_in_spec]
269 pub assume_specification[<$iN>::wrapping_sub](x: $iN, y: $iN) -> (res: $iN)
270 returns (
271 if x - y > <$iN>::MAX {
272 (x - y - $range) as $iN
273 } else if x - y < <$iN>::MIN {
274 (x - y + $range) as $iN
275 } else {
276 (x - y) as $iN
277 }
278 );
279
280 pub open spec fn signed_crop(x: int) -> $iN {
281 if (x % ($range as int)) > (<$iN>::MAX as int) {
282 ((x % ($range as int)) - $range) as $iN
283 } else {
284 (x % ($range as int)) as $iN
285 }
286 }
287
288 #[verifier::allow_in_spec]
289 pub assume_specification[<$iN>::wrapping_mul](x: $iN, y: $iN) -> $iN
290 returns signed_crop(x * y);
291
292 #[verifier::allow_in_spec]
293 pub assume_specification[<$iN>::checked_add](x: $iN, y: $iN) -> Option<$iN>
294 returns (
295 if x + y > <$iN>::MAX || x + y < <$iN>::MIN {
296 None
297 } else {
298 Some((x + y) as $iN)
299 }
300 );
301
302 #[verifier::allow_in_spec]
303 pub assume_specification[<$iN>::checked_add_unsigned](x: $iN, y: $uN) -> Option<$iN>
304 returns (
305 if x + y > <$iN>::MAX {
306 None
307 } else {
308 Some((x + y) as $iN)
309 }
310 );
311
312 #[verifier::allow_in_spec]
313 pub assume_specification[<$uN>::saturating_add](x: $uN, y: $uN) -> $uN
314 returns (
315 if x + y > <$uN>::MAX {
316 <$uN>::MAX
317 } else {
318 (x + y) as $uN
319 }
320 );
321
322 #[verifier::allow_in_spec]
323 pub assume_specification[<$uN>::saturating_sub](x: $uN, y: $uN) -> $uN
324 returns (
325 if x - y < <$uN>::MIN {
326 <$uN>::MIN
327 } else {
328 (x - y) as $uN
329 }
330 );
331
332 #[verifier::allow_in_spec]
333 pub assume_specification[<$iN>::checked_sub](x: $iN, y: $iN) -> Option<$iN>
334 returns (
335 if x - y > <$iN>::MAX || x - y < <$iN>::MIN {
336 None
337 } else {
338 Some((x - y) as $iN)
339 }
340 );
341
342 #[verifier::allow_in_spec]
343 pub assume_specification[<$iN>::checked_sub_unsigned](x: $iN, y: $uN) -> Option<$iN>
344 returns (
345 if x - y < <$iN>::MIN {
346 None
347 } else {
348 Some((x - y) as $iN)
349 }
350 );
351
352 #[verifier::allow_in_spec]
353 pub assume_specification[<$iN>::checked_mul](x: $iN, y: $iN) -> Option<$iN>
354 returns (
355 if x * y > <$iN>::MAX || x * y < <$iN>::MIN {
356 None
357 } else {
358 Some((x * y) as $iN)
359 }
360 );
361 }
362
363 }
364 };
365}
366
367num_specs!(u8, i8, u8_specs, i8_specs, 0x100);
368num_specs!(u16, i16, u16_specs, i16_specs, 0x1_0000);
369num_specs!(u32, i32, u32_specs, i32_specs, 0x1_0000_0000);
370num_specs!(u64, i64, u64_specs, i64_specs, 0x1_0000_0000_0000_0000);
371num_specs!(u128, i128, u128_specs, i128_specs, 0x1_0000_0000_0000_0000_0000_0000_0000_0000);
372num_specs!(usize, isize, usize_specs, isize_specs, (usize::MAX - usize::MIN + 1));
373
374verus! {
375
376pub assume_specification[ u32::checked_rem ](lhs: u32, rhs: u32) -> (result: Option<u32>)
379 ensures
380 rhs == 0 ==> result is None,
381 rhs != 0 ==> result == Some((lhs % rhs) as u32),
382;
383
384pub assume_specification[ u32::checked_rem_euclid ](lhs: u32, rhs: u32) -> (result: Option<u32>)
385 ensures
386 rhs == 0 ==> result is None,
387 rhs != 0 ==> result == Some((lhs % rhs) as u32),
388;
389
390pub assume_specification[ i32::checked_div ](lhs: i32, rhs: i32) -> (result: Option<i32>)
392 ensures
393 rhs == 0 ==> result is None,
394 ({
395 let x = lhs as int;
396 let d = rhs as int;
397 let output = if x == 0 {
398 0
399 } else if x > 0 && d > 0 {
400 x / d
401 } else if x < 0 && d < 0 {
402 ((x * -1) / (d * -1))
403 } else if x < 0 {
404 ((x * -1) / d) * -1
405 } else { (x / (d * -1)) * -1
407 };
408 if output < i32::MIN || output > i32::MAX {
409 result is None
410 } else {
411 result == Some(output as i32)
412 }
413 }),
414;
415
416pub assume_specification[ i32::checked_div_euclid ](lhs: i32, rhs: i32) -> (result: Option<i32>)
417 ensures
418 rhs == 0 ==> result is None,
419 lhs / rhs < i32::MIN || lhs / rhs > i32::MAX ==> result is None,
420 i32::MIN <= lhs / rhs <= i32::MAX ==> result == Some((lhs / rhs) as i32),
421;
422
423pub assume_specification[ i32::checked_rem ](lhs: i32, rhs: i32) -> (result: Option<i32>)
424 ensures
425 rhs == 0 ==> result is None,
426 ({
427 let x = lhs as int;
428 let d = rhs as int;
429 let output = if x == 0 {
430 0
431 } else if x > 0 && d > 0 {
432 x % d
433 } else if x < 0 && d < 0 {
434 ((x * -1) % (d * -1)) * -1
435 } else if x < 0 {
436 ((x * -1) % d) * -1
437 } else { x % (d * -1)
439 };
440 if output < i32::MIN || output > i32::MAX {
441 result is None
442 } else {
443 result == Some(output as i32)
444 }
445 }),
446;
447
448pub assume_specification[ i32::checked_rem_euclid ](lhs: i32, rhs: i32) -> (result: Option<i32>)
449 ensures
450 rhs == 0 ==> result is None,
451 lhs % rhs < i32::MIN || lhs % rhs > i32::MAX ==> result is None,
452 i32::MIN <= lhs % rhs <= i32::MAX ==> result == Some((lhs % rhs) as i32),
453;
454
455}