# HG changeset patch # User haftmann # Date 1455742316 -3600 # Node ID e66d7841d5a2dba24690e14ace468e1713ca0330 # Parent 759d684c0e60eecee239326908f47bc26685f677 further generalization and polishing diff -r 759d684c0e60 -r e66d7841d5a2 NEWS --- a/NEWS Wed Feb 17 21:51:56 2016 +0100 +++ b/NEWS Wed Feb 17 21:51:56 2016 +0100 @@ -35,6 +35,8 @@ * Compound constants INFIMUM and SUPREMUM are mere abbreviations now. INCOMPATIBILITY. +* Class semiring_Lcd merged into semiring_Gcd. INCOMPATIBILITY. + New in Isabelle2016 (February 2016) ----------------------------------- diff -r 759d684c0e60 -r e66d7841d5a2 src/HOL/GCD.thy --- a/src/HOL/GCD.thy Wed Feb 17 21:51:56 2016 +0100 +++ b/src/HOL/GCD.thy Wed Feb 17 21:51:56 2016 +0100 @@ -31,7 +31,7 @@ imports Main begin -subsection \GCD and LCM definitions\ +subsection \Abstract GCD and LCM\ class gcd = zero + one + dvd + fixes gcd :: "'a \ 'a \ 'a" @@ -67,6 +67,14 @@ "b dvd c \ gcd a b dvd c" by (rule dvd_trans) (rule gcd_dvd2) +lemma dvd_gcdD1: + "a dvd gcd b c \ a dvd b" + using gcd_dvd1 [of b c] by (blast intro: dvd_trans) + +lemma dvd_gcdD2: + "a dvd gcd b c \ a dvd c" + using gcd_dvd2 [of b c] by (blast intro: dvd_trans) + lemma gcd_0_left [simp]: "gcd 0 a = normalize a" by (rule associated_eqI) simp_all @@ -203,6 +211,14 @@ "a dvd c \ a dvd lcm b c" by (rule dvd_trans) (assumption, blast) +lemma lcm_dvdD1: + "lcm a b dvd c \ a dvd c" + using dvd_lcm1 [of a b] by (blast intro: dvd_trans) + +lemma lcm_dvdD2: + "lcm a b dvd c \ b dvd c" + using dvd_lcm2 [of a b] by (blast intro: dvd_trans) + lemma lcm_least: assumes "a dvd c" and "b dvd c" shows "lcm a b dvd c" @@ -350,16 +366,79 @@ end +class ring_gcd = comm_ring_1 + semiring_gcd + class semiring_Gcd = semiring_gcd + Gcd + assumes Gcd_dvd: "a \ A \ Gcd A dvd a" and Gcd_greatest: "(\b. b \ A \ a dvd b) \ a dvd Gcd A" and normalize_Gcd [simp]: "normalize (Gcd A) = Gcd A" + assumes dvd_Lcm: "a \ A \ a dvd Lcm A" + and Lcm_least: "(\b. b \ A \ b dvd a) \ Lcm A dvd a" + and normalize_Lcm [simp]: "normalize (Lcm A) = Lcm A" begin +lemma Lcm_Gcd: + "Lcm A = Gcd {b. \a\A. a dvd b}" + by (rule associated_eqI) (auto intro: Gcd_dvd dvd_Lcm Gcd_greatest Lcm_least) + +lemma Gcd_Lcm: + "Gcd A = Lcm {b. \a\A. b dvd a}" + by (rule associated_eqI) (auto intro: Gcd_dvd dvd_Lcm Gcd_greatest Lcm_least) + lemma Gcd_empty [simp]: "Gcd {} = 0" by (rule dvd_0_left, rule Gcd_greatest) simp +lemma Lcm_empty [simp]: + "Lcm {} = 1" + by (auto intro: associated_eqI Lcm_least) + +lemma Gcd_insert [simp]: + "Gcd (insert a A) = gcd a (Gcd A)" +proof - + have "Gcd (insert a A) dvd gcd a (Gcd A)" + by (auto intro: Gcd_dvd Gcd_greatest) + moreover have "gcd a (Gcd A) dvd Gcd (insert a A)" + proof (rule Gcd_greatest) + fix b + assume "b \ insert a A" + then show "gcd a (Gcd A) dvd b" + proof + assume "b = a" then show ?thesis by simp + next + assume "b \ A" + then have "Gcd A dvd b" by (rule Gcd_dvd) + moreover have "gcd a (Gcd A) dvd Gcd A" by simp + ultimately show ?thesis by (blast intro: dvd_trans) + qed + qed + ultimately show ?thesis + by (auto intro: associated_eqI) +qed + +lemma Lcm_insert [simp]: + "Lcm (insert a A) = lcm a (Lcm A)" +proof (rule sym) + have "lcm a (Lcm A) dvd Lcm (insert a A)" + by (auto intro: dvd_Lcm Lcm_least) + moreover have "Lcm (insert a A) dvd lcm a (Lcm A)" + proof (rule Lcm_least) + fix b + assume "b \ insert a A" + then show "b dvd lcm a (Lcm A)" + proof + assume "b = a" then show ?thesis by simp + next + assume "b \ A" + then have "b dvd Lcm A" by (rule dvd_Lcm) + moreover have "Lcm A dvd lcm a (Lcm A)" by simp + ultimately show ?thesis by (blast intro: dvd_trans) + qed + qed + ultimately show "lcm a (Lcm A) = Lcm (insert a A)" + by (rule associated_eqI) (simp_all add: lcm_eq_0_iff) +qed + lemma Gcd_0_iff [simp]: "Gcd A = 0 \ A \ {0}" (is "?P \ ?Q") proof @@ -384,147 +463,6 @@ then show ?P by simp qed -lemma unit_factor_Gcd: - "unit_factor (Gcd A) = (if \a\A. a = 0 then 0 else 1)" -proof (cases "Gcd A = 0") - case True then show ?thesis by auto -next - case False - from unit_factor_mult_normalize - have "unit_factor (Gcd A) * normalize (Gcd A) = Gcd A" . - then have "unit_factor (Gcd A) * Gcd A = Gcd A" by simp - then have "unit_factor (Gcd A) * Gcd A div Gcd A = Gcd A div Gcd A" by simp - with False have "unit_factor (Gcd A) = 1" by simp - with False show ?thesis by auto -qed - -lemma Gcd_UNIV [simp]: - "Gcd UNIV = 1" - by (rule associated_eqI) (auto intro: Gcd_dvd simp add: unit_factor_Gcd) - -lemma Gcd_eq_1_I: - assumes "is_unit a" and "a \ A" - shows "Gcd A = 1" -proof - - from assms have "is_unit (Gcd A)" - by (blast intro: Gcd_dvd dvd_unit_imp_unit) - then have "normalize (Gcd A) = 1" - by (rule is_unit_normalize) - then show ?thesis - by simp -qed - -lemma Gcd_insert [simp]: - "Gcd (insert a A) = gcd a (Gcd A)" -proof - - have "Gcd (insert a A) dvd gcd a (Gcd A)" - by (auto intro: Gcd_dvd Gcd_greatest) - moreover have "gcd a (Gcd A) dvd Gcd (insert a A)" - proof (rule Gcd_greatest) - fix b - assume "b \ insert a A" - then show "gcd a (Gcd A) dvd b" - proof - assume "b = a" then show ?thesis by simp - next - assume "b \ A" - then have "Gcd A dvd b" by (rule Gcd_dvd) - moreover have "gcd a (Gcd A) dvd Gcd A" by simp - ultimately show ?thesis by (blast intro: dvd_trans) - qed - qed - ultimately show ?thesis - by (auto intro: associated_eqI) -qed - -lemma dvd_Gcd: \ \FIXME remove\ - "\b\A. a dvd b \ a dvd Gcd A" - by (blast intro: Gcd_greatest) - -lemma Gcd_set [code_unfold]: - "Gcd (set as) = foldr gcd as 0" - by (induct as) simp_all - -lemma Gcd_image_normalize [simp]: - "Gcd (normalize ` A) = Gcd A" -proof - - have "Gcd (normalize ` A) dvd a" if "a \ A" for a - proof - - from that obtain B where "A = insert a B" by blast - moreover have " gcd (normalize a) (Gcd (normalize ` B)) dvd normalize a" - by (rule gcd_dvd1) - ultimately show "Gcd (normalize ` A) dvd a" - by simp - qed - then have "Gcd (normalize ` A) dvd Gcd A" and "Gcd A dvd Gcd (normalize ` A)" - by (auto intro!: Gcd_greatest intro: Gcd_dvd) - then show ?thesis - by (auto intro: associated_eqI) -qed - -end - -class semiring_Lcm = semiring_Gcd + - assumes Lcm_Gcd: "Lcm A = Gcd {b. \a\A. a dvd b}" -begin - -lemma dvd_Lcm: - assumes "a \ A" - shows "a dvd Lcm A" - using assms by (auto intro: Gcd_greatest simp add: Lcm_Gcd) - -lemma Lcm_least: - assumes "\b. b \ A \ b dvd a" - shows "Lcm A dvd a" - using assms by (auto intro: Gcd_dvd simp add: Lcm_Gcd) - -lemma normalize_Lcm [simp]: - "normalize (Lcm A) = Lcm A" - by (simp add: Lcm_Gcd) - -lemma unit_factor_Lcm: - "unit_factor (Lcm A) = (if Lcm A = 0 then 0 else 1)" -proof (cases "Lcm A = 0") - case True then show ?thesis by simp -next - case False - with unit_factor_normalize have "unit_factor (normalize (Lcm A)) = 1" - by blast - with False show ?thesis - by simp -qed - -lemma Gcd_Lcm: - "Gcd A = Lcm {b. \a\A. b dvd a}" - by (rule associated_eqI) (auto intro: Gcd_dvd dvd_Lcm Gcd_greatest Lcm_least) - -lemma Lcm_empty [simp]: - "Lcm {} = 1" - by (simp add: Lcm_Gcd) - -lemma Lcm_insert [simp]: - "Lcm (insert a A) = lcm a (Lcm A)" -proof (rule sym) - have "lcm a (Lcm A) dvd Lcm (insert a A)" - by (auto intro: dvd_Lcm Lcm_least) - moreover have "Lcm (insert a A) dvd lcm a (Lcm A)" - proof (rule Lcm_least) - fix b - assume "b \ insert a A" - then show "b dvd lcm a (Lcm A)" - proof - assume "b = a" then show ?thesis by simp - next - assume "b \ A" - then have "b dvd Lcm A" by (rule dvd_Lcm) - moreover have "Lcm A dvd lcm a (Lcm A)" by simp - ultimately show ?thesis by (blast intro: dvd_trans) - qed - qed - ultimately show "lcm a (Lcm A) = Lcm (insert a A)" - by (rule associated_eqI) (simp_all add: lcm_eq_0_iff) -qed - lemma Lcm_1_iff [simp]: "Lcm A = 1 \ (\a\A. is_unit a)" (is "?P \ ?Q") proof @@ -548,6 +486,44 @@ by simp qed +lemma unit_factor_Gcd: + "unit_factor (Gcd A) = (if \a\A. a = 0 then 0 else 1)" +proof (cases "Gcd A = 0") + case True then show ?thesis by auto +next + case False + from unit_factor_mult_normalize + have "unit_factor (Gcd A) * normalize (Gcd A) = Gcd A" . + then have "unit_factor (Gcd A) * Gcd A = Gcd A" by simp + then have "unit_factor (Gcd A) * Gcd A div Gcd A = Gcd A div Gcd A" by simp + with False have "unit_factor (Gcd A) = 1" by simp + with False show ?thesis by auto +qed + +lemma unit_factor_Lcm: + "unit_factor (Lcm A) = (if Lcm A = 0 then 0 else 1)" +proof (cases "Lcm A = 0") + case True then show ?thesis by simp +next + case False + with unit_factor_normalize have "unit_factor (normalize (Lcm A)) = 1" + by blast + with False show ?thesis + by simp +qed + +lemma Gcd_eq_1_I: + assumes "is_unit a" and "a \ A" + shows "Gcd A = 1" +proof - + from assms have "is_unit (Gcd A)" + by (blast intro: Gcd_dvd dvd_unit_imp_unit) + then have "normalize (Gcd A) = 1" + by (rule is_unit_normalize) + then show ?thesis + by simp +qed + lemma Lcm_eq_0_I: assumes "0 \ A" shows "Lcm A = 0" @@ -558,6 +534,10 @@ by simp qed +lemma Gcd_UNIV [simp]: + "Gcd UNIV = 1" + using dvd_refl by (rule Gcd_eq_1_I) simp + lemma Lcm_UNIV [simp]: "Lcm UNIV = 0" by (rule Lcm_eq_0_I) simp @@ -573,25 +553,48 @@ (auto simp add: lcm_eq_0_iff) qed +lemma dvd_Gcd: \ \FIXME remove\ + "\b\A. a dvd b \ a dvd Gcd A" + by (blast intro: Gcd_greatest) + +lemma Gcd_set [code_unfold]: + "Gcd (set as) = foldr gcd as 0" + by (induct as) simp_all + lemma Lcm_set [code_unfold]: "Lcm (set as) = foldr lcm as 1" by (induct as) simp_all - -end -class ring_gcd = comm_ring_1 + semiring_gcd +lemma Gcd_image_normalize [simp]: + "Gcd (normalize ` A) = Gcd A" +proof - + have "Gcd (normalize ` A) dvd a" if "a \ A" for a + proof - + from that obtain B where "A = insert a B" by blast + moreover have " gcd (normalize a) (Gcd (normalize ` B)) dvd normalize a" + by (rule gcd_dvd1) + ultimately show "Gcd (normalize ` A) dvd a" + by simp + qed + then have "Gcd (normalize ` A) dvd Gcd A" and "Gcd A dvd Gcd (normalize ` A)" + by (auto intro!: Gcd_greatest intro: Gcd_dvd) + then show ?thesis + by (auto intro: associated_eqI) +qed + +end + + +subsection \GCD and LCM on @{typ nat} and @{typ int}\ instantiation nat :: gcd begin -fun - gcd_nat :: "nat \ nat \ nat" -where - "gcd_nat x y = - (if y = 0 then x else gcd y (x mod y))" +fun gcd_nat :: "nat \ nat \ nat" +where "gcd_nat x y = + (if y = 0 then x else gcd y (x mod y))" -definition - lcm_nat :: "nat \ nat \ nat" +definition lcm_nat :: "nat \ nat \ nat" where "lcm_nat x y = x * y div (gcd x y)" @@ -602,22 +605,17 @@ instantiation int :: gcd begin -definition - gcd_int :: "int \ int \ int" -where - "gcd_int x y = int (gcd (nat \x\) (nat \y\))" +definition gcd_int :: "int \ int \ int" + where "gcd_int x y = int (gcd (nat \x\) (nat \y\))" -definition - lcm_int :: "int \ int \ int" -where - "lcm_int x y = int (lcm (nat \x\) (nat \y\))" +definition lcm_int :: "int \ int \ int" + where "lcm_int x y = int (lcm (nat \x\) (nat \y\))" instance .. end - -subsection \Transfer setup\ +text \Transfer setup\ lemma transfer_nat_int_gcd: "(x::int) >= 0 \ y >= 0 \ gcd (nat x) (nat y) = nat (gcd x y)" @@ -646,10 +644,6 @@ declare transfer_morphism_int_nat[transfer add return: transfer_int_nat_gcd transfer_int_nat_gcd_closures] - -subsection \GCD properties\ - -(* was gcd_induct *) lemma gcd_nat_induct: fixes m n :: nat assumes "\m. P m 0" @@ -722,11 +716,9 @@ lemma lcm_ge_0_int [simp]: "lcm (x::int) y >= 0" by (simp add: lcm_int_def) -(* was gcd_0, etc. *) lemma gcd_0_nat: "gcd (x::nat) 0 = x" by simp -(* was igcd_0, etc. *) lemma gcd_0_int [simp]: "gcd (x::int) 0 = \x\" by (unfold gcd_int_def, auto) @@ -741,7 +733,7 @@ (* weaker, but useful for the simplifier *) -lemma gcd_non_0_nat: "y ~= (0::nat) \ gcd (x::nat) y = gcd y (x mod y)" +lemma gcd_non_0_nat: "y \ (0::nat) \ gcd (x::nat) y = gcd y (x mod y)" by simp lemma gcd_1_nat [simp]: "gcd (m::nat) 1 = 1" @@ -790,18 +782,6 @@ by standard (simp_all add: dvd_int_unfold_dvd_nat gcd_int_def lcm_int_def zdiv_int nat_abs_mult_distrib [symmetric] lcm_gcd gcd_greatest) -lemma dvd_gcd_D1_nat: "k dvd gcd m n \ (k::nat) dvd m" - by (metis gcd_dvd1 dvd_trans) - -lemma dvd_gcd_D2_nat: "k dvd gcd m n \ (k::nat) dvd n" - by (metis gcd_dvd2 dvd_trans) - -lemma dvd_gcd_D1_int: "i dvd gcd m n \ (i::int) dvd m" - by (metis gcd_dvd1 dvd_trans) - -lemma dvd_gcd_D2_int: "i dvd gcd m n \ (i::int) dvd n" - by (metis gcd_dvd2 dvd_trans) - lemma gcd_le1_nat [simp]: "a \ 0 \ gcd (a::nat) b \ a" by (rule dvd_imp_le, auto) @@ -1096,17 +1076,32 @@ ultimately show ?thesis using dvd_times_left_cancel_iff [of "gcd a b" _ 1] by simp qed +lemma coprime: + "coprime a b \ (\d. d dvd a \ d dvd b \ is_unit d)" (is "?P \ ?Q") +proof + assume ?P then show ?Q by auto +next + assume ?Q + then have "is_unit (gcd a b) \ gcd a b dvd a \ gcd a b dvd b" + by blast + then have "is_unit (gcd a b)" + by simp + then show ?P + by simp +qed + end -lemma coprime_nat: "coprime (a::nat) b \ (\d. d dvd a \ d dvd b \ d = 1)" - using gcd_unique_nat[of 1 a b, simplified] by auto +lemma coprime_nat: + "coprime (a::nat) b \ (\d. d dvd a \ d dvd b \ d = 1)" + using coprime [of a b] by simp lemma coprime_Suc_0_nat: - "coprime (a::nat) b \ (\d. d dvd a \ d dvd b \ d = Suc 0)" + "coprime (a::nat) b \ (\d. d dvd a \ d dvd b \ d = Suc 0)" using coprime_nat by simp -lemma coprime_int: "coprime (a::int) b \ - (\d. d >= 0 \ d dvd a \ d dvd b \ d = 1)" +lemma coprime_int: + "coprime (a::int) b \ (\d. d \ 0 \ d dvd a \ d dvd b \ d = 1)" using gcd_unique_int [of 1 a b] apply clarsimp apply (erule subst) @@ -1136,7 +1131,6 @@ assumes z: "gcd (a::int) b \ 0" and a: "a = a' * gcd a b" and b: "b = b' * gcd a b" shows "coprime a' b'" - apply (subgoal_tac "a' = a div gcd a b") apply (erule ssubst) apply (subgoal_tac "b' = b div gcd a b") @@ -1709,7 +1703,7 @@ qed -subsection \LCM properties\ +subsection \LCM properties on @{typ nat} and @{typ int}\ lemma lcm_altdef_int [code]: "lcm (a::int) b = \a\ * \b\ div gcd a b" by (simp add: lcm_int_def lcm_nat_def zdiv_int gcd_int_def) @@ -1808,13 +1802,13 @@ by auto -subsection \The complete divisibility lattice\ +subsection \The complete divisibility lattice on @{typ nat} and @{typ int}\ text\Lifting gcd and lcm to sets (Gcd/Lcm). Gcd is defined via Lcm to facilitate the proof that we have a complete lattice. \ -instantiation nat :: Gcd +instantiation nat :: semiring_Gcd begin interpretation semilattice_neutr_set lcm "1::nat" @@ -1863,35 +1857,22 @@ definition "Gcd (M::nat set) = Lcm {d. \m\M. d dvd m}" -instance .. - -end - -instance nat :: semiring_Gcd -proof +instance proof show "Gcd N dvd n" if "n \ N" for N and n :: nat using that by (induct N rule: infinite_finite_induct) (auto simp add: Gcd_nat_def) show "n dvd Gcd N" if "\m. m \ N \ n dvd m" for N and n :: nat using that by (induct N rule: infinite_finite_induct) (auto simp add: Gcd_nat_def) -qed simp - -instance nat :: semiring_Lcm -proof - show "Lcm N = Gcd {m. \n\N. n dvd m}" for N :: "nat set" - by (rule associated_eqI) (auto intro!: Gcd_dvd Gcd_greatest) -qed + show "n dvd Lcm N" if "n \ N" for N and n ::nat + using that by (induct N rule: infinite_finite_induct) + auto + show "Lcm N dvd n" if "\m. m \ N \ m dvd n" for N and n ::nat + using that by (induct N rule: infinite_finite_induct) + auto +qed simp_all -lemma Lcm_eq_0 [simp]: - "finite (M::nat set) \ 0 \ M \ Lcm M = 0" - by (rule Lcm_eq_0_I) - -lemma Lcm0_iff [simp]: - fixes M :: "nat set" - assumes "finite M" and "M \ {}" - shows "Lcm M = 0 \ 0 \ M" - using assms by (simp add: Lcm_0_iff) +end text\Alternative characterizations of Gcd:\ @@ -1935,8 +1916,7 @@ apply(rule antisym) apply(rule Max_ge, assumption) apply(erule (2) Lcm_in_lcm_closed_set_nat) -apply clarsimp -apply (metis Lcm0_iff dvd_Lcm_nat dvd_imp_le neq0_conv) +apply (auto simp add: not_le Lcm_0_iff dvd_imp_le leD le_neq_trans) done lemma mult_inj_if_coprime_nat: @@ -1956,7 +1936,7 @@ subsubsection \Setwise gcd and lcm for integers\ -instantiation int :: Gcd +instantiation int :: semiring_Gcd begin definition @@ -1965,63 +1945,45 @@ definition "Gcd M = int (Gcd (nat ` abs ` M))" +instance by standard + (auto intro!: Gcd_dvd Gcd_greatest simp add: Gcd_int_def + Lcm_int_def int_dvd_iff dvd_int_iff dvd_int_unfold_dvd_nat [symmetric]) + +end + + +subsection \GCD and LCM on @{typ integer}\ + +instantiation integer :: gcd +begin + +context + includes integer.lifting +begin + +lift_definition gcd_integer :: "integer \ integer \ integer" + is gcd . +lift_definition lcm_integer :: "integer \ integer \ integer" + is lcm . + +end instance .. end -instance int :: semiring_Gcd - by standard (auto intro!: Gcd_dvd Gcd_greatest simp add: Gcd_int_def Lcm_int_def int_dvd_iff dvd_int_iff - dvd_int_unfold_dvd_nat [symmetric]) - -instance int :: semiring_Lcm -proof - fix K :: "int set" - have "{n. \k\K. nat \k\ dvd n} = ((\k. nat \k\) ` {l. \k\K. k dvd l})" - proof (rule set_eqI) - fix n - have "(\k\K. nat \k\ dvd n) \ (\l. (\k\K. k dvd l) \ n = nat \l\)" (is "?P \ ?Q") - proof - assume ?P - then have "(\k\K. k dvd int n) \ n = nat \int n\" - by (auto simp add: dvd_int_unfold_dvd_nat) - then show ?Q by blast - next - assume ?Q then show ?P - by (auto simp add: dvd_int_unfold_dvd_nat) - qed - then show "n \ {n. \k\K. nat \k\ dvd n} \ n \ (\k. nat \k\) ` {l. \k\K. k dvd l}" - by auto - qed - then show "Lcm K = Gcd {l. \k\K. k dvd l}" - by (simp add: Gcd_int_def Lcm_int_def Lcm_Gcd image_image) -qed - -lemma Lcm_dvd_int [simp]: - fixes M :: "int set" - assumes "\m\M. m dvd n" shows "Lcm M dvd n" - using assms by (auto intro: Lcm_least) - - -subsection \gcd and lcm instances for @{typ integer}\ - -instantiation integer :: gcd begin -context includes integer.lifting begin -lift_definition gcd_integer :: "integer \ integer \ integer" is gcd . -lift_definition lcm_integer :: "integer \ integer \ integer" is lcm . -end -instance .. -end lifting_update integer.lifting lifting_forget integer.lifting -context includes integer.lifting begin +context + includes integer.lifting +begin lemma gcd_code_integer [code]: "gcd k l = \if l = (0::integer) then k else gcd l (\k\ mod \l\)\" -by transfer(fact gcd_code_int) + by transfer (fact gcd_code_int) lemma lcm_code_integer [code]: "lcm (a::integer) b = \a\ * \b\ div gcd a b" -by transfer(fact lcm_altdef_int) + by transfer (fact lcm_altdef_int) end @@ -2184,6 +2146,33 @@ lemma comp_fun_idem_lcm_int: "comp_fun_idem (lcm :: int\int\int)" by (fact comp_fun_idem_lcm) +lemma Lcm_eq_0 [simp]: + "finite (M::nat set) \ 0 \ M \ Lcm M = 0" + by (rule Lcm_eq_0_I) + +lemma Lcm0_iff [simp]: + fixes M :: "nat set" + assumes "finite M" and "M \ {}" + shows "Lcm M = 0 \ 0 \ M" + using assms by (simp add: Lcm_0_iff) + +lemma Lcm_dvd_int [simp]: + fixes M :: "int set" + assumes "\m\M. m dvd n" shows "Lcm M dvd n" + using assms by (auto intro: Lcm_least) + +lemma dvd_gcd_D1_nat: "k dvd gcd m n \ (k::nat) dvd m" + by (fact dvd_gcdD1) + +lemma dvd_gcd_D2_nat: "k dvd gcd m n \ (k::nat) dvd n" + by (fact dvd_gcdD2) + +lemma dvd_gcd_D1_int: "i dvd gcd m n \ (i::int) dvd m" + by (fact dvd_gcdD1) + +lemma dvd_gcd_D2_int: "i dvd gcd m n \ (i::int) dvd n" + by (fact dvd_gcdD2) + interpretation dvd: order "op dvd" "\n m :: nat. n dvd m \ m \ n" by standard (auto intro: dvd_refl dvd_trans dvd_antisym)