1use crate::prelude::*;
4use core::cmp::Ordering;
5
6#[allow(unused)]
14pub trait OrdLogic {
15 #[logic]
20 fn cmp_log(self, other: Self) -> Ordering;
21
22 #[logic(open)]
24 fn le_log(self, o: Self) -> bool {
25 pearlite! { self.cmp_log(o) != Ordering::Greater }
26 }
27
28 #[logic(law)]
29 #[ensures(x.le_log(y) == (x.cmp_log(y) != Ordering::Greater))]
30 fn cmp_le_log(x: Self, y: Self);
31
32 #[logic(open)]
34 fn lt_log(self, o: Self) -> bool {
35 pearlite! { self.cmp_log(o) == Ordering::Less }
36 }
37
38 #[logic(law)]
39 #[ensures(x.lt_log(y) == (x.cmp_log(y) == Ordering::Less))]
40 fn cmp_lt_log(x: Self, y: Self);
41
42 #[logic(open)]
44 fn ge_log(self, o: Self) -> bool {
45 pearlite! { self.cmp_log(o) != Ordering::Less }
46 }
47
48 #[logic(law)]
49 #[ensures(x.ge_log(y) == (x.cmp_log(y) != Ordering::Less))]
50 fn cmp_ge_log(x: Self, y: Self);
51
52 #[logic(open)]
54 fn gt_log(self, o: Self) -> bool {
55 pearlite! { self.cmp_log(o) == Ordering::Greater }
56 }
57
58 #[logic(law)]
59 #[ensures(x.gt_log(y) == (x.cmp_log(y) == Ordering::Greater))]
60 fn cmp_gt_log(x: Self, y: Self);
61
62 #[logic(law)]
64 #[ensures(x.cmp_log(x) == Ordering::Equal)]
65 fn refl(x: Self);
66
67 #[logic(law)]
69 #[requires(x.cmp_log(y) == o)]
70 #[requires(y.cmp_log(z) == o)]
71 #[ensures(x.cmp_log(z) == o)]
72 fn trans(x: Self, y: Self, z: Self, o: Ordering);
73
74 #[logic(law)]
78 #[requires(x.cmp_log(y) == Ordering::Less)]
79 #[ensures(y.cmp_log(x) == Ordering::Greater)]
80 fn antisym1(x: Self, y: Self);
81
82 #[logic(law)]
86 #[requires(x.cmp_log(y) == Ordering::Greater)]
87 #[ensures(y.cmp_log(x) == Ordering::Less)]
88 fn antisym2(x: Self, y: Self);
89
90 #[logic(law)]
92 #[ensures((x == y) == (x.cmp_log(y) == Ordering::Equal))]
93 fn eq_cmp(x: Self, y: Self);
94}
95
96#[macro_export]
159macro_rules! ord_laws_impl {
160 ( $($lemma:stmt)* ) => {
161 #[::creusot_std::macros::logic(open(self), law)]
162 #[::creusot_std::macros::ensures(x.le_log(y) == (x.cmp_log(y) != Ordering::Greater))]
163 fn cmp_le_log(x: Self, y: Self) {
164 $($lemma)*
165 }
166
167 #[::creusot_std::macros::logic(open(self), law)]
168 #[::creusot_std::macros::ensures(x.lt_log(y) == (x.cmp_log(y) == Ordering::Less))]
169 fn cmp_lt_log(x: Self, y: Self) {
170 $($lemma)*
171 }
172
173 #[::creusot_std::macros::logic(open(self), law)]
174 #[::creusot_std::macros::ensures(x.ge_log(y) == (x.cmp_log(y) != Ordering::Less))]
175 fn cmp_ge_log(x: Self, y: Self) {
176 $($lemma)*
177 }
178
179 #[::creusot_std::macros::logic(open(self), law)]
180 #[::creusot_std::macros::ensures(x.gt_log(y) == (x.cmp_log(y) == Ordering::Greater))]
181 fn cmp_gt_log(x: Self, y: Self) {
182 $($lemma)*
183 }
184
185 #[::creusot_std::macros::logic(open(self), law)]
186 #[::creusot_std::macros::ensures(x.cmp_log(x) == Ordering::Equal)]
187 fn refl(x: Self) {
188 $($lemma)*
189 }
190
191 #[::creusot_std::macros::logic(open(self), law)]
192 #[::creusot_std::macros::requires(x.cmp_log(y) == o)]
193 #[::creusot_std::macros::requires(y.cmp_log(z) == o)]
194 #[::creusot_std::macros::ensures(x.cmp_log(z) == o)]
195 fn trans(x: Self, y: Self, z: Self, o: Ordering) {
196 $($lemma)*
197 }
198
199 #[::creusot_std::macros::logic(open(self), law)]
200 #[::creusot_std::macros::requires(x.cmp_log(y) == Ordering::Less)]
201 #[::creusot_std::macros::ensures(y.cmp_log(x) == Ordering::Greater)]
202 fn antisym1(x: Self, y: Self) {
203 $($lemma)*
204 }
205
206 #[::creusot_std::macros::logic(open(self), law)]
207 #[::creusot_std::macros::requires(x.cmp_log(y) == Ordering::Greater)]
208 #[::creusot_std::macros::ensures(y.cmp_log(x) == Ordering::Less)]
209 fn antisym2(x: Self, y: Self) {
210 $($lemma)*
211 }
212
213 #[::creusot_std::macros::logic(open(self), law)]
214 #[::creusot_std::macros::ensures((x == y) == (x.cmp_log(y) == Ordering::Equal))]
215 fn eq_cmp(x: Self, y: Self) {
216 $($lemma)*
217 }
218 };
219}
220
221pub use ord_laws_impl;
222
223impl<T: OrdLogic> OrdLogic for &T {
224 #[logic(open)]
225 fn cmp_log(self, o: Self) -> Ordering {
226 T::cmp_log(*self, *o)
227 }
228
229 #[logic]
230 fn le_log(self, other: Self) -> bool {
231 T::le_log(*self, *other)
232 }
233
234 #[logic]
235 fn lt_log(self, other: Self) -> bool {
236 T::lt_log(*self, *other)
237 }
238
239 #[logic]
240 fn ge_log(self, other: Self) -> bool {
241 T::ge_log(*self, *other)
242 }
243
244 #[logic]
245 fn gt_log(self, other: Self) -> bool {
246 T::gt_log(*self, *other)
247 }
248
249 ord_laws_impl! {}
250}
251
252impl OrdLogic for Int {
253 #[logic(open)]
254 fn cmp_log(self, o: Self) -> Ordering {
255 if self < o {
256 Ordering::Less
257 } else if self == o {
258 Ordering::Equal
259 } else {
260 Ordering::Greater
261 }
262 }
263
264 #[logic]
265 #[builtin("int.Int.(<=)")]
266 fn le_log(self, _: Self) -> bool {
267 dead
268 }
269
270 #[logic]
271 #[builtin("int.Int.(<)")]
272 fn lt_log(self, _: Self) -> bool {
273 dead
274 }
275
276 #[logic]
277 #[builtin("int.Int.(>=)")]
278 fn ge_log(self, _: Self) -> bool {
279 dead
280 }
281
282 #[logic]
283 #[builtin("int.Int.(>)")]
284 fn gt_log(self, _: Self) -> bool {
285 dead
286 }
287
288 ord_laws_impl! {}
289}
290
291macro_rules! ord_logic_impl {
292 ($t:ty, $module:literal) => {
293 impl OrdLogic for $t {
294 #[logic(open)]
295 fn cmp_log(self, o: Self) -> Ordering {
296 if self < o {
297 Ordering::Less
298 } else if self == o {
299 Ordering::Equal
300 } else {
301 Ordering::Greater
302 }
303 }
304
305 #[logic]
306 #[builtin(concat!($module, ".le"))]
307 fn le_log(self, _: Self) -> bool {
308 true
309 }
310
311 #[logic]
312 #[builtin(concat!($module, ".lt"))]
313 fn lt_log(self, _: Self) -> bool {
314 true
315 }
316
317 #[logic]
318 #[builtin(concat!($module, ".ge"))]
319 fn ge_log(self, _: Self) -> bool {
320 true
321 }
322
323 #[logic]
324 #[builtin(concat!($module, ".gt"))]
325 fn gt_log(self, _: Self) -> bool {
326 true
327 }
328
329 ord_laws_impl! {}
330 }
331 };
332}
333
334ord_logic_impl!(u8, "creusot.int.UInt8$BW$");
335ord_logic_impl!(u16, "creusot.int.UInt16$BW$");
336ord_logic_impl!(u32, "creusot.int.UInt32$BW$");
337ord_logic_impl!(u64, "creusot.int.UInt64$BW$");
338ord_logic_impl!(u128, "creusot.int.UInt128$BW$");
339#[cfg(target_pointer_width = "64")]
340ord_logic_impl!(usize, "creusot.int.UInt64$BW$");
341#[cfg(target_pointer_width = "32")]
342ord_logic_impl!(usize, "creusot.int.UInt32$BW$");
343#[cfg(target_pointer_width = "16")]
344ord_logic_impl!(usize, "creusot.int.UInt16$BW$");
345
346ord_logic_impl!(i8, "creusot.int.Int8$BW$");
347ord_logic_impl!(i16, "creusot.int.Int16$BW$");
348ord_logic_impl!(i32, "creusot.int.Int32$BW$");
349ord_logic_impl!(i64, "creusot.int.Int64$BW$");
350ord_logic_impl!(i128, "creusot.int.Int128$BW$");
351#[cfg(target_pointer_width = "64")]
352ord_logic_impl!(isize, "creusot.int.Int64$BW$");
353#[cfg(target_pointer_width = "32")]
354ord_logic_impl!(isize, "creusot.int.Int32$BW$");
355#[cfg(target_pointer_width = "16")]
356ord_logic_impl!(isize, "creusot.int.Int16$BW$");
357
358ord_logic_impl!(char, "creusot.prelude.Char");
359ord_logic_impl!(bool, "creusot.prelude.Bool");
360
361impl<A: OrdLogic, B: OrdLogic> OrdLogic for (A, B) {
362 #[logic(open)]
363 fn cmp_log(self, o: Self) -> Ordering {
364 pearlite! { {
365 let r = self.0.cmp_log(o.0);
366 if r == Ordering::Equal {
367 self.1.cmp_log(o.1)
368 } else {
369 r
370 }
371 } }
372 }
373
374 #[logic(open)]
375 fn le_log(self, o: Self) -> bool {
376 pearlite! { (self.0 == o.0 && self.1 <= o.1) || self.0 < o.0 }
377 }
378
379 #[logic(open)]
380 fn lt_log(self, o: Self) -> bool {
381 pearlite! { (self.0 == o.0 && self.1 < o.1) || self.0 < o.0 }
382 }
383
384 #[logic(open)]
385 fn ge_log(self, o: Self) -> bool {
386 pearlite! { (self.0 == o.0 && self.1 >= o.1) || self.0 > o.0 }
387 }
388
389 #[logic(open)]
390 fn gt_log(self, o: Self) -> bool {
391 pearlite! { (self.0 == o.0 && self.1 > o.1) || self.0 > o.0 }
392 }
393
394 ord_laws_impl! {}
395}