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