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