Skip to main content

vstd/arithmetic/
div_mod.rs

1//! This file contains proofs related to integer division (`/`) and
2//! remainder aka mod (`%`). These are part of the math standard library.
3//!
4//! It's based on the following file from the Dafny math standard
5//! library:
6//! `Source/DafnyStandardLibraries/src/Std/Arithmetic/DivMod.dfy`.
7//! That file has the following copyright notice:
8//! /*******************************************************************************
9//! * Original: Copyright (c) Microsoft Corporation *
10//! SPDX-License-Identifier: MIT * * Modifications and Extensions:
11//! Copyright by the contributors to the Dafny Project *
12//! SPDX-License-Identifier: MIT
13//! *******************************************************************************/
14use super::super::calc_macro::*;
15#[allow(unused_imports)]
16use super::super::prelude::*;
17
18verus! {
19
20#[verifier::inline]
21#[cfg_attr(verus_keep_ghost, rustc_diagnostic_item = "verus::vstd::arithmetic::div_mod::rust_div")]
22pub open spec fn rust_div(a: int, b: int) -> int
23    recommends
24        b != 0,
25{
26    if a == 0 {
27        0
28    } else if a > 0 {
29        a / b
30    } else {
31        -((-a) / b)
32    }
33}
34
35#[verifier::inline]
36#[cfg_attr(verus_keep_ghost, rustc_diagnostic_item = "verus::vstd::arithmetic::div_mod::rust_rem")]
37pub open spec fn rust_rem(a: int, b: int) -> int
38    recommends
39        b != 0,
40{
41    if a == 0 {
42        0
43    } else if a > 0 {
44        a % b
45    } else {
46        -((-a) % b)
47    }
48}
49
50#[allow(unused_imports)]
51#[cfg(verus_keep_ghost)]
52use super::super::arithmetic::internals::div_internals::{
53    div_recursive,
54    lemma_div_induction_auto,
55    div_auto,
56    div_pos,
57    lemma_div_auto,
58};
59use super::super::arithmetic::internals::div_internals_nonlinear as DivINL;
60#[cfg(verus_keep_ghost)]
61use super::super::arithmetic::internals::mod_internals::{
62    lemma_div_add_denominator,
63    lemma_mod_auto,
64    mod_recursive,
65};
66use super::super::arithmetic::internals::mod_internals_nonlinear as ModINL;
67#[cfg(verus_keep_ghost)]
68use super::internals::mul_internals::{
69    group_mul_properties_internal,
70    lemma_mul_induction,
71    lemma_mul_induction_auto,
72};
73#[cfg(verus_keep_ghost)]
74use super::super::arithmetic::internals::general_internals::{is_le};
75#[cfg(verus_keep_ghost)]
76use super::super::math::{add as add1, sub as sub1, div as div1};
77use super::super::arithmetic::mul::*;
78
79/*****************************************************************************
80* Division
81*****************************************************************************/
82
83/// Proof that, for the case of `x / d`, division using `/` is
84/// equivalent to a recursive definition of division.
85pub broadcast proof fn lemma_div_is_div_recursive(x: int, d: int)
86    requires
87        0 < d,
88    ensures
89        div_recursive(x, d) == #[trigger] (x / d),
90{
91    reveal(div_recursive);
92    reveal(div_pos);
93    lemma_div_induction_auto(d, x, |u: int| div_recursive(u, d) == u / d);
94}
95
96/// Proof that the quotient of an integer divided by itself is 1,
97/// specifically that `d / d == 1`.
98pub proof fn lemma_div_by_self(d: int)
99    requires
100        d != 0,
101    ensures
102        d / d == 1,
103{
104    DivINL::lemma_div_by_self(d);
105}
106
107/// Proof that 0 divided by a nonzero integer is 0, specifically `0 / d == 0`.
108pub proof fn lemma_div_of0(d: int)
109    requires
110        d != 0,
111    ensures
112        0 as int / d == 0,
113{
114    DivINL::lemma_div_of0(d);
115}
116
117/// Proof establishing basic properties of division using `x`: 0
118/// divided by `x` is 0; `x` divided by 1 is itself; and `x` divided
119/// by itself is 1.
120pub proof fn lemma_div_basics(x: int)
121    ensures
122        x != 0 as int ==> 0 as int / x == 0,
123        x / 1 == x,
124        x != 0 ==> x / x == 1,
125{
126    if (x != 0) {
127        lemma_div_by_self(x);
128        lemma_div_of0(x);
129    }
130}
131
132/// Proof for basic property that 0 divided by `x` is 0.
133pub broadcast proof fn lemma_div_basics_1(x: int)
134    ensures
135        x != 0 as int ==> #[trigger] (0int / x) == 0,
136{
137    lemma_div_basics(x);
138}
139
140/// Proof for basic property that `x` divided by 1 is `x`.
141pub broadcast proof fn lemma_div_basics_2(x: int)
142    ensures
143        #[trigger] (x / 1) == x,
144{
145    lemma_div_basics(x);
146}
147
148/// Proof for basic property that `x` divided by `x` is 1.
149pub broadcast proof fn lemma_div_basics_3(x: int)
150    ensures
151        x != 0 ==> #[trigger] (x / x) == 1,
152{
153    lemma_div_basics(x);
154}
155
156/// Proof that dividing any non-negative integer by a positive integer is non-zero.
157pub broadcast proof fn lemma_div_basics_4(x: int, y: int)
158    ensures
159        x >= 0 && y > 0 ==> #[trigger] (x / y) >= 0,
160{
161}
162
163/// Proof that the quotient produced by dividing any non-negative integer `x`
164/// by a positive integer `y` is at most `x`.
165pub broadcast proof fn lemma_div_basics_5(x: int, y: int)
166    ensures
167        x >= 0 && y > 0 ==> #[trigger] (x / y) <= x,
168{
169    assert forall|x: int, y: int| x >= 0 && y > 0 implies 0 <= #[trigger] (x / y) <= x by {
170        lemma_div_pos_is_pos(x, y);
171        lemma_div_is_ordered_by_denominator(x, 1, y);
172    };
173}
174
175pub broadcast group group_div_basics {
176    lemma_div_basics_1,
177    lemma_div_basics_2,
178    lemma_div_basics_3,
179    lemma_div_basics_4,
180    lemma_div_basics_5,
181}
182
183/// Proof that if a dividend is a whole number, the divisor is a
184/// natural number, and their quotient is 0, then the dividend is
185/// smaller than the divisor.
186pub broadcast proof fn lemma_small_div_converse(x: int, d: int)
187    ensures
188        0 <= x && 0 < d && #[trigger] (x / d) == 0 ==> x < d,
189{
190    assert forall|x: int, d: int| 0 <= x && 0 < d && #[trigger] (x / d) == 0 implies x < d by {
191        lemma_div_induction_auto(d, x, |u: int| 0 <= u && 0 < d && u / d == 0 ==> u < d);
192    }
193}
194
195/// Proof that division of a positive integer by a positive integer
196/// less than or equal to it is nonzero. Specifically,
197/// given that `x >= d`, we can conclude that `x / d > 0`.
198pub proof fn lemma_div_non_zero(x: int, d: int)
199    requires
200        x >= d > 0,
201    ensures
202        #[trigger] (x / d) > 0,
203{
204    broadcast use lemma_div_pos_is_pos;
205
206    if x / d == 0 {
207        broadcast use lemma_small_div_converse;
208
209    }
210}
211
212/// Proof that given two fractions with the same numerator, the order
213/// of the fractions is determined by the denominators. However, if
214/// the numerator is 0, the fractions are equal regardless of the
215/// denominators' values. Specifically, given that `1 <= y <= z`, we
216/// know `x / y >= x / z`.
217pub broadcast proof fn lemma_div_is_ordered_by_denominator(x: int, y: int, z: int)
218    requires
219        0 <= x,
220        1 <= y <= z,
221    ensures
222        #[trigger] (x / y) >= #[trigger] (x / z),
223    decreases x,
224{
225    reveal(div_recursive);
226    reveal(div_pos);
227    broadcast use lemma_div_is_div_recursive;
228
229    assert(forall|u: int, d: int|
230        #![trigger div_recursive(u, d)]
231        #![trigger div1(u, d)]
232        d > 0 ==> div_recursive(u, d) == div1(u, d));
233    if (x < z) {
234        lemma_div_is_ordered(0, x, y);
235    } else {
236        lemma_div_is_ordered(x - z, x - y, y);
237        lemma_div_is_ordered_by_denominator(x - z, y, z);
238    }
239}
240
241/// Proof that a number gets strictly smaller when divided by a number
242/// greater than one. Specifically, `x / d < x`.
243pub broadcast proof fn lemma_div_is_strictly_smaller(x: int, d: int)
244    requires
245        0 < x,
246        1 < d,
247    ensures
248        #[trigger] (x / d) < x,
249    decreases x,
250{
251    lemma_div_induction_auto(d, x, |u: int| 0 < u ==> u / d < u);
252}
253
254/// Proof that, given `r == a % d + b % d - (a + b) % d`, `r` can also
255/// be expressed as `d * ((a + b) / d) - d * (a / d) - d * (b / d)`.
256pub broadcast proof fn lemma_dividing_sums(a: int, b: int, d: int, r: int)
257    requires
258        0 < d,
259        r == a % d + b % d - (a + b) % d,
260    ensures
261        #![trigger (d * ((a + b) / d) - r), (d * (a / d) + d * (b / d))]
262        d * ((a + b) / d) - r == d * (a / d) + d * (b / d),
263{
264    ModINL::lemma_fundamental_div_mod(a + b, d);
265    ModINL::lemma_fundamental_div_mod(a, d);
266    ModINL::lemma_fundamental_div_mod(b, d);
267}
268
269/// Proof that dividing a whole number by a natural number will result
270/// in a quotient that is greater than or equal to 0. Specifically,
271/// `x / d >= 0`.
272pub broadcast proof fn lemma_div_pos_is_pos(x: int, d: int)
273    requires
274        0 <= x,
275        0 < d,
276    ensures
277        0 <= #[trigger] (x / d),
278{
279    lemma_div_auto(d);
280    assert(div_auto(d));
281    let f = |u: int| 0 <= u ==> u / d >= 0;
282    assert forall|i: int| #[trigger] is_le(0, i) && f(i) implies f(i + d) by {
283        assert(i / d >= 0);
284    };
285    lemma_div_induction_auto(d, x, |u: int| 0 <= u ==> u / d >= 0);
286}
287
288/// Proof that dividing a number then adding 1 gives the same result
289/// as adding the divisor and then doing the division. Specifically,
290/// `1 + (x / d)` is equal to `(d + x) / d`.
291pub broadcast proof fn lemma_div_plus_one(x: int, d: int)
292    requires
293        0 < d,
294    ensures
295        #![trigger (1 + x / d), ((d + x) / d)]
296        1 + x / d == (d + x) / d,
297{
298    lemma_div_auto(d);
299}
300
301/// Proof that dividing a number then subtracting 1 gives the same result
302/// as subtracting the divisor and then doing the division. Specifically,
303/// `-1 + (x / d)` is equal to `(-d + x) / d`.
304pub broadcast proof fn lemma_div_minus_one(x: int, d: int)
305    requires
306        0 < d,
307    ensures
308        #![trigger (-1 + x / d), ((-d + x) / d)]
309        -1 + x / d == (-d + x) / d,
310{
311    lemma_div_auto(d);
312}
313
314/// Proof that dividing any non-negative integer less than `d` by `d`
315/// produces a quotient of 0.
316pub proof fn lemma_basic_div_specific_divisor(d: int)
317    requires
318        0 < d,
319    ensures
320        forall|x: int| 0 <= x < d ==> #[trigger] (x / d) == 0,
321{
322    lemma_div_auto(d);
323}
324
325/// Proof that dividing any non-negative integer by a larger integer
326/// produces a quotient of 0.
327pub broadcast proof fn lemma_basic_div(x: int, d: int)
328    requires
329        0 <= x < d,
330    ensures
331        #[trigger] (x / d) == 0,
332{
333    lemma_basic_div_specific_divisor(d);
334}
335
336/// Proof that numerical order is preserved when dividing two seperate
337/// integers by a common positive divisor. Specifically, given that
338/// `z > 0` and `x <= y`, we know `x / z <= y / z`.
339pub broadcast proof fn lemma_div_is_ordered(x: int, y: int, z: int)
340    requires
341        x <= y,
342        0 < z,
343    ensures
344        #[trigger] (x / z) <= #[trigger] (y / z),
345{
346    lemma_div_auto(z);
347    let f = |xy: int| xy <= 0 ==> (xy + y) / z <= y / z;
348    assert forall|i: int| #[trigger] is_le(i + 1, z) && f(i) implies f(i - z) by {
349        if (i - z <= 0) {
350            assert(f(i));
351            assert(i <= 0 ==> (i + y) / z <= y / z);
352            if (i > 0) {
353                assert(z > 0);
354                assert(i <= z);
355                assert(((i + y) - z) / z <= y / z);
356            } else {
357                assert((i + y) / z <= y / z);
358            }
359            assert((i - z + y) / z <= y / z);
360        }
361    };
362    lemma_div_induction_auto(z, x - y, |xy: int| xy <= 0 ==> (xy + y) / z <= y / z);
363}
364
365/// Proof that dividing an integer by 2 or more results in a quotient
366/// that is smaller than the original dividend. Specifically, `x / d < x`.
367pub broadcast proof fn lemma_div_decreases(x: int, d: int)
368    requires
369        0 < x,
370        1 < d,
371    ensures
372        #[trigger] (x / d) < x,
373{
374    lemma_div_induction_auto(d, x, |u: int| 0 < u ==> u / d < u);
375}
376
377/// Proof that dividing an integer by 1 or more results in a quotient
378/// that is less than or equal to the original dividend. Specifically,
379/// `x / d <= x`.
380pub broadcast proof fn lemma_div_nonincreasing(x: int, d: int)
381    requires
382        0 <= x,
383        0 < d,
384    ensures
385        #[trigger] (x / d) <= x,
386{
387    lemma_div_induction_auto(d, x, |u: int| 0 <= u ==> u / d <= u);
388}
389
390/// Proof that a natural number x divided by a larger natural number
391/// gives a remainder equal to x. Specifically, because `x < m`, we
392/// know `x % m == x`.
393pub proof fn lemma_small_mod(x: nat, m: nat)
394    requires
395        x < m,
396        0 < m,
397    ensures
398        x % m == x,
399{
400    ModINL::lemma_small_mod(x, m);
401}
402
403/// The remainder of a nonnegative integer `x` divided by the product of two positive integers
404/// `y` and `z` is equivalent to dividing `x` by `y`, dividing the quotient by `z`, multiplying
405/// the remainder by `y`, and then adding the product to the remainder of `x` divided by `y`.
406/// In mathematical terms, `(x % (y * z)) == y * ((x / y) % z) + x % y`.
407pub broadcast proof fn lemma_breakdown(x: int, y: int, z: int)
408    requires
409        0 <= x,
410        0 < y,
411        0 < z,
412    ensures
413        #![trigger y * z, x % (y * z), y * ((x / y) % z) + x % y]
414        0 < y * z,
415        (x % (y * z)) == y * ((x / y) % z) + x % y,
416{
417    broadcast use lemma_mul_strictly_positive;
418
419    lemma_div_pos_is_pos(x, y);
420    calc! {
421        (<)
422        (y * (x / y)) % (y * z) + (x % y) % (y * z); (<=) {
423            lemma_part_bound1(x, y, z);
424        }
425        y * (z - 1) + (x % y) % (y * z); (<) {
426            lemma_part_bound2(x, y, z);
427        }
428        y * (z - 1) + y; (==) {
429            broadcast use group_mul_basics;
430
431        }
432        y * (z - 1) + y * 1; (==) {
433            broadcast use group_mul_is_distributive;
434
435        }
436        y * (z - 1 + 1); (==) {}
437        y * z;
438    }
439    calc! {
440        (==)
441        x % (y * z); {
442            ModINL::lemma_fundamental_div_mod(x, y);
443        }
444        (y * (x / y) + x % y) % (y * z); {
445            broadcast use group_mod_properties;
446
447            assert(0 <= x % y);
448            lemma_mul_nonnegative(y, x / y);
449            assert((y * (x / y)) % (y * z) + (x % y) % (y * z) < y * z);
450            lemma_mod_adds(y * (x / y), x % y, y * z);
451        }
452        (y * (x / y)) % (y * z) + (x % y) % (y * z); {
453            broadcast use {group_mod_properties, lemma_mul_is_commutative};
454
455            lemma_mul_increases(z, y);
456            // comparison op can't be chained in calc!
457            // assert forall is also not avaialable in calc!
458            assert((x % y) < y && y <= (y * z));
459            lemma_small_mod((x % y) as nat, (y * z) as nat);
460            assert((x % y) % (y * z) == x % y);
461        }
462        (y * (x / y)) % (y * z) + x % y; {
463            lemma_truncate_middle(x / y, y, z);
464        }
465        y * ((x / y) % z) + x % y;
466    }
467}
468
469/// Proof that the difference between a nonnegative integer `x` and a
470/// positive integer `d` must be strictly less than the quotient of
471/// `x` divided by `d` and then multiplied by `d`.
472pub broadcast proof fn lemma_remainder_upper(x: int, d: int)
473    requires
474        0 <= x,
475        0 < d,
476    ensures
477        #![trigger (x - d), (x / d * d)]
478        x - d < x / d * d,
479{
480    broadcast use group_mul_properties_internal;
481
482    lemma_div_induction_auto(d, x, |u: int| 0 <= u ==> u - d < u / d * d);
483}
484
485/// Proof that the division of a nonnegative integer `x` by a positive
486/// integer `d` multiplied by `d` is less than or equal to the value
487/// of `x`.
488pub broadcast proof fn lemma_remainder_lower(x: int, d: int)
489    requires
490        0 <= x,
491        0 < d,
492    ensures
493        x >= #[trigger] (x / d * d),
494{
495    broadcast use group_mul_properties_internal;
496
497    lemma_div_induction_auto(d, x, |u: int| 0 <= u ==> u >= u / d * d);
498}
499
500/// Proof that the difference between a nonnegative integer `x` and
501/// the division of `x` by a positive integer `d` multiplied by `d` is
502/// lower bounded (inclusively) by 0 and upper bounded (exclusively)
503/// by `d`.
504pub broadcast proof fn lemma_remainder(x: int, d: int)
505    requires
506        0 <= x,
507        0 < d,
508    ensures
509        0 <= #[trigger] (x - (x / d * d)) < d,
510{
511    broadcast use group_mul_properties_internal;
512
513    lemma_div_induction_auto(d, x, |u: int| 0 <= u - u / d * d < d);
514}
515
516/// Proof of the fundamental theorem of division and modulo, namely
517/// that `x` can be expressed as `d` times the quotient `x / d` plus
518/// the remainder `x % d`.
519pub broadcast proof fn lemma_fundamental_div_mod(x: int, d: int)
520    requires
521        d != 0,
522    ensures
523        x == #[trigger] (d * (x / d) + (x % d)),
524{
525    assert(x == d * (x / d) + (x % d)) by {
526        ModINL::lemma_fundamental_div_mod(x, d);
527    }
528}
529
530/// Proof that dividing `x` by `c * d` is equivalent to first dividing
531/// `x` by `c` and then dividing the result by `d`.
532pub broadcast proof fn lemma_div_denominator(x: int, c: int, d: int)
533    requires
534        0 <= x,
535        0 < c,
536        0 < d,
537    ensures
538        c * d != 0,
539        #[trigger] ((x / c) / d) == x / (c * d),
540{
541    lemma_mul_strictly_positive(c, d);
542    let r = x % (c as int * d as int);
543    lemma_div_pos_is_pos(r, c as int);
544    if (r / c as int >= d) {
545        ModINL::lemma_fundamental_div_mod(r, c as int);
546        lemma_mul_inequality(d as int, r / c as int, c as int);
547        lemma_mul_is_commutative(d, c);
548    }
549    assert(r / (c as int) < d);
550    lemma_fundamental_div_mod_converse(r / c, d, 0, r / c);
551    assert((r / c as int) % d as int == r / c as int);
552    lemma_fundamental_div_mod(r, c);
553    assert(c * (r / c) + r % c == r);
554    assert(c * ((r / c as int) % d as int) + r % c as int == r);
555    let k = x / (c as int * d as int);
556    lemma_fundamental_div_mod(x, c * d);
557    assert(x == (c * d) * (x / (c * d)) + x % (c * d));
558    assert(r == x - (c * d) * (x / (c * d)));
559    assert(r == x - (c * d) * k);
560    calc! {
561        (==)
562        c * ((x / c) % d) + x % c; {
563            broadcast use lemma_mul_is_commutative;
564
565            lemma_mod_multiples_vanish(-k, x / c, d);
566        }
567        c * ((x / c + (-k) * d) % d) + x % c; {
568            lemma_hoist_over_denominator(x, (-k) * d, c as nat);
569        }
570        c * (((x + (((-k) * d) * c)) / c) % d) + x % c; {
571            lemma_mul_is_associative(-k, d, c);
572        }
573        c * (((x + ((-k) * (d * c))) / c) % d) + x % c; {
574            lemma_mul_unary_negation(k, d * c);
575        }
576        c * (((x + (-(k * (d * c)))) / c) % d) + x % c; {
577            lemma_mul_is_associative(k, d, c);
578        }
579        c * (((x + (-(k * d * c))) / c) % d) + x % c; {}
580        c * (((x - k * d * c) / c) % d) + x % c; {
581            broadcast use {lemma_mul_is_associative, lemma_mul_is_commutative};
582
583        }
584        c * ((r / c) % d) + x % c; {}
585        c * (r / c) + x % c; {
586            lemma_fundamental_div_mod(r, c);
587            assert(r == c * (r / c) + r % c);
588            lemma_mod_mod(x, c, d);
589            assert(r % c == x % c);
590        }
591        r; {
592            broadcast use {group_mod_properties, lemma_mod_is_mod_recursive};
593
594        }
595        r % (c * d); {}
596        (x - (c * d) * k) % (c * d); {
597            lemma_mul_unary_negation(c * d, k);
598        }
599        (x + (c * d) * (-k)) % (c * d); {
600            lemma_mod_multiples_vanish(-k, x, c * d);
601        }
602        x % (c * d);
603    }
604    assert(c * (x / c) + x % c - r == c * (x / c) - c * ((x / c) % d) ==> x - r == c * (x / c) - c
605        * ((x / c) % d)) by {
606        lemma_fundamental_div_mod(x, c);
607    };
608    assert(c * (x / c) + x % c - r == c * (x / c) - c * ((x / c) % d));
609    assert(x - r == c * (x / c) - c * ((x / c) % d));
610    assert((x / c) / d == x / (c * d)) by {
611        lemma_fundamental_div_mod(x / c, d);
612        assert(d * ((x / c) / d) == x / c - ((x / c) % d));
613        lemma_fundamental_div_mod(x, c * d);
614        assert(x == (c * d) * (x / (c * d)) + (x % (c * d)));
615        lemma_mul_is_distributive_sub(c, x / c, (x / c) % d);
616        assert(c * (d * ((x / c) / d)) == c * (x / c) - c * ((x / c) % d));
617        lemma_mul_is_associative(c, d, (x / c) / d);
618        assert((c * d) * ((x / c) / d) == c * (x / c) - c * ((x / c) % d));
619        assert((c * d) * ((x / c) / d) == x - r);
620        assert((c * d) * ((x / c) / d) == (c * d) * (x / (c * d)));
621        lemma_mul_equality_converse(c * d, (x / c) / d, x / (c * d));
622    }
623    assert(c * d != 0) by {
624        assert(0 < c * d);
625    }
626    assert(c * d != 0);  // work around https://github.com/Z3Prover/z3/issues/8057
627}
628
629/// Proof that multiplying an integer by a fraction is equivalent to
630/// multiplying the fraction's numerator by the integer. Specifically,
631/// `x * (y / z) == (x * y) / z`.
632pub broadcast proof fn lemma_mul_hoist_inequality(x: int, y: int, z: int)
633    requires
634        0 <= x,
635        0 < z,
636    ensures
637        #![trigger (x * (y / z)), ((x * y) / z)]
638        x * (y / z) <= (x * y) / z,
639{
640    calc! {
641        (==)
642        (x * y) / z; (==) {
643            lemma_fundamental_div_mod(y, z);
644        }
645        (x * (z * (y / z) + y % z)) / z; (==) {
646            broadcast use group_mul_is_distributive;
647
648        }
649        (x * (z * (y / z)) + x * (y % z)) / z;
650    }
651    assert((x * (z * (y / z)) + x * (y % z)) / z >= x * (y / z)) by {
652        broadcast use {group_mod_properties, lemma_mul_is_associative, lemma_mul_is_commutative};
653
654        lemma_mul_nonnegative(x, y % z);
655        lemma_div_is_ordered(x * (z * (y / z)), x * (z * (y / z)) + x * (y % z), z);
656        lemma_div_multiples_vanish(x * (y / z), z);
657    };
658}
659
660/// Proof that for a positive integer `d`, if `a - a % d` is less than
661/// or equal to `b` and `b` is less than `a + d - a % d`, then the
662/// quotient of `a` divided by `d` is equivalent to the quotient of
663/// `b` divided by `d`.
664///
665/// In other words, if `a` and `b` occur between the same two
666/// multiples of `d`, then their quotient with `d` is equivalent.
667pub broadcast proof fn lemma_indistinguishable_quotients(a: int, b: int, d: int)
668    requires
669        0 < d,
670        0 <= a - a % d <= b < a + d - a % d,
671    ensures
672        #![trigger (a / d), (b / d)]
673        a / d == b / d,
674{
675    lemma_div_induction_auto(
676        d,
677        a - b,
678        |ab: int|
679            {
680                let u = ab + b;
681                0 <= u - u % d <= b < u + d - u % d ==> u / d == b / d
682            },
683    );
684}
685
686/// Proof that common factors from the dividend and divisor of a
687/// modulus operation can be factored out. Specifically,
688/// `(b * x) % (b * c) == b * (x % c)`.
689pub proof fn lemma_truncate_middle(x: int, b: int, c: int)
690    requires
691        0 <= x,
692        0 < b,
693        0 < c,
694    ensures
695        #![trigger (b * (x % c))]
696        0 < b * c,
697        (b * x) % (b * c) == b * (x % c),
698{
699    broadcast use {lemma_mul_strictly_positive, lemma_mul_nonnegative};
700
701    calc! {
702        (==)
703        b * x; {
704            ModINL::lemma_fundamental_div_mod(b * x, b * c);
705        }
706        (b * c) * ((b * x) / (b * c)) + (b * x) % (b * c); {
707            lemma_div_denominator(b * x, b, c);
708        }
709        (b * c) * (((b * x) / b) / c) + (b * x) % (b * c); {
710            broadcast use lemma_mul_is_commutative;
711
712            lemma_div_by_multiple(x, b);
713        }
714        (b * c) * (x / c) + (b * x) % (b * c);
715    }
716    assert(b * x == (b * c) * (x / c) + b * (x % c)) by {
717        ModINL::lemma_fundamental_div_mod(x, c);
718        broadcast use {group_mul_is_distributive, lemma_mul_is_associative};
719
720    };
721}
722
723/// Proof that multiplying the numerator and denominator by an integer
724/// does not change the quotient. Specifically,
725/// `a / d == (x * a) / (x * d)`.
726pub broadcast proof fn lemma_div_multiples_vanish_quotient(x: int, a: int, d: int)
727    requires
728        0 < x,
729        0 <= a,
730        0 < d,
731    ensures
732        #![trigger a / d, x * a, x * d]
733        0 < x * d,
734        a / d == (x * a) / (x * d),
735{
736    lemma_mul_strictly_positive(x, d);
737    calc! {
738        (==)
739        (x * a) / (x * d); {
740            lemma_mul_nonnegative(x, a);
741            lemma_div_denominator(x * a, x, d);
742        }
743        ((x * a) / x) / d; {
744            lemma_div_multiples_vanish(a, x);
745        }
746        a / d;
747    }
748}
749
750/// Proof that, since `a % d == 0` and `0 <= r < d`, we can conclude
751/// `a == d * (a + r) / d`.
752#[verifier::spinoff_prover]
753pub broadcast proof fn lemma_round_down(a: int, r: int, d: int)
754    requires
755        0 < d,
756        a % d == 0,
757        0 <= r < d,
758    ensures
759        #![trigger (d * ((a + r) / d))]
760        a == d * ((a + r) / d),
761{
762    broadcast use group_mul_properties_internal;
763
764    lemma_div_induction_auto(d, a, |u: int| u % d == 0 ==> u == d * ((u + r) / d));
765}
766
767/// Proof that, since `0 <= b < d`, we have `(d * x + b) / d == x`.
768pub broadcast proof fn lemma_div_multiples_vanish_fancy(x: int, b: int, d: int)
769    requires
770        0 < d,
771        0 <= b < d,
772    ensures
773        #![trigger (d * x + b) / d]
774        (d * x + b) / d == x,
775{
776    let f = |u: int| (d * u + b) / d == u;
777    assert(f(0)) by {
778        lemma_div_auto(d);
779    }
780    assert forall|i: int| i >= 0 && #[trigger] f(i) implies #[trigger] f(add1(i, 1)) by {
781        assert(d * (i + 1) + b == d * i + b + d) by {
782            assert(d * (i + 1) == d * i + d) by {
783                lemma_mul_is_distributive_add(d, i, 1);
784                lemma_mul_basics(d);
785            }
786        }
787        super::internals::div_internals::lemma_div_basics(d);
788    }
789    assert forall|i: int| i <= 0 && #[trigger] f(i) implies #[trigger] f(sub1(i, 1)) by {
790        assert(d * (i - 1) + b == d * i + b - d) by {
791            assert(d * (i - 1) == d * i - d) by {
792                lemma_mul_is_distributive_sub(d, i, 1);
793                lemma_mul_basics(d);
794            }
795        }
796        super::internals::div_internals::lemma_div_basics(d);
797    }
798    broadcast use group_mul_properties_internal;
799
800    lemma_mul_induction(f);
801    assert(f(x));
802}
803
804/// Proof that multiplying an integer by a common numerator and
805/// denominator results in the original integer. Specifically,
806/// `(d * x) / d == x`.
807pub broadcast proof fn lemma_div_multiples_vanish(x: int, d: int)
808    requires
809        0 < d,
810    ensures
811        #![trigger (d * x) / d]
812        (d * x) / d == x,
813{
814    lemma_div_multiples_vanish_fancy(x, 0, d);
815}
816
817/// Proof that multiplying a whole number by a common numerator and
818/// denominator results in the original integer. Specifically,
819/// `(b * d) / d == b`.
820pub broadcast proof fn lemma_div_by_multiple(b: int, d: int)
821    requires
822        0 <= b,
823        0 < d,
824    ensures
825        #![trigger ((b * d) / d)]
826        (b * d) / d == b,
827{
828    lemma_div_multiples_vanish(b, d);
829    broadcast use group_mul_properties_internal;
830
831}
832
833/// Proof that a dividend that is a positive multiple of a divisor
834/// will always yield a greater quotient than a smaller dividend.
835/// Specifically, `x / z < y / z` because `y == m * z` and `x < y`.
836pub broadcast proof fn lemma_div_by_multiple_is_strongly_ordered(x: int, y: int, m: int, z: int)
837    requires
838        x < y,
839        y == m * z,
840        0 < z,
841    ensures
842        #![trigger x / z, m * z, y / z]
843        x / z < y / z,
844{
845    lemma_mod_multiples_basic(m, z);
846    lemma_div_induction_auto(
847        z,
848        y - x,
849        |yx: int|
850            {
851                let u = yx + x;
852                x < u && u % z == 0 ==> x / z < u / z
853            },
854    );
855}
856
857/// Proof that if an integer is less than or equal to the product of
858/// two other integers, then the quotient with one of them will be
859/// less than or equal to the other of them. Specifically, because
860/// `a <= b * c`, we know `a / b <= c`.
861pub broadcast proof fn lemma_multiply_divide_le(a: int, b: int, c: int)
862    requires
863        0 < b,
864        a <= b * c,
865    ensures
866        #![trigger a / b, b * c]
867        a / b <= c,
868{
869    lemma_mod_multiples_basic(c, b);
870    let f = |i: int| 0 <= i && (i + a) % b == 0 ==> a / b <= (i + a) / b;
871    lemma_div_induction_auto(b, b * c - a, f);
872    lemma_div_multiples_vanish(c, b);
873}
874
875/// Proof that if an integer is less than the product of two other
876/// integers, then the quotient with one of them will be less than the
877/// other. Specifically, because `a < b * c`, we know `a / b < c`.
878pub broadcast proof fn lemma_multiply_divide_lt(a: int, b: int, c: int)
879    requires
880        0 < b,
881        a < b * c,
882    ensures
883        #![trigger a / b, b * c]
884        a / b < c,
885{
886    assert(((b * c - a) + a) % b == 0 ==> a / b < ((b * c - a) + a) / b) by {
887        let f = |i: int| 0 < i && (i + a) % b == 0 ==> a / b < (i + a) / b;
888        lemma_div_induction_auto(b, b * c - a, f);
889    }
890    assert(b * c == c * b) by {
891        lemma_mul_is_commutative(b, c);
892    }
893    assert((b * c) % b == 0) by {
894        lemma_mod_multiples_basic(c, b);
895    }
896    assert((b * c) / b == c) by {
897        lemma_div_multiples_vanish(c, b);
898    }
899}
900
901/// Proof that adding an integer to a fraction is equivalent to adding
902/// that integer times the denominator to the numerator. Specifically,
903/// `x / d + j == (x + j * d) / d`.
904pub broadcast proof fn lemma_hoist_over_denominator(x: int, j: int, d: nat)
905    requires
906        0 < d,
907    ensures
908        #![trigger x / d as int + j]
909        x / d as int + j == (x + j * d) / d as int,
910{
911    let dd = d as int;
912    let q = x / dd;
913    let r = x % dd;
914    assert(x == dd * q + r) by {
915        lemma_fundamental_div_mod(x, dd);
916    }
917    assert(j * dd == dd * j) by {
918        lemma_mul_is_commutative(j, dd);
919    }
920    assert(x + j * dd == dd * (q + j) + r) by {
921        lemma_mul_is_distributive_add(dd, q, j);
922    }
923    assert((x + j * dd) / dd == q + j) by {
924        lemma_fundamental_div_mod_converse(x + j * d, dd, q + j, r);
925    }
926}
927
928/// Proof that, for nonnegative integer `a` and positive integers `b` and `c`,
929/// the remainder of `b * (a / b)` divided by `b * c` is less than or equal to `b * (c - 1)`.
930/// This accounts for the rounding down that occurs in integer division.
931pub broadcast proof fn lemma_part_bound1(a: int, b: int, c: int)
932    requires
933        0 <= a,
934        0 < b,
935        0 < c,
936    ensures
937        #![trigger (b * (a / b) % (b * c))]
938        0 < b * c,
939        (b * (a / b) % (b * c)) <= b * (c - 1),
940{
941    lemma_mul_strictly_positive(b, a / b);
942    lemma_mul_strictly_positive(b, c);
943    lemma_mul_strictly_positive(b, c - 1);
944    calc! {
945        (==)
946        b * (a / b) % (b * c); {
947            ModINL::lemma_fundamental_div_mod(b * (a / b), b * c);
948        }
949        b * (a / b) - (b * c) * ((b * (a / b)) / (b * c)); {
950            broadcast use lemma_mul_is_associative;
951
952        }
953        b * (a / b) - b * (c * ((b * (a / b)) / (b * c))); {
954            broadcast use group_mul_is_distributive;
955
956        }
957        b * ((a / b) - (c * ((b * (a / b)) / (b * c))));
958    }
959    assert(b * (a / b) % (b * c) <= b * (c - 1)) by {
960        broadcast use {lemma_mul_is_commutative, lemma_mul_inequality};
961
962    };
963}
964
965/*******************************************************************************
966* Modulus
967*******************************************************************************/
968
969/// Proof that computing the modulus using `%` is equivalent to
970/// computing it with a recursive definition of modulus. Specifically,
971/// `x % m` is equivalent in that way.
972pub broadcast proof fn lemma_mod_is_mod_recursive(x: int, m: int)
973    requires
974        m > 0,
975    ensures
976        mod_recursive(x, m) == #[trigger] (x % m),
977    decreases
978            (if x < 0 {
979                -x + m
980            } else {
981                x
982            }),
983{
984    reveal(mod_recursive);
985    if x < 0 {
986        calc! {
987            (==)
988            mod_recursive(x, m); {}
989            mod_recursive(x + m, m); {
990                lemma_mod_is_mod_recursive(x + m, m);
991            }
992            (x + m) % m; {
993                lemma_add_mod_noop(x, m, m);
994            }
995            ((x % m) + (m % m)) % m; {
996                broadcast use {lemma_mod_self_0, lemma_mod_twice};
997
998            }
999            (x % m) % m; {
1000                broadcast use {lemma_mod_self_0, lemma_mod_twice};
1001
1002            }
1003            x % m;
1004        }
1005    } else if x < m {
1006        lemma_small_mod(x as nat, m as nat);
1007    } else {
1008        calc! {
1009            (==)
1010            mod_recursive(x, m); {}
1011            mod_recursive(x - m, m); {
1012                lemma_mod_is_mod_recursive(x - m, m);
1013            }
1014            (x - m) % m; {
1015                lemma_sub_mod_noop(x, m, m);
1016            }
1017            ((x % m) - (m % m)) % m; {
1018                broadcast use {lemma_mod_self_0, lemma_mod_twice};
1019
1020            }
1021            (x % m) % m; {
1022                broadcast use {lemma_mod_self_0, lemma_mod_twice};
1023
1024            }
1025            x % m;
1026        }
1027    }
1028}
1029
1030/// Proof that any integer divided by itself produces a remainder of 0.
1031pub broadcast proof fn lemma_mod_self_0(m: int)
1032    requires
1033        m > 0,
1034    ensures
1035        #[trigger] (m % m) == 0,
1036{
1037    lemma_mod_auto(m);
1038}
1039
1040/// Proof that performing `(x % m) % m` gives the same result as simply perfoming `x % m`.
1041pub broadcast proof fn lemma_mod_twice(x: int, m: int)
1042    requires
1043        m > 0,
1044    ensures
1045        #[trigger] ((x % m) % m) == x % m,
1046{
1047    lemma_mod_auto(m);
1048}
1049
1050pub broadcast group group_mod_basics {
1051    lemma_mod_self_0,
1052    lemma_mod_twice,
1053}
1054
1055/// Proof that the remainder of any division will be less than the divisor's value.
1056pub broadcast proof fn lemma_mod_division_less_than_divisor(x: int, m: int)
1057    requires
1058        m > 0,
1059    ensures
1060        0 <= #[trigger] (x % m) < m,
1061{
1062    lemma_mod_auto(m);
1063}
1064
1065pub broadcast group group_mod_properties {
1066    group_mod_basics,
1067    lemma_mod_division_less_than_divisor,
1068}
1069
1070/// Proof that when natural number `x` is divided by natural number
1071/// `m`, the remainder will be less than or equal to `x`.
1072pub broadcast proof fn lemma_mod_decreases(x: nat, m: nat)
1073    requires
1074        0 < m,
1075    ensures
1076        #[trigger] (x % m) <= x,
1077{
1078    lemma_mod_auto(m as int);
1079}
1080
1081/// Proof that if `x % m` is zero and `x` is positive, then `x >= m`.
1082pub broadcast proof fn lemma_mod_is_zero(x: nat, m: nat)
1083    requires
1084        x > 0 && m > 0,
1085        #[trigger] (x % m) == 0,
1086    ensures
1087        x >= m,
1088{
1089    if (x < m) {
1090        lemma_small_mod(x, m);
1091    }
1092}
1093
1094/// Proof that multiplying by a number then dividing by that same
1095/// number produces a remainder of 0. Specifically, `(x * m) % m == 0`.
1096#[verifier::spinoff_prover]
1097pub broadcast proof fn lemma_mod_multiples_basic(x: int, m: int)
1098    requires
1099        m > 0,
1100    ensures
1101        #[trigger] ((x * m) % m) == 0,
1102{
1103    lemma_mod_auto(m);
1104    broadcast use group_mul_properties_internal;
1105
1106    let f = |u: int| (u * m) % m == 0;
1107    lemma_mul_induction(f);
1108    assert(f(x));
1109}
1110
1111/// Proof that adding the divisor to the dividend doesn't change the
1112/// remainder. Specifically, `(m + b) % m == b % m`.
1113pub broadcast proof fn lemma_mod_add_multiples_vanish(b: int, m: int)
1114    requires
1115        0 < m,
1116    ensures
1117        (m + b) % m == #[trigger] (b % m),
1118{
1119    lemma_mod_auto(m);
1120}
1121
1122/// Proof that subtracting the divisor from the dividend doesn't
1123/// change the remainder. Specifically, `(-m + b) % m == b % m`.
1124pub broadcast proof fn lemma_mod_sub_multiples_vanish(b: int, m: int)
1125    requires
1126        0 < m,
1127    ensures
1128        (-m + b) % m == #[trigger] (b % m),
1129{
1130    lemma_mod_auto(m);
1131}
1132
1133/// Proof that adding any multiple of the divisor to the dividend will produce the
1134/// same remainder. In other words, `(m * a + b) % m == b % m`.
1135#[verifier::spinoff_prover]
1136pub broadcast proof fn lemma_mod_multiples_vanish(a: int, b: int, m: int)
1137    requires
1138        0 < m,
1139    ensures
1140        #[trigger] ((m * a + b) % m) == b % m,
1141    decreases
1142            (if a > 0 {
1143                a
1144            } else {
1145                -a
1146            }),
1147{
1148    lemma_mod_auto(m);
1149    broadcast use group_mul_properties_internal;
1150
1151    let f = |u: int| (m * u + b) % m == b % m;
1152    lemma_mul_induction(f);
1153    assert(f(a));
1154}
1155
1156/// Proof that modulo distributes over subtraction if the subtracted value is
1157/// less than or equal to the modulo of the number it's being subtracted from.
1158/// Specifically, because `0 <= s <= x % d`, we can conclude that
1159/// `x % d - s % d == (x - s) % d`.
1160pub broadcast proof fn lemma_mod_subtraction(x: nat, s: nat, d: nat)
1161    requires
1162        0 < d,
1163        0 <= s <= x % d,
1164    ensures
1165        #![trigger ((x - s) % d as int)]
1166        x % d - s % d == (x - s) % d as int,
1167{
1168    lemma_mod_auto(d as int);
1169}
1170
1171/// Proof that modulo distributes over addition, provided you do an
1172/// extra modulo after adding the remainders. Specifically,
1173/// `((x % m) + (y % m)) % m == (x + y) % m`.
1174pub broadcast proof fn lemma_add_mod_noop(x: int, y: int, m: int)
1175    requires
1176        0 < m,
1177    ensures
1178        #![trigger (x + y) % m]
1179        ((x % m) + (y % m)) % m == (x + y) % m,
1180{
1181    lemma_mod_auto(m);
1182}
1183
1184/// Proof that describes an expanded and succinct version of modulus
1185/// operator in relation to addition. Specifically,
1186/// `(x + (y % m)) % m == (x + y) % m`.
1187pub broadcast proof fn lemma_add_mod_noop_right(x: int, y: int, m: int)
1188    requires
1189        0 < m,
1190    ensures
1191        #![trigger (x + y) % m]
1192        (x + (y % m)) % m == (x + y) % m,
1193{
1194    lemma_mod_auto(m);
1195}
1196
1197/// Proof that modulo distributes over subtraction provided you do an
1198/// extra modulo operation after subtracting the remainders.
1199/// Specifically, `((x % m) - (y % m)) % m == (x - y) % m`.
1200pub broadcast proof fn lemma_sub_mod_noop(x: int, y: int, m: int)
1201    requires
1202        0 < m,
1203    ensures
1204        #![trigger (x - y) % m]
1205        ((x % m) - (y % m)) % m == (x - y) % m,
1206{
1207    lemma_mod_auto(m);
1208}
1209
1210/// Proof that describes an expanded and succinct version of modulus
1211/// operator in relation to subtraction. Specifically,
1212/// `(x - (y % m)) % m == (x - y) % m`.
1213pub broadcast proof fn lemma_sub_mod_noop_right(x: int, y: int, m: int)
1214    requires
1215        0 < m,
1216    ensures
1217        #![trigger ((x - y) % m)]
1218        (x - (y % m)) % m == (x - y) % m,
1219{
1220    lemma_mod_auto(m);
1221}
1222
1223/// Proof of two properties of the sum of two remainders with the same dividend:
1224/// 1) `a % d + b % d == (a + b) % d + d * ((a % d + b % d) / d)`.
1225/// 2) `(a % d + b % d) < d ==> a % d + b % d == (a + b) % d`.
1226pub broadcast proof fn lemma_mod_adds(a: int, b: int, d: int)
1227    requires
1228        0 < d,
1229    ensures
1230        #![trigger ((a + b) % d)]
1231        a % d + b % d == (a + b) % d + d * ((a % d + b % d) / d),
1232        (a % d + b % d) < d ==> a % d + b % d == (a + b) % d,
1233{
1234    broadcast use group_mul_properties_internal;
1235
1236    lemma_div_auto(d);
1237}
1238
1239/// Proof that the remainder when dividing integer `x` by positive
1240/// integer `d` is equivalent to the remainder of `x * (1 - d)` by
1241/// `d`.
1242#[verifier::spinoff_prover]
1243pub proof fn lemma_mod_neg_neg(x: int, d: int)
1244    requires
1245        0 < d,
1246    ensures
1247        x % d == (x * (1 - d)) % d,
1248{
1249    broadcast use group_mul_properties_internal;
1250
1251    assert((x - x * d) % d == x % d) by {
1252        let f = |i: int| (x - i * d) % d == x % d;
1253        assert(f(0) && (forall|i: int| i >= 0 && #[trigger] f(i) ==> #[trigger] f(add1(i, 1))) && (
1254        forall|i: int| i <= 0 && #[trigger] f(i) ==> #[trigger] f(sub1(i, 1)))) by {
1255            lemma_mod_auto(d);
1256        };
1257        lemma_mul_induction(f);
1258        assert(f(x));
1259    }
1260
1261}
1262
1263/// This proof isn't exported from this module. It's just used in
1264/// the proof of [`lemma_fundamental_div_mod_converse`].
1265proof fn lemma_fundamental_div_mod_converse_helper_1(u: int, d: int, r: int)
1266    requires
1267        d != 0,
1268        0 <= r < d,
1269    ensures
1270        u == (u * d + r) / d,
1271    decreases
1272            if u >= 0 {
1273                u
1274            } else {
1275                -u
1276            },
1277{
1278    if u < 0 {
1279        lemma_fundamental_div_mod_converse_helper_1(u + 1, d, r);
1280        lemma_div_add_denominator(d, u * d + r);
1281        lemma_mul_is_distributive_add_other_way(d, u + 1, -1);
1282        assert(u == (u * d + r) / d);
1283    } else if u == 0 {
1284        DivINL::lemma_small_div();
1285        assert(u == 0 ==> u * d == 0) by (nonlinear_arith);
1286        assert(u == (u * d + r) / d);
1287    } else {
1288        lemma_fundamental_div_mod_converse_helper_1(u - 1, d, r);
1289        lemma_div_add_denominator(d, (u - 1) * d + r);
1290        lemma_mul_is_distributive_add_other_way(d, u - 1, 1);
1291        assert(u * d + r == (u - 1) * d + r + d);
1292        assert(u == (u * d + r) / d);
1293    }
1294}
1295
1296/// This proof isn't exported from this module. It's just used in
1297/// the proof of [`lemma_fundamental_div_mod_converse`].
1298proof fn lemma_fundamental_div_mod_converse_helper_2(u: int, d: int, r: int)
1299    requires
1300        d != 0,
1301        0 <= r < d,
1302    ensures
1303        r == (u * d + r) % d,
1304    decreases
1305            if u >= 0 {
1306                u
1307            } else {
1308                -u
1309            },
1310{
1311    if u < 0 {
1312        lemma_fundamental_div_mod_converse_helper_2(u + 1, d, r);
1313        lemma_mod_add_multiples_vanish(u * d + r, d);
1314        lemma_mul_is_distributive_add_other_way(d, u + 1, -1);
1315        assert(u * d == (u + 1) * d + (-1) * d);
1316        assert(u * d + r == (u + 1) * d + r - d);
1317        assert(r == (u * d + r) % d);
1318    } else if u == 0 {
1319        assert(u == 0 ==> u * d == 0) by (nonlinear_arith);
1320        if d > 0 {
1321            lemma_small_mod(r as nat, d as nat);
1322        } else {
1323            lemma_small_mod(r as nat, (-d) as nat);
1324        }
1325        assert(r == (u * d + r) % d);
1326    } else {
1327        lemma_fundamental_div_mod_converse_helper_2(u - 1, d, r);
1328        lemma_mod_add_multiples_vanish((u - 1) * d + r, d);
1329        lemma_mul_is_distributive_add_other_way(d, u - 1, 1);
1330        assert(u * d + r == (u - 1) * d + r + d);
1331        assert(r == (u * d + r) % d);
1332    }
1333}
1334
1335/// Proof of the converse of the fundamental property of division and modulo.
1336/// Specifically, if we know `0 <= r < d` and `x == q * d + r`, then we
1337/// know that `r` is the remainder `x % d`.
1338pub broadcast proof fn lemma_fundamental_div_mod_converse_mod(x: int, d: int, q: int, r: int)
1339    requires
1340        d != 0,
1341        0 <= r < d,
1342        x == #[trigger] (q * d + r),
1343    ensures
1344        r == #[trigger] (x % d),
1345{
1346    lemma_fundamental_div_mod_converse_helper_1(q, d, r);
1347    assert(q == (q * d + r) / d);
1348    lemma_fundamental_div_mod_converse_helper_2(q, d, r);
1349}
1350
1351/// Proof of the converse of the fundamental property of division and modulo.
1352/// Specifically, if we know `0 <= r < d` and `x == q * d + r`, then we
1353/// know that `q` is the quotient `x / d`.
1354pub broadcast proof fn lemma_fundamental_div_mod_converse_div(x: int, d: int, q: int, r: int)
1355    requires
1356        d != 0,
1357        0 <= r < d,
1358        x == #[trigger] (q * d + r),
1359    ensures
1360        q == #[trigger] (x / d),
1361{
1362    lemma_fundamental_div_mod_converse_helper_1(q, d, r);
1363    assert(q == (q * d + r) / d);
1364    lemma_fundamental_div_mod_converse_helper_2(q, d, r);
1365}
1366
1367/// Proof of the converse of the fundamental property of division and modulo.
1368/// Specifically, if we know `0 <= r < d` and `x == q * d + r`, then we
1369/// know that `q` is the quotient `x / d` and `r` is the remainder `x % d`.
1370pub proof fn lemma_fundamental_div_mod_converse(x: int, d: int, q: int, r: int)
1371    requires
1372        d != 0,
1373        0 <= r < d,
1374        x == q * d + r,
1375    ensures
1376        r == x % d,
1377        q == x / d,
1378{
1379    lemma_fundamental_div_mod_converse_mod(x, d, q, r);
1380    lemma_fundamental_div_mod_converse_div(x, d, q, r);
1381}
1382
1383pub broadcast group group_fundamental_div_mod_converse {
1384    lemma_fundamental_div_mod_converse_mod,
1385    lemma_fundamental_div_mod_converse_div,
1386}
1387
1388/// Proof that the remainder, when natural number `x` is divided by
1389/// positive integer `m`, is less than `m`.
1390pub broadcast proof fn lemma_mod_pos_bound(x: int, m: int)
1391    requires
1392        0 <= x,
1393        0 < m,
1394    ensures
1395        0 <= #[trigger] (x % m) < m,
1396{
1397    lemma_mod_auto(m);
1398}
1399
1400/// Proof that when integer `x` is divided by positive integer `m`,
1401/// the remainder is nonegative and less than `m`.
1402pub broadcast proof fn lemma_mod_bound(x: int, m: int)
1403    requires
1404        0 < m,
1405    ensures
1406        0 <= #[trigger] (x % m) < m,
1407{
1408    ModINL::lemma_mod_range(x, m);
1409}
1410
1411/// Proof that the remainder when `x * y` is divided by `m` is
1412/// equivalent to the remainder when `(x % m) * y` is divided by `m`.
1413pub broadcast proof fn lemma_mul_mod_noop_left(x: int, y: int, m: int)
1414    requires
1415        0 < m,
1416    ensures
1417        (x % m) * y % m == #[trigger] (x * y % m),
1418{
1419    lemma_mod_auto(m);
1420    lemma_mul_induction_auto(y, |u: int| (x % m) * u % m == x * u % m);
1421}
1422
1423/// Proof that the remainder when `x * y` is divided by `m` is
1424/// equivalent to the remainder when `x * (y % m)` is divided by `m`.
1425pub broadcast proof fn lemma_mul_mod_noop_right(x: int, y: int, m: int)
1426    requires
1427        0 < m,
1428    ensures
1429        x * (y % m) % m == #[trigger] ((x * y) % m),
1430{
1431    lemma_mod_auto(m);
1432    lemma_mul_induction_auto(x, |u: int| u * (y % m) % m == (u * y) % m);
1433}
1434
1435/// Proof of various properties about modulo equivalence with respect
1436/// to multiplication, specifically various expressions that `(x * y)
1437/// % m` is equivalent to.
1438pub broadcast proof fn lemma_mul_mod_noop_general(x: int, y: int, m: int)
1439    requires
1440        0 < m,
1441    ensures
1442        ((x % m) * y) % m == (x * y) % m,
1443        (x * (y % m)) % m == (x * y) % m,
1444        ((x % m) * (y % m)) % m == #[trigger] ((x * y) % m),
1445{
1446    lemma_mul_mod_noop_left(x, y, m);
1447    lemma_mul_mod_noop_right(x, y, m);
1448    lemma_mul_mod_noop_right(x % m, y, m);
1449}
1450
1451/// Proof that modulo distributes over multiplication, provided you do
1452/// an extra modulo operation after multiplying the remainders. Specifically,
1453/// `(x % m) * (y % m) % m == (x * y) % m`.
1454pub broadcast proof fn lemma_mul_mod_noop(x: int, y: int, m: int)
1455    requires
1456        0 < m,
1457    ensures
1458        (x % m) * (y % m) % m == #[trigger] ((x * y) % m),
1459{
1460    lemma_mul_mod_noop_general(x, y, m);
1461}
1462
1463/// Proof that `x` and `y` are congruent modulo `m` if and only if `x
1464/// - y` is congruent to 0 modulo `m`. In other words, `x % m == y % m
1465/// <==> (x - y) % m == 0`.
1466///
1467/// Note: The Dafny standard library uses the triggers `x % m, y % m`
1468/// for the broadcasted forall quantifier. But this can lead to a trigger loop,
1469/// so we don't do that here.
1470pub broadcast proof fn lemma_mod_equivalence(x: int, y: int, m: int)
1471    requires
1472        0 < m,
1473    ensures
1474        #![trigger (x - y) % m]
1475        x % m == y % m <==> (x - y) % m == 0,
1476{
1477    lemma_mod_auto(m);
1478}
1479
1480/// This function says that `x` is congruent to `y` modulo `m` if and
1481/// only if their difference `x - y` is congruent to 0 modulo `m`.
1482pub open spec fn is_mod_equivalent(x: int, y: int, m: int) -> bool
1483    recommends
1484        m > 0,
1485{
1486    x % m == y % m <==> (x - y) % m == 0
1487}
1488
1489/// Proof that if `is_mod_equivalent` holds for `x`, `y`, and `m`,
1490/// then it holds for `x * z`, `y * z`, and `m`.
1491pub broadcast proof fn lemma_mod_mul_equivalent(x: int, y: int, z: int, m: int)
1492    requires
1493        m > 0,
1494        is_mod_equivalent(x, y, m),
1495    ensures
1496        #[trigger] is_mod_equivalent(x * z, y * z, m),
1497{
1498    lemma_mul_mod_noop_left(x, z, m);
1499    lemma_mul_mod_noop_left(y, z, m);
1500    lemma_mod_equivalence(x, y, m);
1501    lemma_mod_equivalence(x * z, y * z, m);
1502}
1503
1504/// Proof that multiplying the divisor by a positive number can't
1505/// decrease the remainder. Specifically, because `k > 0`, we have
1506/// `x % d <= x % (d * k)`.
1507pub broadcast proof fn lemma_mod_ordering(x: int, k: int, d: int)
1508    requires
1509        1 < d,
1510        0 < k,
1511    ensures
1512        0 < d * k,
1513        x % d <= #[trigger] (x % (d * k)),
1514{
1515    lemma_mul_strictly_increases(d, k);
1516    calc! {
1517        (==)
1518        x % d + d * (x / d); {
1519            lemma_fundamental_div_mod(x, d);
1520        }
1521        x; {
1522            lemma_fundamental_div_mod(x, d * k);
1523        }
1524        x % (d * k) + (d * k) * (x / (d * k)); {
1525            broadcast use lemma_mul_is_associative;
1526
1527        }
1528        x % (d * k) + d * (k * (x / (d * k)));
1529    }
1530    calc! {
1531        (==)
1532        x % d; {
1533            broadcast use group_mod_properties;
1534
1535        }
1536        (x % d) % d; {
1537            lemma_mod_multiples_vanish(x / d - k * (x / (d * k)), x % d, d);
1538        }
1539        (x % d + d * (x / d - k * (x / (d * k)))) % d; {
1540            broadcast use lemma_mul_is_distributive_sub;
1541
1542        }
1543        (x % d + d * (x / d) - d * (k * (x / (d * k)))) % d; {}
1544        (x % (d * k)) % d;
1545    }
1546    assert((x % (d * k)) % d <= x % (d * k)) by {
1547        broadcast use group_mod_properties;
1548
1549        lemma_mod_decreases((x % (d * k)) as nat, d as nat);
1550    };
1551}
1552
1553/// Proof that the remainder when `x` is divided by `a * b`, taken
1554/// modulo `a`, is equivalent to `x` modulo `a`. That is,
1555/// `(x % (a * b)) % a == x % a`.
1556pub broadcast proof fn lemma_mod_mod(x: int, a: int, b: int)
1557    requires
1558        0 < a,
1559        0 < b,
1560    ensures
1561        #![trigger (x % (a * b)) % a, x % a]
1562        0 < a * b,
1563        (x % (a * b)) % a == x % a,
1564{
1565    broadcast use lemma_mul_strictly_positive;
1566
1567    calc! {
1568        (==)
1569        x; {
1570            lemma_fundamental_div_mod(x, a * b);
1571        }
1572        (a * b) * (x / (a * b)) + x % (a * b); {
1573            broadcast use lemma_mul_is_associative;
1574
1575        }
1576        a * (b * (x / (a * b))) + x % (a * b); {
1577            lemma_fundamental_div_mod(x % (a * b), a);
1578        }
1579        a * (b * (x / (a * b))) + a * (x % (a * b) / a) + (x % (a * b)) % a; {
1580            broadcast use group_mul_is_distributive;
1581
1582        }
1583        a * (b * (x / (a * b)) + x % (a * b) / a) + (x % (a * b)) % a;
1584    }
1585    broadcast use {group_mod_properties, lemma_mul_is_commutative};
1586
1587    lemma_fundamental_div_mod_converse(
1588        x,
1589        a,
1590        b * (x / (a * b)) + x % (a * b) / a,
1591        (x % (a * b)) % a,
1592    );
1593}
1594
1595/// Proof that `(x % y) % (y * z) < y`.
1596pub broadcast proof fn lemma_part_bound2(x: int, y: int, z: int)
1597    requires
1598        0 <= x,
1599        0 < y,
1600        0 < z,
1601    ensures
1602        y * z > 0,
1603        #[trigger] (x % y) % #[trigger] (y * z) < y,
1604{
1605    broadcast use {
1606        lemma_mul_strictly_positive,
1607        group_mod_properties,
1608        lemma_mul_is_commutative,
1609        lemma_mul_increases,
1610    };
1611
1612    assert(x % y < y);
1613    assert(y <= y * z);
1614    assert(0 <= x % y < y * z);
1615    lemma_small_mod((x % y) as nat, (y * z) as nat);
1616    assert((x % y) % (y * z) == x % y);
1617}
1618
1619/// Proof of the validity of an expanded form of the modulus operation.
1620/// Specifically, `x % (y * z) == y * ((x / y) % z) + x % y`.
1621pub broadcast proof fn lemma_mod_breakdown(x: int, y: int, z: int)
1622    requires
1623        0 <= x,
1624        0 < y,
1625        0 < z,
1626    ensures
1627        #![trigger x % (y * z)]
1628        y * z > 0,
1629        x % (y * z) == y * ((x / y) % z) + x % y,
1630{
1631    broadcast use lemma_mul_strictly_positive;
1632
1633    lemma_div_pos_is_pos(x, y);
1634    assert(0 <= x / y);
1635    assert((y * (x / y)) % (y * z) + (x % y) % (y * z) < y * z) by {
1636        lemma_part_bound1(x, y, z);
1637        lemma_part_bound2(x, y, z);
1638        broadcast use {group_mul_basics, group_mul_is_distributive};
1639
1640    };
1641    calc! {
1642        (==)
1643        x % (y * z); {
1644            lemma_fundamental_div_mod(x, y);
1645        }
1646        (y * (x / y) + x % y) % (y * z); {
1647            broadcast use group_mod_properties;
1648
1649            assert(0 <= x % y);
1650            lemma_mul_nonnegative(y, x / y);
1651            assert((y * (x / y)) % (y * z) + (x % y) % (y * z) < y * z);
1652            lemma_mod_adds(y * (x / y), x % y, y * z);
1653        }
1654        (y * (x / y)) % (y * z) + (x % y) % (y * z); {
1655            broadcast use {group_mod_properties, lemma_mul_is_commutative};
1656
1657            lemma_mul_increases(z, y);
1658            assert(x % y < y && y <= y * z);
1659            lemma_small_mod((x % y) as nat, (y * z) as nat);
1660            assert((x % y) % (y * z) == x % y);
1661        }
1662        (y * (x / y)) % (y * z) + x % y; {
1663            lemma_truncate_middle(x / y, y, z);
1664        }
1665        y * ((x / y) % z) + x % y;
1666    }
1667}
1668
1669} // verus!