Built with Alectryon, running Coq+SerAPI v8.10.0+0.7.0. Coq sources are in this panel; goals and messages will appear in the other. Bubbles () indicate interactive fragments: hover for details, tap to reveal contents. Use Ctrl+↑ Ctrl+↓ to navigate, Ctrl+🖱️ to focus.
(************************************************************************) (* * The Coq Proof Assistant / The Coq Development Team *) (* v * INRIA, CNRS and contributors - Copyright 1999-2018 *) (* <O___,, * (see CREDITS file for the list of authors) *) (* \VV/ **************************************************************) (* // * This file is distributed under the terms of the *) (* * GNU Lesser General Public License Version 2.1 *) (* * (see LICENSE file for the text of the license) *) (************************************************************************) Require Import ZAxioms ZMulOrder ZSgnAbs ZGcd ZDivTrunc ZDivFloor.
Unlike other functions around, we will define lcm below instead of
axiomatizing it. Indeed, there is no "prior art" about lcm in the
standard library to be compliant with, and the generic definition
of lcm via gcd is quite reasonable.
By the way, we also state here some combined properties of div/mod
and quot/rem and gcd.
Module Type ZLcmProp
(Import A : ZAxiomsSig')
(Import B : ZMulOrderProp A)
(Import C : ZSgnAbsProp A B)
(Import D : ZDivProp A B C)
(Import E : ZQuotProp A B C)
(Import F : ZGcdProp A B C).
The two notions of division are equal on non-negative numbers
forall a b : t, 0 <= a -> 0 < b -> a ÷ b == a / bforall a b : t, 0 <= a -> 0 < b -> a ÷ b == a / ba, b:tH:0 <= aH0:0 < ba ÷ b == a / ba, b:tH:0 <= aH0:0 < b0 <= a rem b < ba, b:tH:0 <= aH0:0 < ba == b * (a ÷ b) + a rem ba, b:tH:0 <= aH0:0 < ba == b * (a ÷ b) + a rem border. Qed.a, b:tH:0 <= aH0:0 < bb ~= 0forall a b : t, 0 <= a -> 0 < b -> a rem b == a mod bforall a b : t, 0 <= a -> 0 < b -> a rem b == a mod ba, b:tH:0 <= aH0:0 < ba rem b == a mod ba, b:tH:0 <= aH0:0 < b0 <= a rem b < ba, b:tH:0 <= aH0:0 < ba == b * (a ÷ b) + a rem ba, b:tH:0 <= aH0:0 < ba == b * (a ÷ b) + a rem border. Qed.a, b:tH:0 <= aH0:0 < bb ~= 0
We can use the sign rule to have an relation between divisions.
forall a b : t, b ~= 0 -> a ÷ b == sgn a * sgn b * (abs a / abs b)forall a b : t, b ~= 0 -> a ÷ b == sgn a * sgn b * (abs a / abs b)forall a b : t, 0 < b -> a ÷ b == sgn a * sgn b * (abs a / abs b)AUX:forall a b : t, 0 < b -> a ÷ b == sgn a * sgn b * (abs a / abs b)forall a b : t, b ~= 0 -> a ÷ b == sgn a * sgn b * (abs a / abs b)a, b:tHb:0 < ba ÷ b == sgn a * sgn b * (abs a / abs b)AUX:forall a b : t, 0 < b -> a ÷ b == sgn a * sgn b * (abs a / abs b)forall a b : t, b ~= 0 -> a ÷ b == sgn a * sgn b * (abs a / abs b)a, b:tHb:0 < ba ÷ b == sgn a * (abs a / b)AUX:forall a b : t, 0 < b -> a ÷ b == sgn a * sgn b * (abs a / abs b)forall a b : t, b ~= 0 -> a ÷ b == sgn a * sgn b * (abs a / abs b)a, b:tHb:0 < bHa:0 < aa ÷ b == sgn a * (abs a / b)a, b:tHb:0 < bHa:0 == aa ÷ b == sgn a * (abs a / b)a, b:tHb:0 < bHa:a < 0a ÷ b == sgn a * (abs a / b)AUX:forall a b : t, 0 < b -> a ÷ b == sgn a * sgn b * (abs a / abs b)forall a b : t, b ~= 0 -> a ÷ b == sgn a * sgn b * (abs a / abs b)a, b:tHb:0 < bHa:0 == aa ÷ b == sgn a * (abs a / b)a, b:tHb:0 < bHa:a < 0a ÷ b == sgn a * (abs a / b)AUX:forall a b : t, 0 < b -> a ÷ b == sgn a * sgn b * (abs a / abs b)forall a b : t, b ~= 0 -> a ÷ b == sgn a * sgn b * (abs a / abs b)a, b:tHb:0 < bHa:a < 0a ÷ b == sgn a * (abs a / b)AUX:forall a b : t, 0 < b -> a ÷ b == sgn a * sgn b * (abs a / abs b)forall a b : t, b ~= 0 -> a ÷ b == sgn a * sgn b * (abs a / abs b)a, b:tHb:0 < bHa:a < 0- a ÷ b == - a / bAUX:forall a b : t, 0 < b -> a ÷ b == sgn a * sgn b * (abs a / abs b)forall a b : t, b ~= 0 -> a ÷ b == sgn a * sgn b * (abs a / abs b)a, b:tHb:0 < bHa:a < 00 <= - aAUX:forall a b : t, 0 < b -> a ÷ b == sgn a * sgn b * (abs a / abs b)forall a b : t, b ~= 0 -> a ÷ b == sgn a * sgn b * (abs a / abs b)(* main *)AUX:forall a b : t, 0 < b -> a ÷ b == sgn a * sgn b * (abs a / abs b)forall a b : t, b ~= 0 -> a ÷ b == sgn a * sgn b * (abs a / abs b)AUX:forall a0 b0 : t, 0 < b0 -> a0 ÷ b0 == sgn a0 * sgn b0 * (abs a0 / abs b0)a, b:tHb:b ~= 0a ÷ b == sgn a * sgn b * (abs a / abs b)AUX:forall a0 b0 : t, 0 < b0 -> a0 ÷ b0 == sgn a0 * sgn b0 * (abs a0 / abs b0)a, b:tHb:b < 0 \/ 0 < ba ÷ b == sgn a * sgn b * (abs a / abs b)AUX:forall a0 b0 : t, 0 < b0 -> a0 ÷ b0 == sgn a0 * sgn b0 * (abs a0 / abs b0)a, b:tHb:b < 0a ÷ b == sgn a * sgn b * (abs a / abs b)AUX:forall a0 b0 : t, 0 < b0 -> a0 ÷ b0 == sgn a0 * sgn b0 * (abs a0 / abs b0)a, b:tHb:b < 0a ÷ - - b == sgn a * sgn b * (abs a / abs b)AUX:forall a0 b0 : t, 0 < b0 -> a0 ÷ b0 == sgn a0 * sgn b0 * (abs a0 / abs b0)a, b:tHb:b < 0- (a ÷ - b) == sgn a * sgn b * (abs a / abs b)AUX:forall a0 b0 : t, 0 < b0 -> a0 ÷ b0 == sgn a0 * sgn b0 * (abs a0 / abs b0)a, b:tHb:b < 0- b ~= 0AUX:forall a0 b0 : t, 0 < b0 -> a0 ÷ b0 == sgn a0 * sgn b0 * (abs a0 / abs b0)a, b:tHb:b < 0sgn a * sgn b * (abs a / abs b) == sgn a * sgn b * (abs a / abs b)AUX:forall a0 b0 : t, 0 < b0 -> a0 ÷ b0 == sgn a0 * sgn b0 * (abs a0 / abs b0)a, b:tHb:b < 00 < - bAUX:forall a0 b0 : t, 0 < b0 -> a0 ÷ b0 == sgn a0 * sgn b0 * (abs a0 / abs b0)a, b:tHb:b < 0- b ~= 0AUX:forall a0 b0 : t, 0 < b0 -> a0 ÷ b0 == sgn a0 * sgn b0 * (abs a0 / abs b0)a, b:tHb:b < 00 < - bAUX:forall a0 b0 : t, 0 < b0 -> a0 ÷ b0 == sgn a0 * sgn b0 * (abs a0 / abs b0)a, b:tHb:b < 0- b ~= 0rewrite eq_opp_l, opp_0; order. Qed.AUX:forall a0 b0 : t, 0 < b0 -> a0 ÷ b0 == sgn a0 * sgn b0 * (abs a0 / abs b0)a, b:tHb:b < 0- b ~= 0forall a b : t, b ~= 0 -> a rem b == sgn a * (abs a mod abs b)forall a b : t, b ~= 0 -> a rem b == sgn a * (abs a mod abs b)a, b:tHb:b ~= 0a rem b == sgn a * (abs a mod abs b)a, b:tHb:b ~= 0a rem abs b == sgn a * (abs a mod abs b)a, b:tHb:b ~= 0Hb':0 < abs ba rem abs b == sgn a * (abs a mod abs b)a, b:tHb:b ~= 0Hb':0 < abs bHa:0 < aa rem abs b == sgn a * (abs a mod abs b)a, b:tHb:b ~= 0Hb':0 < abs bHa:0 == aa rem abs b == sgn a * (abs a mod abs b)a, b:tHb:b ~= 0Hb':0 < abs bHa:a < 0a rem abs b == sgn a * (abs a mod abs b)a, b:tHb:b ~= 0Hb':0 < abs bHa:0 == aa rem abs b == sgn a * (abs a mod abs b)a, b:tHb:b ~= 0Hb':0 < abs bHa:a < 0a rem abs b == sgn a * (abs a mod abs b)a, b:tHb:b ~= 0Hb':0 < abs bHa:a < 0a rem abs b == sgn a * (abs a mod abs b)a, b:tHb:b ~= 0Hb':0 < abs bHa:a < 0- a rem abs b == - a mod abs bapply opp_nonneg_nonpos; order. Qed.a, b:tHb:b ~= 0Hb':0 < abs bHa:a < 00 <= - a
Modulo and remainder are null at the same place,
and this correspond to the divisibility relation.
forall a b : t, b ~= 0 -> a mod b == 0 <-> (b | a)forall a b : t, b ~= 0 -> a mod b == 0 <-> (b | a)a, b:tHb:b ~= 0a mod b == 0 <-> (b | a)a, b:tHb:b ~= 0a mod b == 0 -> (b | a)a, b:tHb:b ~= 0(b | a) -> a mod b == 0a, b:tHb:b ~= 0Hab:a mod b == 0(b | a)a, b:tHb:b ~= 0(b | a) -> a mod b == 0a, b:tHb:b ~= 0Hab:a mod b == 0a == a / b * ba, b:tHb:b ~= 0(b | a) -> a mod b == 0a, b:tHb:b ~= 0Hab:a mod b == 0a == b * (a / b)a, b:tHb:b ~= 0(b | a) -> a mod b == 0a, b:tHb:b ~= 0Hab:a mod b == 0b * (a / b) + a mod b == b * (a / b)a, b:tHb:b ~= 0(b | a) -> a mod b == 0a, b:tHb:b ~= 0(b | a) -> a mod b == 0a, b:tHb:b ~= 0c:tHc:a == c * ba mod b == 0now apply mod_mul. Qed.a, b:tHb:b ~= 0c:tHc:a == c * b(c * b) mod b == 0forall a b : t, b ~= 0 -> a rem b == 0 <-> (b | a)forall a b : t, b ~= 0 -> a rem b == 0 <-> (b | a)a, b:tHb:b ~= 0a rem b == 0 <-> (b | a)a, b:tHb:b ~= 0a rem b == 0 -> (b | a)a, b:tHb:b ~= 0(b | a) -> a rem b == 0a, b:tHb:b ~= 0Hab:a rem b == 0(b | a)a, b:tHb:b ~= 0(b | a) -> a rem b == 0a, b:tHb:b ~= 0Hab:a rem b == 0a == a ÷ b * ba, b:tHb:b ~= 0(b | a) -> a rem b == 0a, b:tHb:b ~= 0Hab:a rem b == 0a == b * (a ÷ b)a, b:tHb:b ~= 0(b | a) -> a rem b == 0a, b:tHb:b ~= 0Hab:a rem b == 0b * (a ÷ b) + a rem b == b * (a ÷ b)a, b:tHb:b ~= 0(b | a) -> a rem b == 0a, b:tHb:b ~= 0(b | a) -> a rem b == 0a, b:tHb:b ~= 0c:tHc:a == c * ba rem b == 0now apply rem_mul. Qed.a, b:tHb:b ~= 0c:tHc:a == c * b(c * b) rem b == 0forall a b : t, b ~= 0 -> a rem b == 0 <-> a mod b == 0forall a b : t, b ~= 0 -> a rem b == 0 <-> a mod b == 0now rewrite mod_divide, rem_divide. Qed.a, b:tHb:b ~= 0a rem b == 0 <-> a mod b == 0
When division is exact, div and quot agree
forall a b : t, b ~= 0 -> (b | a) -> a ÷ b == a / bforall a b : t, b ~= 0 -> (b | a) -> a ÷ b == a / ba, b:tHb:b ~= 0H:(b | a)a ÷ b == a / ba, b:tHb:b ~= 0H:(b | a)b * (a ÷ b) == b * (a / b)a, b:tHb:b ~= 0H, H':(b | a)b * (a ÷ b) == b * (a / b)a, b:tHb:b ~= 0H:a == b * (a ÷ b)H':(b | a)b * (a ÷ b) == b * (a / b)now rewrite <-H,<-H'. Qed.a, b:tHb:b ~= 0H:a == b * (a ÷ b)H':a == b * (a / b)b * (a ÷ b) == b * (a / b)forall a b c : t, b ~= 0 -> (b | a) -> c * a / b == c * (a / b)forall a b c : t, b ~= 0 -> (b | a) -> c * a / b == c * (a / b)a, b, c:tHb:b ~= 0H:(b | a)c * a / b == c * (a / b)a, b, c:tHb:b ~= 0H:(b | a)b * (c * a / b) == b * (c * (a / b))a, b, c:tHb:b ~= 0H:(b | a)b * (c * a / b) == b * (a / b) * ca, b, c:tHb:b ~= 0H, H':(b | a)b * (c * a / b) == b * (a / b) * ca, b, c:tHb:b ~= 0H:(b | a)H':a == b * (a / b)b * (c * a / b) == b * (a / b) * ca, b, c:tHb:b ~= 0H:(b | a)H':a == b * (a / b)b * (c * a / b) == c * aa, b, c:tHb:b ~= 0H:(b | a)H':a == b * (a / b)c * a == b * (c * a / b)a, b, c:tHb:b ~= 0H:(b | a)H':a == b * (a / b)(c * a) mod b == 0now apply divide_mul_r. Qed.a, b, c:tHb:b ~= 0H:(b | a)H':a == b * (a / b)(b | c * a)forall a b c : t, b ~= 0 -> (b | a) -> c * a ÷ b == c * (a ÷ b)forall a b c : t, b ~= 0 -> (b | a) -> c * a ÷ b == c * (a ÷ b)a, b, c:tHb:b ~= 0H:(b | a)c * a ÷ b == c * (a ÷ b)a, b, c:tHb:b ~= 0H:(b | a)c * a / b == c * (a / b)a, b, c:tHb:b ~= 0H:(b | a)(b | c * a)now apply divide_mul_r. Qed.a, b, c:tHb:b ~= 0H:(b | a)(b | c * a)
Gcd of divided elements, for exact divisions
forall a b c : t, 0 < c -> (c | a) -> (c | b) -> gcd (a / c) (b / c) == gcd a b / cforall a b c : t, 0 < c -> (c | a) -> (c | b) -> gcd (a / c) (b / c) == gcd a b / ca, b, c:tHc:0 < cHa:(c | a)Hb:(c | b)gcd (a / c) (b / c) == gcd a b / ca, b, c:tHc:0 < cHa:(c | a)Hb:(c | b)c * gcd (a / c) (b / c) == c * (gcd a b / c)a, b, c:tHc:0 < cHa:(c | a)Hb:(c | b)H:(c | gcd a b)c * gcd (a / c) (b / c) == c * (gcd a b / c)a, b, c:tHc:0 < cHa:(c | a)Hb:(c | b)H:gcd a b == c * (gcd a b / c)c * gcd (a / c) (b / c) == c * (gcd a b / c)a, b, c:tHc:0 < cHa:(c | a)Hb:(c | b)H:gcd a b == c * (gcd a b / c)c * gcd (a / c) (b / c) == gcd a bf_equiv; symmetry; apply div_exact; try order; apply mod_divide; trivial; try order. Qed.a, b, c:tHc:0 < cHa:(c | a)Hb:(c | b)H:gcd a b == c * (gcd a b / c)gcd (c * (a / c)) (c * (b / c)) == gcd a bforall a b c : t, 0 < c -> (c | a) -> (c | b) -> gcd (a ÷ c) (b ÷ c) == gcd a b ÷ cforall a b c : t, 0 < c -> (c | a) -> (c | b) -> gcd (a ÷ c) (b ÷ c) == gcd a b ÷ ca, b, c:tHc:0 < cHa:(c | a)Hb:(c | b)gcd (a ÷ c) (b ÷ c) == gcd a b ÷ ca, b, c:tHc:0 < cHa:(c | a)Hb:(c | b)gcd (a / c) (b / c) == gcd a b / ca, b, c:tHc:0 < cHa:(c | a)Hb:(c | b)(c | gcd a b)now apply gcd_greatest. Qed.a, b, c:tHc:0 < cHa:(c | a)Hb:(c | b)(c | gcd a b)forall a b g : t, g ~= 0 -> g == gcd a b -> gcd (a / g) (b / g) == 1forall a b g : t, g ~= 0 -> g == gcd a b -> gcd (a / g) (b / g) == 1a, b, g:tNZ:g ~= 0EQ:g == gcd a bgcd (a / g) (b / g) == 1a, b, g:tNZ:g ~= 0EQ:g == gcd a bgcd a b / g == 1a, b, g:tNZ:g ~= 0EQ:g == gcd a b0 < ga, b, g:tNZ:g ~= 0EQ:g == gcd a b(g | a)a, b, g:tNZ:g ~= 0EQ:g == gcd a b(g | b)a, b, g:tNZ:g ~= 0EQ:g == gcd a b0 < ga, b, g:tNZ:g ~= 0EQ:g == gcd a b(g | a)a, b, g:tNZ:g ~= 0EQ:g == gcd a b(g | b)a, b, g:tNZ:g ~= 0EQ:g == gcd a b(g | a)a, b, g:tNZ:g ~= 0EQ:g == gcd a b(g | b)rewrite EQ; apply gcd_divide_r. Qed.a, b, g:tNZ:g ~= 0EQ:g == gcd a b(g | b)forall a b g : t, g ~= 0 -> g == gcd a b -> gcd (a ÷ g) (b ÷ g) == 1forall a b g : t, g ~= 0 -> g == gcd a b -> gcd (a ÷ g) (b ÷ g) == 1a, b, g:tNZ:g ~= 0EQ:g == gcd a bgcd (a ÷ g) (b ÷ g) == 1a, b, g:tNZ:g ~= 0EQ:g == gcd a bgcd (a / g) (b / g) == 1a, b, g:tNZ:g ~= 0EQ:g == gcd a b(g | b)a, b, g:tNZ:g ~= 0EQ:g == gcd a b(g | a)a, b, g:tNZ:g ~= 0EQ:g == gcd a b(g | b)a, b, g:tNZ:g ~= 0EQ:g == gcd a b(g | a)rewrite EQ; apply gcd_divide_l. Qed.a, b, g:tNZ:g ~= 0EQ:g == gcd a b(g | a)
The following equality is crucial for Euclid algorithm
forall a b : t, b ~= 0 -> gcd (a mod b) b == gcd b aforall a b : t, b ~= 0 -> gcd (a mod b) b == gcd b aa, b:tHb:b ~= 0gcd (a mod b) b == gcd b aa, b:tHb:b ~= 0gcd (a - b * (a / b)) b == gcd b aa, b:tHb:b ~= 0gcd (a + - (a / b) * b) b == gcd b aapply gcd_add_mult_diag_r. Qed.a, b:tHb:b ~= 0gcd b (a + - (a / b) * b) == gcd b aforall a b : t, b ~= 0 -> gcd (a rem b) b == gcd b aforall a b : t, b ~= 0 -> gcd (a rem b) b == gcd b aa, b:tHb:b ~= 0gcd (a rem b) b == gcd b aa, b:tHb:b ~= 0gcd (a - b * (a ÷ b)) b == gcd b aa, b:tHb:b ~= 0gcd (a + - (a ÷ b) * b) b == gcd b aapply gcd_add_mult_diag_r. Qed.a, b:tHb:b ~= 0gcd b (a + - (a ÷ b) * b) == gcd b a
We now define lcm thanks to gcd:
lcm a b = a * (b / gcd a b)
= (a / gcd a b) * b
= (a*b) / gcd a b
We had an abs in order to have an always-nonnegative lcm,
in the spirit of gcd. Nota: lcm 0 0 should be 0, which
isn't guarantee with the third equation above.
Definition lcm a b := abs (a*(b/gcd a b)).Proper (eq ==> eq ==> eq) lcmProper (eq ==> eq ==> eq) lcmsolve_proper. Qed.Proper (eq ==> eq ==> eq) (fun a b : t => abs (a * (b / gcd a b)))forall a b : t, gcd a b ~= 0 -> a * (b / gcd a b) == a * b / gcd a bforall a b : t, gcd a b ~= 0 -> a * (b / gcd a b) == a * b / gcd a ba, b:tH:gcd a b ~= 0a * (b / gcd a b) == a * b / gcd a bapply gcd_divide_r. Qed.a, b:tH:gcd a b ~= 0(gcd a b | b)forall a b : t, gcd a b ~= 0 -> a / gcd a b * b == a * b / gcd a bforall a b : t, gcd a b ~= 0 -> a / gcd a b * b == a * b / gcd a ba, b:tH:gcd a b ~= 0a / gcd a b * b == a * b / gcd a ba, b:tH:gcd a b ~= 0b * (a / gcd a b) == b * a / gcd a bapply gcd_divide_l. Qed.a, b:tH:gcd a b ~= 0(gcd a b | a)forall a b : t, a / gcd a b * b == a * (b / gcd a b)forall a b : t, a / gcd a b * b == a * (b / gcd a b)a, b:ta / gcd a b * b == a * (b / gcd a b)a, b:tEQ:gcd a b == 0a / gcd a b * b == a * (b / gcd a b)a, b:tNEQ:gcd a b ~= 0a / gcd a b * b == a * (b / gcd a b)a, b:tEQ:a == 0 /\ b == 0a / gcd a b * b == a * (b / gcd a b)a, b:tNEQ:gcd a b ~= 0a / gcd a b * b == a * (b / gcd a b)a, b:tEQ:a == 0EQ':b == 0a / gcd a b * b == a * (b / gcd a b)a, b:tNEQ:gcd a b ~= 0a / gcd a b * b == a * (b / gcd a b)a, b:tEQ:a == 0EQ':b == 00 / gcd 0 0 * 0 == 0 * (0 / gcd 0 0)a, b:tNEQ:gcd a b ~= 0a / gcd a b * b == a * (b / gcd a b)now rewrite lcm_equiv1, <-lcm_equiv2. Qed.a, b:tNEQ:gcd a b ~= 0a / gcd a b * b == a * (b / gcd a b)forall a b : t, (a | lcm a b)forall a b : t, (a | lcm a b)forall a b : t, (a | abs (a * (b / gcd a b)))apply divide_abs_r, divide_factor_l. Qed.a, b:t(a | abs (a * (b / gcd a b)))forall a b : t, (b | lcm a b)forall a b : t, (b | lcm a b)forall a b : t, (b | abs (a * (b / gcd a b)))a, b:t(b | abs (a * (b / gcd a b)))a, b:t(b | a * (b / gcd a b))apply divide_factor_r. Qed.a, b:t(b | a / gcd a b * b)forall a b c : t, a ~= 0 -> (a | b) -> (b | c) -> (b / a | c / a)forall a b c : t, a ~= 0 -> (a | b) -> (b | c) -> (b / a | c / a)a, b, c:tHa:a ~= 0Hb:(a | b)c':tHc:c == c' * b(b / a | c / a)now rewrite <- divide_div_mul_exact, <- Hc. Qed.a, b, c:tHa:a ~= 0Hb:(a | b)c':tHc:c == c' * bc / a == c' * (b / a)forall a b c : t, (a | c) -> (b | c) -> (lcm a b | c)forall a b c : t, (a | c) -> (b | c) -> (lcm a b | c)a, b, c:tHa:(a | c)Hb:(b | c)(lcm a b | c)a, b, c:tHa:(a | c)Hb:(b | c)(abs (a * (b / gcd a b)) | c)a, b, c:tHa:(a | c)Hb:(b | c)(a * (b / gcd a b) | c)a, b, c:tHa:(a | c)Hb:(b | c)EQ:gcd a b == 0(a * (b / gcd a b) | c)a, b, c:tHa:(a | c)Hb:(b | c)NEQ:gcd a b ~= 0(a * (b / gcd a b) | c)a, b, c:tHa:(a | c)Hb:(b | c)EQ:a == 0 /\ b == 0(a * (b / gcd a b) | c)a, b, c:tHa:(a | c)Hb:(b | c)NEQ:gcd a b ~= 0(a * (b / gcd a b) | c)a, b, c:tHa:(a | c)Hb:(b | c)EQ:a == 0EQ':b == 0(a * (b / gcd a b) | c)a, b, c:tHa:(a | c)Hb:(b | c)NEQ:gcd a b ~= 0(a * (b / gcd a b) | c)a, b, c:tHa:(0 | c)Hb:(b | c)EQ:a == 0EQ':b == 0(0 * (b / gcd 0 b) | c)a, b, c:tHa:(a | c)Hb:(b | c)NEQ:gcd a b ~= 0(a * (b / gcd a b) | c)a, b, c:tHa:(a | c)Hb:(b | c)NEQ:gcd a b ~= 0(a * (b / gcd a b) | c)a, b, c:tHa:(a | c)Hb:(b | c)NEQ:gcd a b ~= 0Ga:(gcd a b | a)(a * (b / gcd a b) | c)a, b, c:tHa:(a | c)Hb:(b | c)NEQ:gcd a b ~= 0Ga:(gcd a b | a)Gb:(gcd a b | b)(a * (b / gcd a b) | c)a, b, c:tHa:(a | c)Hb:(b | c)g:=gcd a b:tNEQ:g ~= 0Ga:(g | a)Gb:(g | b)(a * (b / g) | c)a, b, c:tHa:(a | c)Hb:(b | c)g:=gcd a b:tNEQ:g ~= 0Ga:(g | a)Gb:(g | b)Ha':(a / g | c / g)(a * (b / g) | c)a, b, c:tHa:(a | c)Hb:(b | c)g:=gcd a b:tNEQ:g ~= 0Ga:(g | a)Gb:(g | b)Ha':(a / g | c / g)Hb':(b / g | c / g)(a * (b / g) | c)a, b, c:tHa:(a | c)Hb:(b | c)g:=gcd a b:tNEQ:g ~= 0Ga:(g | a)Gb:(g | b)a':tHa':c / g == a' * (a / g)Hb':(b / g | c / g)(a * (b / g) | c)a, b, c:tHa:(a | c)Hb:(b | c)g:=gcd a b:tNEQ:g ~= 0Ga:(g | a)Gb:(g | b)a':tHa':c / g == a' * (a / g)Hb':(b / g | a / g * a')(a * (b / g) | c)a, b, c:tHa:(a | c)Hb:(b | c)g:=gcd a b:tNEQ:g ~= 0Ga:(g | a)Gb:(g | b)a':tHa':c / g == a' * (a / g)Hb':(b / g | a')(a * (b / g) | c)a, b, c:tHa:(a | c)Hb:(b | c)g:=gcd a b:tNEQ:g ~= 0Ga:(g | a)Gb:(g | b)a':tHa':c / g == a' * (a / g)b':tHb':a' == b' * (b / g)(a * (b / g) | c)a, b, c:tHa:(a | c)Hb:(b | c)g:=gcd a b:tNEQ:g ~= 0Ga:(g | a)Gb:(g | b)a':tHa':c / g == a' * (a / g)b':tHb':a' == b' * (b / g)c == b' * (a * (b / g))a, b, c:tHa:(a | c)Hb:(b | c)g:=gcd a b:tNEQ:g ~= 0Ga:(g | a)Gb:(g | b)a':tHa':c / g == a' * (a / g)b':tHb':a' == b' * (b / g)c == a * a'a, b, c:tHa:(a | c)Hb:(b | c)g:=gcd a b:tNEQ:g ~= 0Ga:(g | a)Gb:(g | b)a':tHa':c / g == a' * (a / g)b':tHb':a' == b' * (b / g)g * (c / g) == a * a'a, b, c:tHa:(a | c)Hb:(b | c)g:=gcd a b:tNEQ:g ~= 0Ga:(g | a)Gb:(g | b)a':tHa':c / g == a' * (a / g)b':tHb':a' == b' * (b / g)c mod g == 0a, b, c:tHa:(a | c)Hb:(b | c)g:=gcd a b:tNEQ:g ~= 0Ga:(g | a)Gb:(g | b)a':tHa':c / g == a' * (a / g)b':tHb':a' == b' * (b / g)a' * (g * (a / g)) == a' * aa, b, c:tHa:(a | c)Hb:(b | c)g:=gcd a b:tNEQ:g ~= 0Ga:(g | a)Gb:(g | b)a':tHa':c / g == a' * (a / g)b':tHb':a' == b' * (b / g)c mod g == 0a, b, c:tHa:(a | c)Hb:(b | c)g:=gcd a b:tNEQ:g ~= 0Ga:(g | a)Gb:(g | b)a':tHa':c / g == a' * (a / g)b':tHb':a' == b' * (b / g)g * (a / g) == aa, b, c:tHa:(a | c)Hb:(b | c)g:=gcd a b:tNEQ:g ~= 0Ga:(g | a)Gb:(g | b)a':tHa':c / g == a' * (a / g)b':tHb':a' == b' * (b / g)c mod g == 0a, b, c:tHa:(a | c)Hb:(b | c)g:=gcd a b:tNEQ:g ~= 0Ga:(g | a)Gb:(g | b)a':tHa':c / g == a' * (a / g)b':tHb':a' == b' * (b / g)a == g * (a / g)a, b, c:tHa:(a | c)Hb:(b | c)g:=gcd a b:tNEQ:g ~= 0Ga:(g | a)Gb:(g | b)a':tHa':c / g == a' * (a / g)b':tHb':a' == b' * (b / g)c mod g == 0a, b, c:tHa:(a | c)Hb:(b | c)g:=gcd a b:tNEQ:g ~= 0Ga:(g | a)Gb:(g | b)a':tHa':c / g == a' * (a / g)b':tHb':a' == b' * (b / g)a mod g == 0a, b, c:tHa:(a | c)Hb:(b | c)g:=gcd a b:tNEQ:g ~= 0Ga:(g | a)Gb:(g | b)a':tHa':c / g == a' * (a / g)b':tHb':a' == b' * (b / g)c mod g == 0a, b, c:tHa:(a | c)Hb:(b | c)g:=gcd a b:tNEQ:g ~= 0Ga:(g | a)Gb:(g | b)a':tHa':c / g == a' * (a / g)b':tHb':a' == b' * (b / g)c mod g == 0transitivity a; trivial. Qed.a, b, c:tHa:(a | c)Hb:(b | c)g:=gcd a b:tNEQ:g ~= 0Ga:(g | a)Gb:(g | b)a':tHa':c / g == a' * (a / g)b':tHb':a' == b' * (b / g)(g | c)forall a b : t, 0 <= lcm a bforall a b : t, 0 <= lcm a ba, b:t0 <= lcm a bapply abs_nonneg. Qed.a, b:t0 <= abs (a * (b / gcd a b))forall a b : t, lcm a b == lcm b aforall a b : t, lcm a b == lcm b aa, b:tlcm a b == lcm b aa, b:tabs (a * (b / gcd a b)) == abs (b * (a / gcd b a))now rewrite <- gcd_div_swap. Qed.a, b:tabs (a * (b / gcd a b)) == abs (a / gcd a b * b)forall n m p : t, (lcm n m | p) <-> (n | p) /\ (m | p)forall n m p : t, (lcm n m | p) <-> (n | p) /\ (m | p)n, m, p:t(lcm n m | p) <-> (n | p) /\ (m | p)n, m, p:t(lcm n m | p) -> (n | p) /\ (m | p)n, m, p:t(n | p) /\ (m | p) -> (lcm n m | p)n, m, p:tH:(lcm n m | p)(n | p)n, m, p:tH:(lcm n m | p)(m | p)n, m, p:t(n | p) /\ (m | p) -> (lcm n m | p)n, m, p:tH:(lcm n m | p)(m | p)n, m, p:t(n | p) /\ (m | p) -> (lcm n m | p)n, m, p:t(n | p) /\ (m | p) -> (lcm n m | p)now apply lcm_least. Qed.n, m, p:tH:(n | p)H':(m | p)(lcm n m | p)forall n m p : t, 0 <= p -> (n | p) -> (m | p) -> (forall q : t, (n | q) -> (m | q) -> (p | q)) -> lcm n m == pforall n m p : t, 0 <= p -> (n | p) -> (m | p) -> (forall q : t, (n | q) -> (m | q) -> (p | q)) -> lcm n m == pn, m, p:tHp:0 <= pHn:(n | p)Hm:(m | p)H:forall q : t, (n | q) -> (m | q) -> (p | q)lcm n m == pn, m, p:tHp:0 <= pHn:(n | p)Hm:(m | p)H:forall q : t, (n | q) -> (m | q) -> (p | q)0 <= lcm n mn, m, p:tHp:0 <= pHn:(n | p)Hm:(m | p)H:forall q : t, (n | q) -> (m | q) -> (p | q)(lcm n m | p)n, m, p:tHp:0 <= pHn:(n | p)Hm:(m | p)H:forall q : t, (n | q) -> (m | q) -> (p | q)(p | lcm n m)n, m, p:tHp:0 <= pHn:(n | p)Hm:(m | p)H:forall q : t, (n | q) -> (m | q) -> (p | q)(lcm n m | p)n, m, p:tHp:0 <= pHn:(n | p)Hm:(m | p)H:forall q : t, (n | q) -> (m | q) -> (p | q)(p | lcm n m)n, m, p:tHp:0 <= pHn:(n | p)Hm:(m | p)H:forall q : t, (n | q) -> (m | q) -> (p | q)(p | lcm n m)n, m, p:tHp:0 <= pHn:(n | p)Hm:(m | p)H:forall q : t, (n | q) -> (m | q) -> (p | q)(n | lcm n m)n, m, p:tHp:0 <= pHn:(n | p)Hm:(m | p)H:forall q : t, (n | q) -> (m | q) -> (p | q)(m | lcm n m)apply divide_lcm_r. Qed.n, m, p:tHp:0 <= pHn:(n | p)Hm:(m | p)H:forall q : t, (n | q) -> (m | q) -> (p | q)(m | lcm n m)forall n m p : t, 0 <= p -> (forall q : t, (p | q) <-> (n | q) /\ (m | q)) -> lcm n m == pforall n m p : t, 0 <= p -> (forall q : t, (p | q) <-> (n | q) /\ (m | q)) -> lcm n m == pn, m, p:tHp:0 <= pH:forall q : t, (p | q) <-> (n | q) /\ (m | q)lcm n m == pn, m, p:tHp:0 <= pH:forall q : t, (p | q) <-> (n | q) /\ (m | q)(n | p)n, m, p:tHp:0 <= pH:forall q : t, (p | q) <-> (n | q) /\ (m | q)(m | p)n, m, p:tHp:0 <= pH:forall q : t, (p | q) <-> (n | q) /\ (m | q)forall q : t, (n | q) -> (m | q) -> (p | q)n, m, p:tHp:0 <= pH:forall q : t, (p | q) <-> (n | q) /\ (m | q)(m | p)n, m, p:tHp:0 <= pH:forall q : t, (p | q) <-> (n | q) /\ (m | q)forall q : t, (n | q) -> (m | q) -> (p | q)n, m, p:tHp:0 <= pH:forall q : t, (p | q) <-> (n | q) /\ (m | q)forall q : t, (n | q) -> (m | q) -> (p | q)n, m, p:tHp:0 <= pH:forall q0 : t, (p | q0) <-> (n | q0) /\ (m | q0)q:tH0:(n | q)H1:(m | q)(p | q)now split. Qed.n, m, p:tHp:0 <= pH:forall q0 : t, (p | q0) <-> (n | q0) /\ (m | q0)q:tH0:(n | q)H1:(m | q)(n | q) /\ (m | q)forall n m p : t, lcm n (lcm m p) == lcm (lcm n m) pforall n m p : t, lcm n (lcm m p) == lcm (lcm n m) pn, m, p:tlcm n (lcm m p) == lcm (lcm n m) pn, m, p:tforall q : t, (lcm (lcm n m) p | q) <-> (n | q) /\ (lcm m p | q)now rewrite !lcm_divide_iff, and_assoc. Qed.n, m, p, q:t(lcm (lcm n m) p | q) <-> (n | q) /\ (lcm m p | q)forall n : t, lcm 0 n == 0forall n : t, lcm 0 n == 0n:tlcm 0 n == 0n:t0 <= 0n:t(0 | 0)n:t(n | 0)n:t(0 | 0)n:t(n | 0)apply divide_0_r. Qed.n:t(n | 0)forall n : t, lcm n 0 == 0forall n : t, lcm n 0 == 0now rewrite lcm_comm, lcm_0_l. Qed.n:tlcm n 0 == 0forall n : t, 0 <= n -> lcm 1 n == nforall n : t, 0 <= n -> lcm 1 n == napply lcm_unique; trivial using divide_1_l, le_0_1, divide_refl. Qed.n:tH:0 <= nlcm 1 n == nforall n : t, 0 <= n -> lcm n 1 == nforall n : t, 0 <= n -> lcm n 1 == nnow rewrite lcm_comm, lcm_1_l_nonneg. Qed.n:tH:0 <= nlcm n 1 == nforall n : t, 0 <= n -> lcm n n == nforall n : t, 0 <= n -> lcm n n == napply lcm_unique; trivial using divide_refl. Qed.n:tH:0 <= nlcm n n == nforall n m : t, lcm n m == 0 <-> n == 0 \/ m == 0forall n m : t, lcm n m == 0 <-> n == 0 \/ m == 0n, m:tlcm n m == 0 <-> n == 0 \/ m == 0n, m:tlcm n m == 0 -> n == 0 \/ m == 0n, m:tn == 0 \/ m == 0 -> lcm n m == 0n, m:tEQ:lcm n m == 0n == 0 \/ m == 0n, m:tn == 0 \/ m == 0 -> lcm n m == 0n, m:tEQ:lcm n m == 0n * m == 0n, m:tn == 0 \/ m == 0 -> lcm n m == 0n, m:tEQ:lcm n m == 0(0 | n * m)n, m:tn == 0 \/ m == 0 -> lcm n m == 0n, m:tEQ:lcm n m == 0(lcm n m | n * m)n, m:tn == 0 \/ m == 0 -> lcm n m == 0n, m:tEQ:lcm n m == 0(n | n * m)n, m:tEQ:lcm n m == 0(m | n * m)n, m:tn == 0 \/ m == 0 -> lcm n m == 0n, m:tEQ:lcm n m == 0(m | n * m)n, m:tn == 0 \/ m == 0 -> lcm n m == 0n, m:tn == 0 \/ m == 0 -> lcm n m == 0n, m:tEQ:n == 0lcm 0 m == 0n, m:tEQ:m == 0lcm n 0 == 0apply lcm_0_r. Qed.n, m:tEQ:m == 0lcm n 0 == 0forall n m : t, 0 <= m -> (n | m) -> lcm n m == mforall n m : t, 0 <= m -> (n | m) -> lcm n m == mn, m:tHm:0 <= mH:(n | m)lcm n m == mn, m:tHm:0 <= mH:(n | m)forall q : t, (m | q) <-> (n | q) /\ (m | q)n, m:tHm:0 <= mH:(n | m)q:t(m | q) <-> (n | q) /\ (m | q)n, m:tHm:0 <= mH:(n | m)q:t(m | q) -> (n | q) /\ (m | q)n, m:tHm:0 <= mH:(n | m)q:t(n | q) /\ (m | q) -> (m | q)n, m:tHm:0 <= mH:(n | m)q:tH0:(m | q)(n | q)n, m:tHm:0 <= mH:(n | m)q:t(n | q) /\ (m | q) -> (m | q)now destruct 1. Qed.n, m:tHm:0 <= mH:(n | m)q:t(n | q) /\ (m | q) -> (m | q)forall n m : t, 0 <= m -> (n | m) <-> lcm n m == mforall n m : t, 0 <= m -> (n | m) <-> lcm n m == mn, m:tHn:0 <= m(n | m) <-> lcm n m == mn, m:tHn:0 <= m(n | m) -> lcm n m == mn, m:tHn:0 <= mlcm n m == m -> (n | m)n, m:tHn:0 <= mlcm n m == m -> (n | m)n, m:tHn:0 <= mEQ:lcm n m == m(n | m)apply divide_lcm_l. Qed.n, m:tHn:0 <= mEQ:lcm n m == m(n | lcm n m)forall n m : t, lcm (- n) m == lcm n mforall n m : t, lcm (- n) m == lcm n mn, m:tlcm (- n) m == lcm n mn, m:tforall q : t, (lcm n m | q) <-> (- n | q) /\ (m | q)n, m, q:t(lcm n m | q) <-> (- n | q) /\ (m | q)apply lcm_divide_iff. Qed.n, m, q:t(lcm n m | q) <-> (n | q) /\ (m | q)forall n m : t, lcm n (- m) == lcm n mforall n m : t, lcm n (- m) == lcm n mnow rewrite lcm_comm, lcm_opp_l, lcm_comm. Qed.n, m:tlcm n (- m) == lcm n mforall n m : t, lcm (abs n) m == lcm n mforall n m : t, lcm (abs n) m == lcm n mn, m:tlcm (abs n) m == lcm n mn, m:tH:abs n == nlcm n m == lcm n mn, m:tH:abs n == - nlcm (- n) m == lcm n mapply lcm_opp_l. Qed.n, m:tH:abs n == - nlcm (- n) m == lcm n mforall n m : t, lcm n (abs m) == lcm n mforall n m : t, lcm n (abs m) == lcm n mnow rewrite lcm_comm, lcm_abs_l, lcm_comm. Qed.n, m:tlcm n (abs m) == lcm n mforall n : t, lcm 1 n == abs nforall n : t, lcm 1 n == abs nn:tlcm 1 n == abs napply lcm_1_l_nonneg, abs_nonneg. Qed.n:tlcm 1 (abs n) == abs nforall n : t, lcm n 1 == abs nforall n : t, lcm n 1 == abs nnow rewrite lcm_comm, lcm_1_l. Qed.n:tlcm n 1 == abs nforall n : t, lcm n n == abs nforall n : t, lcm n n == abs nn:tlcm n n == abs napply lcm_diag_nonneg, abs_nonneg. Qed.n:tlcm (abs n) (abs n) == abs nforall n m p : t, lcm (p * n) (p * m) == abs p * lcm n mforall n m p : t, lcm (p * n) (p * m) == abs p * lcm n mn, m, p:tlcm (p * n) (p * m) == abs p * lcm n mn, m, p:tHp:p == 0lcm (p * n) (p * m) == abs p * lcm n mn, m, p:tHp:p ~= 0lcm (p * n) (p * m) == abs p * lcm n mn, m, p:tHp:p == 0lcm (0 * n) (0 * m) == abs 0 * lcm n mn, m, p:tHp:p ~= 0lcm (p * n) (p * m) == abs p * lcm n mn, m, p:tHp:p == 0lcm 0 0 == abs 0 * lcm n mn, m, p:tHp:p ~= 0lcm (p * n) (p * m) == abs p * lcm n mn, m, p:tHp:p == 00 == 0 * lcm n mn, m, p:tHp:p ~= 0lcm (p * n) (p * m) == abs p * lcm n mn, m, p:tHp:p ~= 0lcm (p * n) (p * m) == abs p * lcm n mn, m, p:tHp:p ~= 0Hg:gcd n m == 0lcm (p * n) (p * m) == abs p * lcm n mn, m, p:tHp:p ~= 0Hg:gcd n m ~= 0lcm (p * n) (p * m) == abs p * lcm n mn, m, p:tHp:p ~= 0Hg:n == 0 /\ m == 0lcm (p * n) (p * m) == abs p * lcm n mn, m, p:tHp:p ~= 0Hg:gcd n m ~= 0lcm (p * n) (p * m) == abs p * lcm n mn, m, p:tHp:p ~= 0Hn:n == 0Hm:m == 0lcm (p * 0) (p * 0) == abs p * lcm 0 0n, m, p:tHp:p ~= 0Hg:gcd n m ~= 0lcm (p * n) (p * m) == abs p * lcm n mn, m, p:tHp:p ~= 0Hn:n == 0Hm:m == 0lcm 0 0 == abs p * lcm 0 0n, m, p:tHp:p ~= 0Hg:gcd n m ~= 0lcm (p * n) (p * m) == abs p * lcm n mn, m, p:tHp:p ~= 0Hn:n == 0Hm:m == 00 == abs p * 0n, m, p:tHp:p ~= 0Hg:gcd n m ~= 0lcm (p * n) (p * m) == abs p * lcm n mn, m, p:tHp:p ~= 0Hg:gcd n m ~= 0lcm (p * n) (p * m) == abs p * lcm n mn, m, p:tHp:p ~= 0Hg:gcd n m ~= 0abs (p * n * (p * m / gcd (p * n) (p * m))) == abs p * abs (n * (m / gcd n m))n, m, p:tHp:p ~= 0Hg:gcd n m ~= 0abs (p * n * (p * m / (abs p * gcd n m))) == abs p * abs (n * (m / gcd n m))n, m, p:tHp:p ~= 0Hg:gcd n m ~= 0abs p * abs n * abs (p * m / (abs p * gcd n m)) == abs p * abs n * abs (m / gcd n m)n, m, p:tHp:p ~= 0Hg:gcd n m ~= 0abs (p * m / (abs p * gcd n m)) == abs (m / gcd n m)n, m, p:tHp:p ~= 0Hg:gcd n m ~= 0abs (abs p * sgn p * m / (abs p * gcd n m)) == abs (m / gcd n m)n, m, p:tHp:p ~= 0Hg:gcd n m ~= 0abs (abs p * (sgn p * m) / (abs p * gcd n m)) == abs (m / gcd n m)n, m, p:tHp:p ~= 0Hg:gcd n m ~= 0abs (sgn p * m / gcd n m) == abs (m / gcd n m)n, m, p:tHp:p ~= 0Hg:gcd n m ~= 0abs p ~= 0n, m, p:tHp:p ~= 0Hg:gcd n m ~= 0abs (sgn p * (m / gcd n m)) == abs (m / gcd n m)n, m, p:tHp:p ~= 0Hg:gcd n m ~= 0(gcd n m | m)n, m, p:tHp:p ~= 0Hg:gcd n m ~= 0abs p ~= 0n, m, p:tHp:p ~= 0Hg:gcd n m ~= 0abs (sgn p) * abs (m / gcd n m) == abs (m / gcd n m)n, m, p:tHp:p ~= 0Hg:gcd n m ~= 0(gcd n m | m)n, m, p:tHp:p ~= 0Hg:gcd n m ~= 0abs p ~= 0n, m, p:tHp:p ~= 0Hg:gcd n m ~= 0sgn p * sgn p * abs (m / gcd n m) == abs (m / gcd n m)n, m, p:tHp:p ~= 0Hg:gcd n m ~= 0(gcd n m | m)n, m, p:tHp:p ~= 0Hg:gcd n m ~= 0abs p ~= 0n, m, p:tHp:p ~= 0Hg:gcd n m ~= 0EQ:sgn p == 1sgn p * sgn p * abs (m / gcd n m) == abs (m / gcd n m)n, m, p:tHp:p ~= 0Hg:gcd n m ~= 0EQ:0 == psgn p * sgn p * abs (m / gcd n m) == abs (m / gcd n m)n, m, p:tHp:p ~= 0Hg:gcd n m ~= 0EQ:sgn p == -1sgn p * sgn p * abs (m / gcd n m) == abs (m / gcd n m)n, m, p:tHp:p ~= 0Hg:gcd n m ~= 0(gcd n m | m)n, m, p:tHp:p ~= 0Hg:gcd n m ~= 0abs p ~= 0n, m, p:tHp:p ~= 0Hg:gcd n m ~= 0EQ:sgn p == 11 * 1 * abs (m / gcd n m) == abs (m / gcd n m)n, m, p:tHp:p ~= 0Hg:gcd n m ~= 0EQ:0 == psgn p * sgn p * abs (m / gcd n m) == abs (m / gcd n m)n, m, p:tHp:p ~= 0Hg:gcd n m ~= 0EQ:sgn p == -1sgn p * sgn p * abs (m / gcd n m) == abs (m / gcd n m)n, m, p:tHp:p ~= 0Hg:gcd n m ~= 0(gcd n m | m)n, m, p:tHp:p ~= 0Hg:gcd n m ~= 0abs p ~= 0n, m, p:tHp:p ~= 0Hg:gcd n m ~= 0EQ:0 == psgn p * sgn p * abs (m / gcd n m) == abs (m / gcd n m)n, m, p:tHp:p ~= 0Hg:gcd n m ~= 0EQ:sgn p == -1sgn p * sgn p * abs (m / gcd n m) == abs (m / gcd n m)n, m, p:tHp:p ~= 0Hg:gcd n m ~= 0(gcd n m | m)n, m, p:tHp:p ~= 0Hg:gcd n m ~= 0abs p ~= 0n, m, p:tHp:p ~= 0Hg:gcd n m ~= 0EQ:sgn p == -1sgn p * sgn p * abs (m / gcd n m) == abs (m / gcd n m)n, m, p:tHp:p ~= 0Hg:gcd n m ~= 0(gcd n m | m)n, m, p:tHp:p ~= 0Hg:gcd n m ~= 0abs p ~= 0n, m, p:tHp:p ~= 0Hg:gcd n m ~= 0EQ:sgn p == -1-1 * -1 * abs (m / gcd n m) == abs (m / gcd n m)n, m, p:tHp:p ~= 0Hg:gcd n m ~= 0(gcd n m | m)n, m, p:tHp:p ~= 0Hg:gcd n m ~= 0abs p ~= 0n, m, p:tHp:p ~= 0Hg:gcd n m ~= 0EQ:sgn p == -11 * 1 * abs (m / gcd n m) == abs (m / gcd n m)n, m, p:tHp:p ~= 0Hg:gcd n m ~= 0(gcd n m | m)n, m, p:tHp:p ~= 0Hg:gcd n m ~= 0abs p ~= 0n, m, p:tHp:p ~= 0Hg:gcd n m ~= 0(gcd n m | m)n, m, p:tHp:p ~= 0Hg:gcd n m ~= 0abs p ~= 0n, m, p:tHp:p ~= 0Hg:gcd n m ~= 0abs p ~= 0now apply abs_0_iff. Qed.n, m, p:tHg:gcd n m ~= 0Hp:abs p == 0p == 0forall n m p : t, 0 <= p -> lcm (p * n) (p * m) == p * lcm n mforall n m p : t, 0 <= p -> lcm (p * n) (p * m) == p * lcm n mn, m, p:tH:0 <= plcm (p * n) (p * m) == p * lcm n mapply lcm_mul_mono_l. Qed.n, m, p:tH:0 <= plcm (p * n) (p * m) == abs p * lcm n mforall n m p : t, lcm (n * p) (m * p) == lcm n m * abs pforall n m p : t, lcm (n * p) (m * p) == lcm n m * abs pnow rewrite !(mul_comm _ p), lcm_mul_mono_l, mul_comm. Qed.n, m, p:tlcm (n * p) (m * p) == lcm n m * abs pforall n m p : t, 0 <= p -> lcm (n * p) (m * p) == lcm n m * pforall n m p : t, 0 <= p -> lcm (n * p) (m * p) == lcm n m * pn, m, p:tH:0 <= plcm (n * p) (m * p) == lcm n m * papply lcm_mul_mono_r. Qed.n, m, p:tH:0 <= plcm (n * p) (m * p) == lcm n m * abs pforall n m : t, n ~= 0 -> m ~= 0 -> gcd n m == 1 <-> lcm n m == abs (n * m)forall n m : t, n ~= 0 -> m ~= 0 -> gcd n m == 1 <-> lcm n m == abs (n * m)n, m:tHn:n ~= 0Hm:m ~= 0gcd n m == 1 <-> lcm n m == abs (n * m)n, m:tHn:n ~= 0Hm:m ~= 0H:gcd n m == 1lcm n m == abs (n * m)n, m:tHn:n ~= 0Hm:m ~= 0H:lcm n m == abs (n * m)gcd n m == 1n, m:tHn:n ~= 0Hm:m ~= 0H:gcd n m == 1abs (n * (m / gcd n m)) == abs (n * m)n, m:tHn:n ~= 0Hm:m ~= 0H:lcm n m == abs (n * m)gcd n m == 1n, m:tHn:n ~= 0Hm:m ~= 0H:gcd n m == 1abs (n * (m / 1)) == abs (n * m)n, m:tHn:n ~= 0Hm:m ~= 0H:lcm n m == abs (n * m)gcd n m == 1n, m:tHn:n ~= 0Hm:m ~= 0H:lcm n m == abs (n * m)gcd n m == 1n, m:tHn:n ~= 0Hm:m ~= 0H:abs (n * (m / gcd n m)) == abs (n * m)gcd n m == 1n, m:tHn:n ~= 0Hm:m ~= 0H:abs n * abs (m / gcd n m) == abs n * abs mgcd n m == 1n, m:tHn:n ~= 0Hm:m ~= 0H:abs (m / gcd n m) == abs mgcd n m == 1n, m:tHn:n ~= 0Hm:m ~= 0H:abs (m / gcd n m) == abs mH':(gcd n m | m)gcd n m == 1n, m:tHn:n ~= 0Hm:m ~= 0H:abs (m / gcd n m) == abs mH':(gcd n m | m)Hg:gcd n m ~= 0gcd n m == 1n, m:tHn:n ~= 0Hm:m ~= 0H:abs (m / gcd n m) == abs mH':m mod gcd n m == 0Hg:gcd n m ~= 0gcd n m == 1n, m:tHn:n ~= 0Hm:m ~= 0H:abs (m / gcd n m) == abs mH':m == gcd n m * (m / gcd n m)Hg:gcd n m ~= 0gcd n m == 1n, m:tHn:n ~= 0Hm:m ~= 0H:abs (m / gcd n m) == abs mH':m == gcd n m * (m / gcd n m)Hg:gcd n m ~= 0H0:m / gcd n m ~= 0gcd n m == 1n, m:tHn:n ~= 0Hm:m ~= 0H:1 * abs (m / gcd n m) == abs mH':m == gcd n m * (m / gcd n m)Hg:gcd n m ~= 0H0:m / gcd n m ~= 0gcd n m == 1n, m:tHn:n ~= 0Hm:m ~= 0H:1 * abs (m / gcd n m) == abs (gcd n m * (m / gcd n m))H':m == gcd n m * (m / gcd n m)Hg:gcd n m ~= 0H0:m / gcd n m ~= 0gcd n m == 1n, m:tHn:n ~= 0Hm:m ~= 0H:1 * abs (m / gcd n m) == abs (gcd n m) * abs (m / gcd n m)H':m == gcd n m * (m / gcd n m)Hg:gcd n m ~= 0H0:m / gcd n m ~= 0gcd n m == 1n, m:tHn:n ~= 0Hm:m ~= 0H:1 == abs (gcd n m)H':m == gcd n m * (m / gcd n m)Hg:gcd n m ~= 0H0:m / gcd n m ~= 0gcd n m == 1n, m:tHn:n ~= 0Hm:m ~= 0H:1 == gcd n mH':m == gcd n m * (m / gcd n m)Hg:gcd n m ~= 0H0:m / gcd n m ~= 0gcd n m == 1n, m:tHn:n ~= 0Hm:m ~= 0H:1 == abs (gcd n m)H':m == gcd n m * (m / gcd n m)Hg:gcd n m ~= 0H0:m / gcd n m ~= 00 <= gcd n mapply gcd_nonneg. Qed. End ZLcmProp.n, m:tHn:n ~= 0Hm:m ~= 0H:1 == abs (gcd n m)H':m == gcd n m * (m / gcd n m)Hg:gcd n m ~= 0H0:m / gcd n m ~= 00 <= gcd n m