1#[allow(unused_imports)]
15use super::super::prelude::*;
16
17verus! {
18
19use super::super::arithmetic::internals::mul_internals_nonlinear as MulINL;
20use super::super::arithmetic::internals::mul_internals::*;
21
22pub broadcast proof fn lemma_mul_is_mul_recursive(x: int, y: int)
26 ensures
27 #[trigger] (x * y) == mul_recursive(x, y),
28{
29 if (x >= 0) {
30 lemma_mul_is_mul_pos(x, y);
31 assert(x * y == mul_pos(x, y));
32 assert((x * y) == mul_recursive(x, y));
33 } else {
34 lemma_mul_is_mul_pos(-x, y);
35 assert(x * y == -1 * (-x * y)) by { lemma_mul_is_associative(-1, -x, y) }; assert((x * y) == mul_recursive(x, y));
37 }
38}
39
40pub proof fn lemma_mul_is_mul_pos(x: int, y: int)
44 requires
45 x >= 0,
46 ensures
47 x * y == mul_pos(x, y),
48{
49 reveal(mul_pos);
50 lemma_mul_induction_auto(x, |u: int| u >= 0 ==> u * y == mul_pos(u, y));
51}
52
53pub proof fn lemma_mul_basics(x: int)
54 ensures
55 0 * x == 0,
56 x * 0 == 0,
57 x * 1 == x,
58 1 * x == x,
59{
60}
61
62pub broadcast proof fn lemma_mul_basics_1(x: int)
65 ensures
66 #[trigger] (0 * x) == 0,
67{
68}
69
70pub broadcast proof fn lemma_mul_basics_2(x: int)
73 ensures
74 #[trigger] (x * 0) == 0,
75{
76}
77
78pub broadcast proof fn lemma_mul_basics_3(x: int)
81 ensures
82 #[trigger] (x * 1) == x,
83{
84}
85
86pub broadcast proof fn lemma_mul_basics_4(x: int)
89 ensures
90 #[trigger] (1 * x) == x,
91{
92}
93
94pub broadcast group group_mul_basics {
95 lemma_mul_basics_1,
96 lemma_mul_basics_2,
97 lemma_mul_basics_3,
98 lemma_mul_basics_4,
99}
100
101pub broadcast proof fn lemma_mul_nonzero(x: int, y: int)
103 ensures
104 #[trigger] (x * y) != 0 <==> x != 0 && y != 0,
105{
106 MulINL::lemma_mul_nonzero(x, y);
107}
108
109pub broadcast proof fn lemma_mul_by_zero_is_zero(x: int)
111 ensures
112 #![trigger x * 0]
113 #![trigger 0 * x]
114 x * 0 == 0 && 0 * x == 0,
115{
116 assert forall|x: int| #![trigger x * 0] #![trigger 0 * x] x * 0 == 0 && 0 * x == 0 by {
117 lemma_mul_basics(x);
118 }
119}
120
121pub broadcast proof fn lemma_mul_is_associative(x: int, y: int, z: int)
124 ensures
125 #![trigger x * (y * z)]
126 #![trigger (x * y) * z]
127 x * (y * z) == (x * y) * z,
128{
129 MulINL::lemma_mul_is_associative(x, y, z);
130}
131
132pub broadcast proof fn lemma_mul_is_commutative(x: int, y: int)
135 ensures
136 #[trigger] (x * y) == y * x,
137{
138}
139
140pub broadcast proof fn lemma_mul_ordering(x: int, y: int)
144 requires
145 x != 0,
146 y != 0,
147 0 <= x * y,
148 ensures
149 #[trigger] (x * y) >= x && x * y >= y,
150{
151 MulINL::lemma_mul_ordering(x, y);
152}
153
154pub broadcast proof fn lemma_mul_inequality(x: int, y: int, z: int)
165 requires
166 x <= y,
167 z >= 0,
168 ensures
169 #[trigger] (x * z) <= #[trigger] (y * z),
170{
171 lemma_mul_induction_auto(z, |u: int| u >= 0 ==> x * u <= y * u);
172}
173
174pub broadcast proof fn lemma_mul_strict_inequality(x: int, y: int, z: int)
176 requires
177 x < y,
178 z > 0,
179 ensures
180 #[trigger] (x * z) < #[trigger] (y * z),
181{
182 MulINL::lemma_mul_strict_inequality(x, y, z);
183}
184
185pub broadcast proof fn lemma_mul_upper_bound(x: int, xbound: int, y: int, ybound: int)
189 requires
190 x <= xbound,
191 y <= ybound,
192 0 <= x,
193 0 <= y,
194 ensures
195 #[trigger] (x * y) <= #[trigger] (xbound * ybound),
196{
197 lemma_mul_inequality(x, xbound, y);
198 lemma_mul_inequality(y, ybound, xbound);
199}
200
201pub broadcast proof fn lemma_mul_strict_upper_bound(x: int, xbound: int, y: int, ybound: int)
206 requires
207 x < xbound,
208 y < ybound,
209 0 < x,
210 0 < y,
211 ensures
212 #[trigger] (x * y) <= #[trigger] ((xbound - 1) * (ybound - 1)),
213{
214 lemma_mul_inequality(x, xbound - 1, y);
215 lemma_mul_inequality(y, ybound - 1, xbound - 1);
216}
217
218pub broadcast proof fn lemma_mul_left_inequality(x: int, y: int, z: int)
222 requires
223 0 < x,
224 ensures
225 y <= z ==> #[trigger] (x * y) <= #[trigger] (x * z),
226 y < z ==> x * y < x * z,
227{
228 lemma_mul_induction_auto(x, |u: int| u > 0 ==> y <= z ==> u * y <= u * z);
229 lemma_mul_induction_auto(x, |u: int| u > 0 ==> y < z ==> u * y < u * z);
230}
231
232pub broadcast proof fn lemma_mul_equality_converse(m: int, x: int, y: int)
235 requires
236 m != 0,
237 #[trigger] (m * x) == #[trigger] (m * y),
238 ensures
239 x == y,
240{
241 lemma_mul_induction_auto(m, |u| x > y && 0 < u ==> x * u > y * u);
242 lemma_mul_induction_auto(m, |u: int| x < y && 0 < u ==> x * u < y * u);
243 lemma_mul_induction_auto(m, |u: int| x > y && 0 > u ==> x * u < y * u);
244 lemma_mul_induction_auto(m, |u: int| x < y && 0 > u ==> x * u > y * u);
245}
246
247pub broadcast proof fn lemma_mul_inequality_converse(x: int, y: int, z: int)
249 requires
250 #[trigger] (x * z) <= #[trigger] (y * z),
251 z > 0,
252 ensures
253 x <= y,
254{
255 lemma_mul_induction_auto(z, |u: int| x * u <= y * u && u > 0 ==> x <= y);
256}
257
258pub broadcast proof fn lemma_mul_strict_inequality_converse(x: int, y: int, z: int)
260 requires
261 #[trigger] (x * z) < #[trigger] (y * z),
262 z >= 0,
263 ensures
264 x < y,
265{
266 lemma_mul_induction_auto(z, |u: int| x * u < y * u && u >= 0 ==> x < y);
267}
268
269pub broadcast proof fn lemma_mul_is_distributive_add(x: int, y: int, z: int)
272 ensures
273 #[trigger] (x * (y + z)) == x * y + x * z,
274{
275 MulINL::lemma_mul_is_distributive_add(x, y, z);
276}
277
278pub broadcast proof fn lemma_mul_is_distributive_add_other_way(x: int, y: int, z: int)
281 ensures
282 #[trigger] ((y + z) * x) == y * x + z * x,
283{
284 broadcast use group_mul_properties_internal;
285
286}
287
288pub broadcast proof fn lemma_mul_is_distributive_sub(x: int, y: int, z: int)
291 ensures
292 #[trigger] (x * (y - z)) == x * y - x * z,
293{
294 broadcast use group_mul_properties_internal;
295
296}
297
298pub broadcast proof fn lemma_mul_is_distributive_sub_other_way(x: int, y: int, z: int)
302 ensures
303 #[trigger] ((y - z) * x) == y * x - z * x,
304{
305 lemma_mul_is_distributive_sub(x, y, z);
306 lemma_mul_is_commutative(x, y - z);
307 lemma_mul_is_commutative(x, y);
308 lemma_mul_is_commutative(x, z);
309}
310
311pub broadcast group group_mul_is_distributive {
312 lemma_mul_is_distributive_add,
313 lemma_mul_is_distributive_add_other_way,
314 lemma_mul_is_distributive_sub,
315 lemma_mul_is_distributive_sub_other_way,
316}
317
318pub broadcast group group_mul_is_commutative_and_distributive {
319 lemma_mul_is_commutative,
320 group_mul_is_distributive,
321}
322
323proof fn lemma_mul_is_distributive(x: int, y: int, z: int)
328 ensures
329 x * (y + z) == x * y + x * z,
330 x * (y - z) == x * y - x * z,
331 (y + z) * x == y * x + z * x,
332 (y - z) * x == y * x - z * x,
333 x * (y + z) == (y + z) * x,
334 x * (y - z) == (y - z) * x,
335 x * y == y * x,
336 x * z == z * x,
337{
338 broadcast use group_mul_is_commutative_and_distributive;
339
340}
341
342pub broadcast proof fn lemma_mul_strictly_positive(x: int, y: int)
359 ensures
360 (0 < x && 0 < y) ==> (0 < #[trigger] (x * y)),
361{
362 MulINL::lemma_mul_strictly_positive(x, y);
363}
364
365pub broadcast proof fn lemma_mul_strictly_increases(x: int, y: int)
367 requires
368 1 < x,
369 0 < y,
370 ensures
371 y < #[trigger] (x * y),
372{
373 lemma_mul_induction_auto(x, |u: int| 1 < u ==> y < u * y);
374}
375
376pub broadcast proof fn lemma_mul_increases(x: int, y: int)
379 requires
380 0 < x,
381 0 < y,
382 ensures
383 y <= #[trigger] (x * y),
384{
385 lemma_mul_induction_auto(x, |u: int| 0 < u ==> y <= u * y);
386}
387
388pub broadcast proof fn lemma_mul_nonnegative(x: int, y: int)
391 requires
392 0 <= x,
393 0 <= y,
394 ensures
395 0 <= #[trigger] (x * y),
396{
397 lemma_mul_induction_auto(x, |u: int| 0 <= u ==> 0 <= u * y);
398}
399
400pub broadcast proof fn lemma_mul_unary_negation(x: int, y: int)
403 ensures
404 #![trigger (-x) * y]
405 #![trigger x * (-y)]
406 (-x) * y == -(x * y) == x * (-y),
407{
408 lemma_mul_induction_auto(x, |u: int| (-u) * y == -(u * y) == u * (-y));
409}
410
411pub broadcast proof fn lemma_mul_cancels_negatives(x: int, y: int)
414 ensures
415 #[trigger] (x * y) == (-x) * (-y),
416{
417 lemma_mul_induction_auto(x, |u: int| (-u) * y == -(u * y) == u * (-y));
418}
419
420pub broadcast group group_mul_properties {
421 group_mul_basics,
422 lemma_mul_strict_inequality,
423 lemma_mul_inequality,
424 group_mul_is_commutative_and_distributive,
425 lemma_mul_is_associative,
426 lemma_mul_ordering,
427 lemma_mul_nonzero,
428 lemma_mul_nonnegative,
429 lemma_mul_strictly_increases,
430 lemma_mul_increases,
431}
432
433proof fn lemma_mul_properties_prove_mul_properties_auto()
435 ensures
436 forall|x: int, y: int| #[trigger] (x * y) == y * x,
437 forall|x: int| #![trigger x * 1] #![trigger 1 * x] x * 1 == 1 * x == x,
438 forall|x: int, y: int, z: int| x < y && z > 0 ==> #[trigger] (x * z) < #[trigger] (y * z),
439 forall|x: int, y: int, z: int|
440 x <= y && z >= 0 ==> #[trigger] (x * z) <= #[trigger] (y * z),
441 forall|x: int, y: int, z: int| #[trigger] (x * (y + z)) == x * y + x * z,
442 forall|x: int, y: int, z: int| #[trigger] (x * (y - z)) == x * y - x * z,
443 forall|x: int, y: int, z: int| #[trigger] ((y + z) * x) == y * x + z * x,
444 forall|x: int, y: int, z: int| #[trigger] ((y - z) * x) == y * x - z * x,
445 forall|x: int, y: int, z: int|
446 #![trigger x * (y * z)]
447 #![trigger (x * y) * z]
448 x * (y * z) == (x * y) * z,
449 forall|x: int, y: int| #[trigger] (x * y) != 0 <==> x != 0 && y != 0,
450 forall|x: int, y: int| 0 <= x && 0 <= y ==> 0 <= #[trigger] (x * y),
451 forall|x: int, y: int|
452 0 < x && 0 < y && 0 <= x * y ==> x <= #[trigger] (x * y) && y <= (x * y),
453 forall|x: int, y: int| (1 < x && 0 < y) ==> (y < #[trigger] (x * y)),
454 forall|x: int, y: int| (0 < x && 0 < y) ==> (y <= #[trigger] (x * y)),
455 forall|x: int, y: int| (0 < x && 0 < y) ==> (0 < #[trigger] (x * y)),
456{
457 broadcast use group_mul_properties;
458
459}
460
461}