Renamed {left,right}_distrib to distrib_{right,left}.
1 (* Authors: Christophe Tabacznyj, Lawrence C. Paulson, Amine Chaieb,
2 Thomas M. Rasmussen, Jeremy Avigad, Tobias Nipkow
5 This file deals with the functions gcd and lcm. Definitions and
6 lemmas are proved uniformly for the natural numbers and integers.
8 This file combines and revises a number of prior developments.
10 The original theories "GCD" and "Primes" were by Christophe Tabacznyj
11 and Lawrence C. Paulson, based on \cite{davenport92}. They introduced
12 gcd, lcm, and prime for the natural numbers.
14 The original theory "IntPrimes" was by Thomas M. Rasmussen, and
15 extended gcd, lcm, primes to the integers. Amine Chaieb provided
16 another extension of the notions to the integers, and added a number
17 of results to "Primes" and "GCD". IntPrimes also defined and developed
18 the congruence relations on the integers. The notion was extended to
19 the natural numbers by Chaieb.
21 Jeremy Avigad combined all of these, made everything uniform for the
22 natural numbers and the integers, and added a number of new theorems.
24 Tobias Nipkow cleaned up a lot.
28 header {* Greatest common divisor and least common multiple *}
34 declare One_nat_def [simp del]
36 subsection {* GCD and LCM definitions *}
38 class gcd = zero + one + dvd +
39 fixes gcd :: "'a \<Rightarrow> 'a \<Rightarrow> 'a"
40 and lcm :: "'a \<Rightarrow> 'a \<Rightarrow> 'a"
44 coprime :: "'a \<Rightarrow> 'a \<Rightarrow> bool"
46 "coprime x y == (gcd x y = 1)"
50 instantiation nat :: gcd
54 gcd_nat :: "nat \<Rightarrow> nat \<Rightarrow> nat"
57 (if y = 0 then x else gcd y (x mod y))"
60 lcm_nat :: "nat \<Rightarrow> nat \<Rightarrow> nat"
62 "lcm_nat x y = x * y div (gcd x y)"
68 instantiation int :: gcd
72 gcd_int :: "int \<Rightarrow> int \<Rightarrow> int"
74 "gcd_int x y = int (gcd (nat (abs x)) (nat (abs y)))"
77 lcm_int :: "int \<Rightarrow> int \<Rightarrow> int"
79 "lcm_int x y = int (lcm (nat (abs x)) (nat (abs y)))"
86 subsection {* Transfer setup *}
88 lemma transfer_nat_int_gcd:
89 "(x::int) >= 0 \<Longrightarrow> y >= 0 \<Longrightarrow> gcd (nat x) (nat y) = nat (gcd x y)"
90 "(x::int) >= 0 \<Longrightarrow> y >= 0 \<Longrightarrow> lcm (nat x) (nat y) = nat (lcm x y)"
91 unfolding gcd_int_def lcm_int_def
94 lemma transfer_nat_int_gcd_closures:
95 "x >= (0::int) \<Longrightarrow> y >= 0 \<Longrightarrow> gcd x y >= 0"
96 "x >= (0::int) \<Longrightarrow> y >= 0 \<Longrightarrow> lcm x y >= 0"
97 by (auto simp add: gcd_int_def lcm_int_def)
99 declare transfer_morphism_nat_int[transfer add return:
100 transfer_nat_int_gcd transfer_nat_int_gcd_closures]
102 lemma transfer_int_nat_gcd:
103 "gcd (int x) (int y) = int (gcd x y)"
104 "lcm (int x) (int y) = int (lcm x y)"
105 by (unfold gcd_int_def lcm_int_def, auto)
107 lemma transfer_int_nat_gcd_closures:
108 "is_nat x \<Longrightarrow> is_nat y \<Longrightarrow> gcd x y >= 0"
109 "is_nat x \<Longrightarrow> is_nat y \<Longrightarrow> lcm x y >= 0"
110 by (auto simp add: gcd_int_def lcm_int_def)
112 declare transfer_morphism_int_nat[transfer add return:
113 transfer_int_nat_gcd transfer_int_nat_gcd_closures]
116 subsection {* GCD properties *}
119 lemma gcd_nat_induct:
121 assumes "\<And>m. P m 0"
122 and "\<And>m n. 0 < n \<Longrightarrow> P n (m mod n) \<Longrightarrow> P m n"
124 apply (rule gcd_nat.induct)
125 apply (case_tac "y = 0")
126 using assms apply simp_all
129 (* specific to int *)
131 lemma gcd_neg1_int [simp]: "gcd (-x::int) y = gcd x y"
132 by (simp add: gcd_int_def)
134 lemma gcd_neg2_int [simp]: "gcd (x::int) (-y) = gcd x y"
135 by (simp add: gcd_int_def)
137 lemma abs_gcd_int[simp]: "abs(gcd (x::int) y) = gcd x y"
138 by(simp add: gcd_int_def)
140 lemma gcd_abs_int: "gcd (x::int) y = gcd (abs x) (abs y)"
141 by (simp add: gcd_int_def)
143 lemma gcd_abs1_int[simp]: "gcd (abs x) (y::int) = gcd x y"
144 by (metis abs_idempotent gcd_abs_int)
146 lemma gcd_abs2_int[simp]: "gcd x (abs y::int) = gcd x y"
147 by (metis abs_idempotent gcd_abs_int)
151 assumes "x >= 0 \<Longrightarrow> y >= 0 \<Longrightarrow> P (gcd x y)"
152 and "x >= 0 \<Longrightarrow> y <= 0 \<Longrightarrow> P (gcd x (-y))"
153 and "x <= 0 \<Longrightarrow> y >= 0 \<Longrightarrow> P (gcd (-x) y)"
154 and "x <= 0 \<Longrightarrow> y <= 0 \<Longrightarrow> P (gcd (-x) (-y))"
156 by (insert assms, auto, arith)
158 lemma gcd_ge_0_int [simp]: "gcd (x::int) y >= 0"
159 by (simp add: gcd_int_def)
161 lemma lcm_neg1_int: "lcm (-x::int) y = lcm x y"
162 by (simp add: lcm_int_def)
164 lemma lcm_neg2_int: "lcm (x::int) (-y) = lcm x y"
165 by (simp add: lcm_int_def)
167 lemma lcm_abs_int: "lcm (x::int) y = lcm (abs x) (abs y)"
168 by (simp add: lcm_int_def)
170 lemma abs_lcm_int [simp]: "abs (lcm i j::int) = lcm i j"
171 by(simp add:lcm_int_def)
173 lemma lcm_abs1_int[simp]: "lcm (abs x) (y::int) = lcm x y"
174 by (metis abs_idempotent lcm_int_def)
176 lemma lcm_abs2_int[simp]: "lcm x (abs y::int) = lcm x y"
177 by (metis abs_idempotent lcm_int_def)
181 assumes "x >= 0 \<Longrightarrow> y >= 0 \<Longrightarrow> P (lcm x y)"
182 and "x >= 0 \<Longrightarrow> y <= 0 \<Longrightarrow> P (lcm x (-y))"
183 and "x <= 0 \<Longrightarrow> y >= 0 \<Longrightarrow> P (lcm (-x) y)"
184 and "x <= 0 \<Longrightarrow> y <= 0 \<Longrightarrow> P (lcm (-x) (-y))"
186 using assms by (auto simp add: lcm_neg1_int lcm_neg2_int) arith
188 lemma lcm_ge_0_int [simp]: "lcm (x::int) y >= 0"
189 by (simp add: lcm_int_def)
191 (* was gcd_0, etc. *)
192 lemma gcd_0_nat [simp]: "gcd (x::nat) 0 = x"
195 (* was igcd_0, etc. *)
196 lemma gcd_0_int [simp]: "gcd (x::int) 0 = abs x"
197 by (unfold gcd_int_def, auto)
199 lemma gcd_0_left_nat [simp]: "gcd 0 (x::nat) = x"
202 lemma gcd_0_left_int [simp]: "gcd 0 (x::int) = abs x"
203 by (unfold gcd_int_def, auto)
205 lemma gcd_red_nat: "gcd (x::nat) y = gcd y (x mod y)"
206 by (case_tac "y = 0", auto)
208 (* weaker, but useful for the simplifier *)
210 lemma gcd_non_0_nat: "y ~= (0::nat) \<Longrightarrow> gcd (x::nat) y = gcd y (x mod y)"
213 lemma gcd_1_nat [simp]: "gcd (m::nat) 1 = 1"
216 lemma gcd_Suc_0 [simp]: "gcd (m::nat) (Suc 0) = Suc 0"
217 by (simp add: One_nat_def)
219 lemma gcd_1_int [simp]: "gcd (m::int) 1 = 1"
220 by (simp add: gcd_int_def)
222 lemma gcd_idem_nat: "gcd (x::nat) x = x"
225 lemma gcd_idem_int: "gcd (x::int) x = abs x"
226 by (auto simp add: gcd_int_def)
228 declare gcd_nat.simps [simp del]
231 \medskip @{term "gcd m n"} divides @{text m} and @{text n}. The
232 conjunctions don't seem provable separately.
235 lemma gcd_dvd1_nat [iff]: "(gcd (m::nat)) n dvd m"
236 and gcd_dvd2_nat [iff]: "(gcd m n) dvd n"
237 apply (induct m n rule: gcd_nat_induct)
238 apply (simp_all add: gcd_non_0_nat)
239 apply (blast dest: dvd_mod_imp_dvd)
242 lemma gcd_dvd1_int [iff]: "gcd (x::int) y dvd x"
243 by (metis gcd_int_def int_dvd_iff gcd_dvd1_nat)
245 lemma gcd_dvd2_int [iff]: "gcd (x::int) y dvd y"
246 by (metis gcd_int_def int_dvd_iff gcd_dvd2_nat)
248 lemma dvd_gcd_D1_nat: "k dvd gcd m n \<Longrightarrow> (k::nat) dvd m"
249 by(metis gcd_dvd1_nat dvd_trans)
251 lemma dvd_gcd_D2_nat: "k dvd gcd m n \<Longrightarrow> (k::nat) dvd n"
252 by(metis gcd_dvd2_nat dvd_trans)
254 lemma dvd_gcd_D1_int: "i dvd gcd m n \<Longrightarrow> (i::int) dvd m"
255 by(metis gcd_dvd1_int dvd_trans)
257 lemma dvd_gcd_D2_int: "i dvd gcd m n \<Longrightarrow> (i::int) dvd n"
258 by(metis gcd_dvd2_int dvd_trans)
260 lemma gcd_le1_nat [simp]: "a \<noteq> 0 \<Longrightarrow> gcd (a::nat) b \<le> a"
261 by (rule dvd_imp_le, auto)
263 lemma gcd_le2_nat [simp]: "b \<noteq> 0 \<Longrightarrow> gcd (a::nat) b \<le> b"
264 by (rule dvd_imp_le, auto)
266 lemma gcd_le1_int [simp]: "a > 0 \<Longrightarrow> gcd (a::int) b \<le> a"
267 by (rule zdvd_imp_le, auto)
269 lemma gcd_le2_int [simp]: "b > 0 \<Longrightarrow> gcd (a::int) b \<le> b"
270 by (rule zdvd_imp_le, auto)
272 lemma gcd_greatest_nat: "(k::nat) dvd m \<Longrightarrow> k dvd n \<Longrightarrow> k dvd gcd m n"
273 by (induct m n rule: gcd_nat_induct) (simp_all add: gcd_non_0_nat dvd_mod)
275 lemma gcd_greatest_int:
276 "(k::int) dvd m \<Longrightarrow> k dvd n \<Longrightarrow> k dvd gcd m n"
277 apply (subst gcd_abs_int)
278 apply (subst abs_dvd_iff [symmetric])
279 apply (rule gcd_greatest_nat [transferred])
283 lemma gcd_greatest_iff_nat [iff]: "(k dvd gcd (m::nat) n) =
285 by (blast intro!: gcd_greatest_nat intro: dvd_trans)
287 lemma gcd_greatest_iff_int: "((k::int) dvd gcd m n) = (k dvd m & k dvd n)"
288 by (blast intro!: gcd_greatest_int intro: dvd_trans)
290 lemma gcd_zero_nat [simp]: "(gcd (m::nat) n = 0) = (m = 0 & n = 0)"
291 by (simp only: dvd_0_left_iff [symmetric] gcd_greatest_iff_nat)
293 lemma gcd_zero_int [simp]: "(gcd (m::int) n = 0) = (m = 0 & n = 0)"
294 by (auto simp add: gcd_int_def)
296 lemma gcd_pos_nat [simp]: "(gcd (m::nat) n > 0) = (m ~= 0 | n ~= 0)"
297 by (insert gcd_zero_nat [of m n], arith)
299 lemma gcd_pos_int [simp]: "(gcd (m::int) n > 0) = (m ~= 0 | n ~= 0)"
300 by (insert gcd_zero_int [of m n], insert gcd_ge_0_int [of m n], arith)
302 interpretation gcd_nat: abel_semigroup "gcd :: nat \<Rightarrow> nat \<Rightarrow> nat"
304 qed (auto intro: dvd_antisym dvd_trans)
306 interpretation gcd_int: abel_semigroup "gcd :: int \<Rightarrow> int \<Rightarrow> int"
308 qed (simp_all add: gcd_int_def gcd_nat.assoc gcd_nat.commute gcd_nat.left_commute)
310 lemmas gcd_assoc_nat = gcd_nat.assoc
311 lemmas gcd_commute_nat = gcd_nat.commute
312 lemmas gcd_left_commute_nat = gcd_nat.left_commute
313 lemmas gcd_assoc_int = gcd_int.assoc
314 lemmas gcd_commute_int = gcd_int.commute
315 lemmas gcd_left_commute_int = gcd_int.left_commute
317 lemmas gcd_ac_nat = gcd_assoc_nat gcd_commute_nat gcd_left_commute_nat
319 lemmas gcd_ac_int = gcd_assoc_int gcd_commute_int gcd_left_commute_int
321 lemma gcd_unique_nat: "(d::nat) dvd a \<and> d dvd b \<and>
322 (\<forall>e. e dvd a \<and> e dvd b \<longrightarrow> e dvd d) \<longleftrightarrow> d = gcd a b"
324 apply (rule dvd_antisym)
325 apply (erule (1) gcd_greatest_nat)
329 lemma gcd_unique_int: "d >= 0 & (d::int) dvd a \<and> d dvd b \<and>
330 (\<forall>e. e dvd a \<and> e dvd b \<longrightarrow> e dvd d) \<longleftrightarrow> d = gcd a b"
331 apply (case_tac "d = 0")
334 apply (rule zdvd_antisym_nonneg)
335 apply (auto intro: gcd_greatest_int)
338 lemma gcd_proj1_if_dvd_nat [simp]: "(x::nat) dvd y \<Longrightarrow> gcd x y = x"
339 by (metis dvd.eq_iff gcd_unique_nat)
341 lemma gcd_proj2_if_dvd_nat [simp]: "(y::nat) dvd x \<Longrightarrow> gcd x y = y"
342 by (metis dvd.eq_iff gcd_unique_nat)
344 lemma gcd_proj1_if_dvd_int[simp]: "x dvd y \<Longrightarrow> gcd (x::int) y = abs x"
345 by (metis abs_dvd_iff abs_eq_0 gcd_0_left_int gcd_abs_int gcd_unique_int)
347 lemma gcd_proj2_if_dvd_int[simp]: "y dvd x \<Longrightarrow> gcd (x::int) y = abs y"
348 by (metis gcd_proj1_if_dvd_int gcd_commute_int)
352 \medskip Multiplication laws
355 lemma gcd_mult_distrib_nat: "(k::nat) * gcd m n = gcd (k * m) (k * n)"
356 -- {* \cite[page 27]{davenport92} *}
357 apply (induct m n rule: gcd_nat_induct)
359 apply (case_tac "k = 0")
360 apply (simp_all add: gcd_non_0_nat)
363 lemma gcd_mult_distrib_int: "abs (k::int) * gcd m n = gcd (k * m) (k * n)"
364 apply (subst (1 2) gcd_abs_int)
365 apply (subst (1 2) abs_mult)
366 apply (rule gcd_mult_distrib_nat [transferred])
370 lemma coprime_dvd_mult_nat: "coprime (k::nat) n \<Longrightarrow> k dvd m * n \<Longrightarrow> k dvd m"
371 apply (insert gcd_mult_distrib_nat [of m k n])
373 apply (erule_tac t = m in ssubst)
377 lemma coprime_dvd_mult_int:
378 "coprime (k::int) n \<Longrightarrow> k dvd m * n \<Longrightarrow> k dvd m"
379 apply (subst abs_dvd_iff [symmetric])
380 apply (subst dvd_abs_iff [symmetric])
381 apply (subst (asm) gcd_abs_int)
382 apply (rule coprime_dvd_mult_nat [transferred])
383 prefer 4 apply assumption
385 apply (subst abs_mult [symmetric], auto)
388 lemma coprime_dvd_mult_iff_nat: "coprime (k::nat) n \<Longrightarrow>
389 (k dvd m * n) = (k dvd m)"
390 by (auto intro: coprime_dvd_mult_nat)
392 lemma coprime_dvd_mult_iff_int: "coprime (k::int) n \<Longrightarrow>
393 (k dvd m * n) = (k dvd m)"
394 by (auto intro: coprime_dvd_mult_int)
396 lemma gcd_mult_cancel_nat: "coprime k n \<Longrightarrow> gcd ((k::nat) * m) n = gcd m n"
397 apply (rule dvd_antisym)
398 apply (rule gcd_greatest_nat)
399 apply (rule_tac n = k in coprime_dvd_mult_nat)
400 apply (simp add: gcd_assoc_nat)
401 apply (simp add: gcd_commute_nat)
402 apply (simp_all add: mult_commute)
405 lemma gcd_mult_cancel_int:
406 "coprime (k::int) n \<Longrightarrow> gcd (k * m) n = gcd m n"
407 apply (subst (1 2) gcd_abs_int)
408 apply (subst abs_mult)
409 apply (rule gcd_mult_cancel_nat [transferred], auto)
412 lemma coprime_crossproduct_nat:
414 assumes "coprime a d" and "coprime b c"
415 shows "a * c = b * d \<longleftrightarrow> a = b \<and> c = d" (is "?lhs \<longleftrightarrow> ?rhs")
417 assume ?rhs then show ?lhs by simp
420 from `?lhs` have "a dvd b * d" by (auto intro: dvdI dest: sym)
421 with `coprime a d` have "a dvd b" by (simp add: coprime_dvd_mult_iff_nat)
422 from `?lhs` have "b dvd a * c" by (auto intro: dvdI dest: sym)
423 with `coprime b c` have "b dvd a" by (simp add: coprime_dvd_mult_iff_nat)
424 from `?lhs` have "c dvd d * b" by (auto intro: dvdI dest: sym simp add: mult_commute)
425 with `coprime b c` have "c dvd d" by (simp add: coprime_dvd_mult_iff_nat gcd_commute_nat)
426 from `?lhs` have "d dvd c * a" by (auto intro: dvdI dest: sym simp add: mult_commute)
427 with `coprime a d` have "d dvd c" by (simp add: coprime_dvd_mult_iff_nat gcd_commute_nat)
428 from `a dvd b` `b dvd a` have "a = b" by (rule Nat.dvd.antisym)
429 moreover from `c dvd d` `d dvd c` have "c = d" by (rule Nat.dvd.antisym)
430 ultimately show ?rhs ..
433 lemma coprime_crossproduct_int:
435 assumes "coprime a d" and "coprime b c"
436 shows "\<bar>a\<bar> * \<bar>c\<bar> = \<bar>b\<bar> * \<bar>d\<bar> \<longleftrightarrow> \<bar>a\<bar> = \<bar>b\<bar> \<and> \<bar>c\<bar> = \<bar>d\<bar>"
437 using assms by (intro coprime_crossproduct_nat [transferred]) auto
439 text {* \medskip Addition laws *}
441 lemma gcd_add1_nat [simp]: "gcd ((m::nat) + n) n = gcd m n"
442 apply (case_tac "n = 0")
443 apply (simp_all add: gcd_non_0_nat)
446 lemma gcd_add2_nat [simp]: "gcd (m::nat) (m + n) = gcd m n"
447 apply (subst (1 2) gcd_commute_nat)
448 apply (subst add_commute)
452 (* to do: add the other variations? *)
454 lemma gcd_diff1_nat: "(m::nat) >= n \<Longrightarrow> gcd (m - n) n = gcd m n"
455 by (subst gcd_add1_nat [symmetric], auto)
457 lemma gcd_diff2_nat: "(n::nat) >= m \<Longrightarrow> gcd (n - m) n = gcd m n"
458 apply (subst gcd_commute_nat)
459 apply (subst gcd_diff1_nat [symmetric])
461 apply (subst gcd_commute_nat)
462 apply (subst gcd_diff1_nat)
464 apply (rule gcd_commute_nat)
467 lemma gcd_non_0_int: "(y::int) > 0 \<Longrightarrow> gcd x y = gcd y (x mod y)"
468 apply (frule_tac b = y and a = x in pos_mod_sign)
469 apply (simp del: pos_mod_sign add: gcd_int_def abs_if nat_mod_distrib)
470 apply (auto simp add: gcd_non_0_nat nat_mod_distrib [symmetric]
472 apply (frule_tac a = x in pos_mod_bound)
473 apply (subst (1 2) gcd_commute_nat)
474 apply (simp del: pos_mod_bound add: nat_diff_distrib gcd_diff2_nat
478 lemma gcd_red_int: "gcd (x::int) y = gcd y (x mod y)"
479 apply (case_tac "y = 0")
481 apply (case_tac "y > 0")
482 apply (subst gcd_non_0_int, auto)
483 apply (insert gcd_non_0_int [of "-y" "-x"])
487 lemma gcd_add1_int [simp]: "gcd ((m::int) + n) n = gcd m n"
488 by (metis gcd_red_int mod_add_self1 add_commute)
490 lemma gcd_add2_int [simp]: "gcd m ((m::int) + n) = gcd m n"
491 by (metis gcd_add1_int gcd_commute_int add_commute)
493 lemma gcd_add_mult_nat: "gcd (m::nat) (k * m + n) = gcd m n"
494 by (metis mod_mult_self3 gcd_commute_nat gcd_red_nat)
496 lemma gcd_add_mult_int: "gcd (m::int) (k * m + n) = gcd m n"
497 by (metis gcd_commute_int gcd_red_int mod_mult_self1 add_commute)
500 (* to do: differences, and all variations of addition rules
501 as simplification rules for nat and int *)
503 (* FIXME remove iff *)
504 lemma gcd_dvd_prod_nat [iff]: "gcd (m::nat) n dvd k * n"
505 using mult_dvd_mono [of 1] by auto
507 (* to do: add the three variations of these, and for ints? *)
509 lemma finite_divisors_nat[simp]:
510 assumes "(m::nat) ~= 0" shows "finite{d. d dvd m}"
512 have "finite{d. d <= m}" by(blast intro: bounded_nat_set_is_finite)
513 from finite_subset[OF _ this] show ?thesis using assms
514 by(bestsimp intro!:dvd_imp_le)
517 lemma finite_divisors_int[simp]:
518 assumes "(i::int) ~= 0" shows "finite{d. d dvd i}"
520 have "{d. abs d <= abs i} = {- abs i .. abs i}" by(auto simp:abs_if)
521 hence "finite{d. abs d <= abs i}" by simp
522 from finite_subset[OF _ this] show ?thesis using assms
523 by(bestsimp intro!:dvd_imp_le_int)
526 lemma Max_divisors_self_nat[simp]: "n\<noteq>0 \<Longrightarrow> Max{d::nat. d dvd n} = n"
528 apply (fastforce intro: Max_le_iff[THEN iffD2] simp: dvd_imp_le)
532 lemma Max_divisors_self_int[simp]: "n\<noteq>0 \<Longrightarrow> Max{d::int. d dvd n} = abs n"
534 apply(rule Max_le_iff [THEN iffD2])
535 apply (auto intro: abs_le_D1 dvd_imp_le_int)
538 lemma gcd_is_Max_divisors_nat:
539 "m ~= 0 \<Longrightarrow> n ~= 0 \<Longrightarrow> gcd (m::nat) n = (Max {d. d dvd m & d dvd n})"
540 apply(rule Max_eqI[THEN sym])
541 apply (metis finite_Collect_conjI finite_divisors_nat)
543 apply(metis Suc_diff_1 Suc_neq_Zero dvd_imp_le gcd_greatest_iff_nat gcd_pos_nat)
547 lemma gcd_is_Max_divisors_int:
548 "m ~= 0 ==> n ~= 0 ==> gcd (m::int) n = (Max {d. d dvd m & d dvd n})"
549 apply(rule Max_eqI[THEN sym])
550 apply (metis finite_Collect_conjI finite_divisors_int)
552 apply (metis gcd_greatest_iff_int gcd_pos_int zdvd_imp_le)
556 lemma gcd_code_int [code]:
557 "gcd k l = \<bar>if l = (0::int) then k else gcd l (\<bar>k\<bar> mod \<bar>l\<bar>)\<bar>"
558 by (simp add: gcd_int_def nat_mod_distrib gcd_non_0_nat)
561 subsection {* Coprimality *}
563 lemma div_gcd_coprime_nat:
564 assumes nz: "(a::nat) \<noteq> 0 \<or> b \<noteq> 0"
565 shows "coprime (a div gcd a b) (b div gcd a b)"
570 let ?g' = "gcd ?a' ?b'"
571 have dvdg: "?g dvd a" "?g dvd b" by simp_all
572 have dvdg': "?g' dvd ?a'" "?g' dvd ?b'" by simp_all
573 from dvdg dvdg' obtain ka kb ka' kb' where
574 kab: "a = ?g * ka" "b = ?g * kb" "?a' = ?g' * ka'" "?b' = ?g' * kb'"
575 unfolding dvd_def by blast
576 then have "?g * ?a' = (?g * ?g') * ka'" "?g * ?b' = (?g * ?g') * kb'"
578 then have dvdgg':"?g * ?g' dvd a" "?g* ?g' dvd b"
579 by (auto simp add: dvd_mult_div_cancel [OF dvdg(1)]
580 dvd_mult_div_cancel [OF dvdg(2)] dvd_def)
581 have "?g \<noteq> 0" using nz by simp
582 then have gp: "?g > 0" by arith
583 from gcd_greatest_nat [OF dvdgg'] have "?g * ?g' dvd ?g" .
584 with dvd_mult_cancel1 [OF gp] show "?g' = 1" by simp
587 lemma div_gcd_coprime_int:
588 assumes nz: "(a::int) \<noteq> 0 \<or> b \<noteq> 0"
589 shows "coprime (a div gcd a b) (b div gcd a b)"
590 apply (subst (1 2 3) gcd_abs_int)
591 apply (subst (1 2) abs_div)
594 apply(subst (1 2) abs_gcd_int)
595 apply (rule div_gcd_coprime_nat [transferred])
596 using nz apply (auto simp add: gcd_abs_int [symmetric])
599 lemma coprime_nat: "coprime (a::nat) b \<longleftrightarrow> (\<forall>d. d dvd a \<and> d dvd b \<longleftrightarrow> d = 1)"
600 using gcd_unique_nat[of 1 a b, simplified] by auto
602 lemma coprime_Suc_0_nat:
603 "coprime (a::nat) b \<longleftrightarrow> (\<forall>d. d dvd a \<and> d dvd b \<longleftrightarrow> d = Suc 0)"
604 using coprime_nat by (simp add: One_nat_def)
606 lemma coprime_int: "coprime (a::int) b \<longleftrightarrow>
607 (\<forall>d. d >= 0 \<and> d dvd a \<and> d dvd b \<longleftrightarrow> d = 1)"
608 using gcd_unique_int [of 1 a b]
613 apply (drule_tac x = "abs ?e" in exI)
614 apply (case_tac "(?e::int) >= 0")
619 lemma gcd_coprime_nat:
620 assumes z: "gcd (a::nat) b \<noteq> 0" and a: "a = a' * gcd a b" and
621 b: "b = b' * gcd a b"
622 shows "coprime a' b'"
624 apply (subgoal_tac "a' = a div gcd a b")
626 apply (subgoal_tac "b' = b div gcd a b")
628 apply (rule div_gcd_coprime_nat)
636 lemma gcd_coprime_int:
637 assumes z: "gcd (a::int) b \<noteq> 0" and a: "a = a' * gcd a b" and
638 b: "b = b' * gcd a b"
639 shows "coprime a' b'"
641 apply (subgoal_tac "a' = a div gcd a b")
643 apply (subgoal_tac "b' = b div gcd a b")
645 apply (rule div_gcd_coprime_int)
653 lemma coprime_mult_nat: assumes da: "coprime (d::nat) a" and db: "coprime d b"
654 shows "coprime d (a * b)"
655 apply (subst gcd_commute_nat)
656 using da apply (subst gcd_mult_cancel_nat)
657 apply (subst gcd_commute_nat, assumption)
658 apply (subst gcd_commute_nat, rule db)
661 lemma coprime_mult_int: assumes da: "coprime (d::int) a" and db: "coprime d b"
662 shows "coprime d (a * b)"
663 apply (subst gcd_commute_int)
664 using da apply (subst gcd_mult_cancel_int)
665 apply (subst gcd_commute_int, assumption)
666 apply (subst gcd_commute_int, rule db)
669 lemma coprime_lmult_nat:
670 assumes dab: "coprime (d::nat) (a * b)" shows "coprime d a"
672 have "gcd d a dvd gcd d (a * b)"
673 by (rule gcd_greatest_nat, auto)
674 with dab show ?thesis
678 lemma coprime_lmult_int:
679 assumes "coprime (d::int) (a * b)" shows "coprime d a"
681 have "gcd d a dvd gcd d (a * b)"
682 by (rule gcd_greatest_int, auto)
683 with assms show ?thesis
687 lemma coprime_rmult_nat:
688 assumes "coprime (d::nat) (a * b)" shows "coprime d b"
690 have "gcd d b dvd gcd d (a * b)"
691 by (rule gcd_greatest_nat, auto intro: dvd_mult)
692 with assms show ?thesis
696 lemma coprime_rmult_int:
697 assumes dab: "coprime (d::int) (a * b)" shows "coprime d b"
699 have "gcd d b dvd gcd d (a * b)"
700 by (rule gcd_greatest_int, auto intro: dvd_mult)
701 with dab show ?thesis
705 lemma coprime_mul_eq_nat: "coprime (d::nat) (a * b) \<longleftrightarrow>
706 coprime d a \<and> coprime d b"
707 using coprime_rmult_nat[of d a b] coprime_lmult_nat[of d a b]
708 coprime_mult_nat[of d a b]
711 lemma coprime_mul_eq_int: "coprime (d::int) (a * b) \<longleftrightarrow>
712 coprime d a \<and> coprime d b"
713 using coprime_rmult_int[of d a b] coprime_lmult_int[of d a b]
714 coprime_mult_int[of d a b]
717 lemma gcd_coprime_exists_nat:
718 assumes nz: "gcd (a::nat) b \<noteq> 0"
719 shows "\<exists>a' b'. a = a' * gcd a b \<and> b = b' * gcd a b \<and> coprime a' b'"
720 apply (rule_tac x = "a div gcd a b" in exI)
721 apply (rule_tac x = "b div gcd a b" in exI)
722 using nz apply (auto simp add: div_gcd_coprime_nat dvd_div_mult)
725 lemma gcd_coprime_exists_int:
726 assumes nz: "gcd (a::int) b \<noteq> 0"
727 shows "\<exists>a' b'. a = a' * gcd a b \<and> b = b' * gcd a b \<and> coprime a' b'"
728 apply (rule_tac x = "a div gcd a b" in exI)
729 apply (rule_tac x = "b div gcd a b" in exI)
730 using nz apply (auto simp add: div_gcd_coprime_int dvd_div_mult_self)
733 lemma coprime_exp_nat: "coprime (d::nat) a \<Longrightarrow> coprime d (a^n)"
734 by (induct n, simp_all add: coprime_mult_nat)
736 lemma coprime_exp_int: "coprime (d::int) a \<Longrightarrow> coprime d (a^n)"
737 by (induct n, simp_all add: coprime_mult_int)
739 lemma coprime_exp2_nat [intro]: "coprime (a::nat) b \<Longrightarrow> coprime (a^n) (b^m)"
740 apply (rule coprime_exp_nat)
741 apply (subst gcd_commute_nat)
742 apply (rule coprime_exp_nat)
743 apply (subst gcd_commute_nat, assumption)
746 lemma coprime_exp2_int [intro]: "coprime (a::int) b \<Longrightarrow> coprime (a^n) (b^m)"
747 apply (rule coprime_exp_int)
748 apply (subst gcd_commute_int)
749 apply (rule coprime_exp_int)
750 apply (subst gcd_commute_int, assumption)
753 lemma gcd_exp_nat: "gcd ((a::nat)^n) (b^n) = (gcd a b)^n"
755 assume "a = 0 & b = 0"
757 next assume "~(a = 0 & b = 0)"
758 hence "coprime ((a div gcd a b)^n) ((b div gcd a b)^n)"
759 by (auto simp:div_gcd_coprime_nat)
760 hence "gcd ((a div gcd a b)^n * (gcd a b)^n)
761 ((b div gcd a b)^n * (gcd a b)^n) = (gcd a b)^n"
762 apply (subst (1 2) mult_commute)
763 apply (subst gcd_mult_distrib_nat [symmetric])
766 also have "(a div gcd a b)^n * (gcd a b)^n = a^n"
767 apply (subst div_power)
769 apply (rule dvd_div_mult_self)
770 apply (rule dvd_power_same)
773 also have "(b div gcd a b)^n * (gcd a b)^n = b^n"
774 apply (subst div_power)
776 apply (rule dvd_div_mult_self)
777 apply (rule dvd_power_same)
780 finally show ?thesis .
783 lemma gcd_exp_int: "gcd ((a::int)^n) (b^n) = (gcd a b)^n"
784 apply (subst (1 2) gcd_abs_int)
785 apply (subst (1 2) power_abs)
786 apply (rule gcd_exp_nat [where n = n, transferred])
790 lemma division_decomp_nat: assumes dc: "(a::nat) dvd b * c"
791 shows "\<exists>b' c'. a = b' * c' \<and> b' dvd b \<and> c' dvd c"
794 {assume "?g = 0" with dc have ?thesis by auto}
796 {assume z: "?g \<noteq> 0"
797 from gcd_coprime_exists_nat[OF z]
798 obtain a' b' where ab': "a = a' * ?g" "b = b' * ?g" "coprime a' b'"
800 have thb: "?g dvd b" by auto
801 from ab'(1) have "a' dvd a" unfolding dvd_def by blast
802 with dc have th0: "a' dvd b*c" using dvd_trans[of a' a "b*c"] by simp
803 from dc ab'(1,2) have "a'*?g dvd (b'*?g) *c" by auto
804 hence "?g*a' dvd ?g * (b' * c)" by (simp add: mult_assoc)
805 with z have th_1: "a' dvd b' * c" by auto
806 from coprime_dvd_mult_nat[OF ab'(3)] th_1
807 have thc: "a' dvd c" by (subst (asm) mult_commute, blast)
808 from ab' have "a = ?g*a'" by algebra
809 with thb thc have ?thesis by blast }
810 ultimately show ?thesis by blast
813 lemma division_decomp_int: assumes dc: "(a::int) dvd b * c"
814 shows "\<exists>b' c'. a = b' * c' \<and> b' dvd b \<and> c' dvd c"
817 {assume "?g = 0" with dc have ?thesis by auto}
819 {assume z: "?g \<noteq> 0"
820 from gcd_coprime_exists_int[OF z]
821 obtain a' b' where ab': "a = a' * ?g" "b = b' * ?g" "coprime a' b'"
823 have thb: "?g dvd b" by auto
824 from ab'(1) have "a' dvd a" unfolding dvd_def by blast
825 with dc have th0: "a' dvd b*c"
826 using dvd_trans[of a' a "b*c"] by simp
827 from dc ab'(1,2) have "a'*?g dvd (b'*?g) *c" by auto
828 hence "?g*a' dvd ?g * (b' * c)" by (simp add: mult_assoc)
829 with z have th_1: "a' dvd b' * c" by auto
830 from coprime_dvd_mult_int[OF ab'(3)] th_1
831 have thc: "a' dvd c" by (subst (asm) mult_commute, blast)
832 from ab' have "a = ?g*a'" by algebra
833 with thb thc have ?thesis by blast }
834 ultimately show ?thesis by blast
837 lemma pow_divides_pow_nat:
838 assumes ab: "(a::nat) ^ n dvd b ^n" and n:"n \<noteq> 0"
842 from n obtain m where m: "n = Suc m" by (cases n, simp_all)
843 {assume "?g = 0" with ab n have ?thesis by auto }
845 {assume z: "?g \<noteq> 0"
846 hence zn: "?g ^ n \<noteq> 0" using n by simp
847 from gcd_coprime_exists_nat[OF z]
848 obtain a' b' where ab': "a = a' * ?g" "b = b' * ?g" "coprime a' b'"
850 from ab have "(a' * ?g) ^ n dvd (b' * ?g)^n"
851 by (simp add: ab'(1,2)[symmetric])
852 hence "?g^n*a'^n dvd ?g^n *b'^n"
853 by (simp only: power_mult_distrib mult_commute)
854 with zn z n have th0:"a'^n dvd b'^n" by auto
855 have "a' dvd a'^n" by (simp add: m)
856 with th0 have "a' dvd b'^n" using dvd_trans[of a' "a'^n" "b'^n"] by simp
857 hence th1: "a' dvd b'^m * b'" by (simp add: m mult_commute)
858 from coprime_dvd_mult_nat[OF coprime_exp_nat [OF ab'(3), of m]] th1
859 have "a' dvd b'" by (subst (asm) mult_commute, blast)
860 hence "a'*?g dvd b'*?g" by simp
861 with ab'(1,2) have ?thesis by simp }
862 ultimately show ?thesis by blast
865 lemma pow_divides_pow_int:
866 assumes ab: "(a::int) ^ n dvd b ^n" and n:"n \<noteq> 0"
870 from n obtain m where m: "n = Suc m" by (cases n, simp_all)
871 {assume "?g = 0" with ab n have ?thesis by auto }
873 {assume z: "?g \<noteq> 0"
874 hence zn: "?g ^ n \<noteq> 0" using n by simp
875 from gcd_coprime_exists_int[OF z]
876 obtain a' b' where ab': "a = a' * ?g" "b = b' * ?g" "coprime a' b'"
878 from ab have "(a' * ?g) ^ n dvd (b' * ?g)^n"
879 by (simp add: ab'(1,2)[symmetric])
880 hence "?g^n*a'^n dvd ?g^n *b'^n"
881 by (simp only: power_mult_distrib mult_commute)
882 with zn z n have th0:"a'^n dvd b'^n" by auto
883 have "a' dvd a'^n" by (simp add: m)
884 with th0 have "a' dvd b'^n"
885 using dvd_trans[of a' "a'^n" "b'^n"] by simp
886 hence th1: "a' dvd b'^m * b'" by (simp add: m mult_commute)
887 from coprime_dvd_mult_int[OF coprime_exp_int [OF ab'(3), of m]] th1
888 have "a' dvd b'" by (subst (asm) mult_commute, blast)
889 hence "a'*?g dvd b'*?g" by simp
890 with ab'(1,2) have ?thesis by simp }
891 ultimately show ?thesis by blast
894 lemma pow_divides_eq_nat [simp]: "n ~= 0 \<Longrightarrow> ((a::nat)^n dvd b^n) = (a dvd b)"
895 by (auto intro: pow_divides_pow_nat dvd_power_same)
897 lemma pow_divides_eq_int [simp]: "n ~= 0 \<Longrightarrow> ((a::int)^n dvd b^n) = (a dvd b)"
898 by (auto intro: pow_divides_pow_int dvd_power_same)
900 lemma divides_mult_nat:
901 assumes mr: "(m::nat) dvd r" and nr: "n dvd r" and mn:"coprime m n"
904 from mr nr obtain m' n' where m': "r = m*m'" and n': "r = n*n'"
905 unfolding dvd_def by blast
906 from mr n' have "m dvd n'*n" by (simp add: mult_commute)
907 hence "m dvd n'" using coprime_dvd_mult_iff_nat[OF mn] by simp
908 then obtain k where k: "n' = m*k" unfolding dvd_def by blast
909 from n' k show ?thesis unfolding dvd_def by auto
912 lemma divides_mult_int:
913 assumes mr: "(m::int) dvd r" and nr: "n dvd r" and mn:"coprime m n"
916 from mr nr obtain m' n' where m': "r = m*m'" and n': "r = n*n'"
917 unfolding dvd_def by blast
918 from mr n' have "m dvd n'*n" by (simp add: mult_commute)
919 hence "m dvd n'" using coprime_dvd_mult_iff_int[OF mn] by simp
920 then obtain k where k: "n' = m*k" unfolding dvd_def by blast
921 from n' k show ?thesis unfolding dvd_def by auto
924 lemma coprime_plus_one_nat [simp]: "coprime ((n::nat) + 1) n"
925 apply (subgoal_tac "gcd (n + 1) n dvd (n + 1 - n)")
927 apply (rule dvd_diff_nat)
931 lemma coprime_Suc_nat [simp]: "coprime (Suc n) n"
932 using coprime_plus_one_nat by (simp add: One_nat_def)
934 lemma coprime_plus_one_int [simp]: "coprime ((n::int) + 1) n"
935 apply (subgoal_tac "gcd (n + 1) n dvd (n + 1 - n)")
937 apply (rule dvd_diff)
941 lemma coprime_minus_one_nat: "(n::nat) \<noteq> 0 \<Longrightarrow> coprime (n - 1) n"
942 using coprime_plus_one_nat [of "n - 1"]
943 gcd_commute_nat [of "n - 1" n] by auto
945 lemma coprime_minus_one_int: "coprime ((n::int) - 1) n"
946 using coprime_plus_one_int [of "n - 1"]
947 gcd_commute_int [of "n - 1" n] by auto
949 lemma setprod_coprime_nat [rule_format]:
950 "(ALL i: A. coprime (f i) (x::nat)) --> coprime (PROD i:A. f i) x"
951 apply (case_tac "finite A")
952 apply (induct set: finite)
953 apply (auto simp add: gcd_mult_cancel_nat)
956 lemma setprod_coprime_int [rule_format]:
957 "(ALL i: A. coprime (f i) (x::int)) --> coprime (PROD i:A. f i) x"
958 apply (case_tac "finite A")
959 apply (induct set: finite)
960 apply (auto simp add: gcd_mult_cancel_int)
963 lemma coprime_common_divisor_nat: "coprime (a::nat) b \<Longrightarrow> x dvd a \<Longrightarrow>
964 x dvd b \<Longrightarrow> x = 1"
965 apply (subgoal_tac "x dvd gcd a b")
967 apply (erule (1) gcd_greatest_nat)
970 lemma coprime_common_divisor_int: "coprime (a::int) b \<Longrightarrow> x dvd a \<Longrightarrow>
971 x dvd b \<Longrightarrow> abs x = 1"
972 apply (subgoal_tac "x dvd gcd a b")
974 apply (erule (1) gcd_greatest_int)
977 lemma coprime_divisors_nat: "(d::int) dvd a \<Longrightarrow> e dvd b \<Longrightarrow> coprime a b \<Longrightarrow>
979 apply (auto simp add: dvd_def)
980 apply (frule coprime_lmult_int)
981 apply (subst gcd_commute_int)
982 apply (subst (asm) (2) gcd_commute_int)
983 apply (erule coprime_lmult_int)
986 lemma invertible_coprime_nat: "(x::nat) * y mod m = 1 \<Longrightarrow> coprime x m"
987 apply (metis coprime_lmult_nat gcd_1_nat gcd_commute_nat gcd_red_nat)
990 lemma invertible_coprime_int: "(x::int) * y mod m = 1 \<Longrightarrow> coprime x m"
991 apply (metis coprime_lmult_int gcd_1_int gcd_commute_int gcd_red_int)
995 subsection {* Bezout's theorem *}
997 (* Function bezw returns a pair of witnesses to Bezout's theorem --
998 see the theorems that follow the definition. *)
1000 bezw :: "nat \<Rightarrow> nat \<Rightarrow> int * int"
1003 (if y = 0 then (1, 0) else
1004 (snd (bezw y (x mod y)),
1005 fst (bezw y (x mod y)) - snd (bezw y (x mod y)) * int(x div y)))"
1007 lemma bezw_0 [simp]: "bezw x 0 = (1, 0)" by simp
1009 lemma bezw_non_0: "y > 0 \<Longrightarrow> bezw x y = (snd (bezw y (x mod y)),
1010 fst (bezw y (x mod y)) - snd (bezw y (x mod y)) * int(x div y))"
1013 declare bezw.simps [simp del]
1015 lemma bezw_aux [rule_format]:
1016 "fst (bezw x y) * int x + snd (bezw x y) * int y = int (gcd x y)"
1017 proof (induct x y rule: gcd_nat_induct)
1019 show "fst (bezw m 0) * int m + snd (bezw m 0) * int 0 = int (gcd m 0)"
1021 next fix m :: nat and n
1022 assume ngt0: "n > 0" and
1023 ih: "fst (bezw n (m mod n)) * int n +
1024 snd (bezw n (m mod n)) * int (m mod n) =
1025 int (gcd n (m mod n))"
1026 thus "fst (bezw m n) * int m + snd (bezw m n) * int n = int (gcd m n)"
1027 apply (simp add: bezw_non_0 gcd_non_0_nat)
1029 apply (simp add: field_simps)
1030 apply (subst mod_div_equality [of m n, symmetric])
1031 (* applying simp here undoes the last substitution!
1032 what is procedure cancel_div_mod? *)
1033 apply (simp only: field_simps of_nat_add of_nat_mult)
1039 shows "EX u v. u * (x::int) + v * y = gcd x y"
1041 have bezout_aux: "!!x y. x \<ge> (0::int) \<Longrightarrow> y \<ge> 0 \<Longrightarrow>
1042 EX u v. u * x + v * y = gcd x y"
1043 apply (rule_tac x = "fst (bezw (nat x) (nat y))" in exI)
1044 apply (rule_tac x = "snd (bezw (nat x) (nat y))" in exI)
1045 apply (unfold gcd_int_def)
1047 apply (subst bezw_aux [symmetric])
1050 have "(x \<ge> 0 \<and> y \<ge> 0) | (x \<ge> 0 \<and> y \<le> 0) | (x \<le> 0 \<and> y \<ge> 0) |
1051 (x \<le> 0 \<and> y \<le> 0)"
1053 moreover have "x \<ge> 0 \<Longrightarrow> y \<ge> 0 \<Longrightarrow> ?thesis"
1054 by (erule (1) bezout_aux)
1055 moreover have "x >= 0 \<Longrightarrow> y <= 0 \<Longrightarrow> ?thesis"
1056 apply (insert bezout_aux [of x "-y"])
1058 apply (rule_tac x = u in exI)
1059 apply (rule_tac x = "-v" in exI)
1060 apply (subst gcd_neg2_int [symmetric])
1063 moreover have "x <= 0 \<Longrightarrow> y >= 0 \<Longrightarrow> ?thesis"
1064 apply (insert bezout_aux [of "-x" y])
1066 apply (rule_tac x = "-u" in exI)
1067 apply (rule_tac x = v in exI)
1068 apply (subst gcd_neg1_int [symmetric])
1071 moreover have "x <= 0 \<Longrightarrow> y <= 0 \<Longrightarrow> ?thesis"
1072 apply (insert bezout_aux [of "-x" "-y"])
1074 apply (rule_tac x = "-u" in exI)
1075 apply (rule_tac x = "-v" in exI)
1076 apply (subst gcd_neg1_int [symmetric])
1077 apply (subst gcd_neg2_int [symmetric])
1080 ultimately show ?thesis by blast
1083 text {* versions of Bezout for nat, by Amine Chaieb *}
1086 assumes c: " \<forall>a b. P (a::nat) b \<longleftrightarrow> P b a" and z: "\<forall>a. P a 0"
1087 and add: "\<forall>a b. P a b \<longrightarrow> P a (a + b)"
1089 proof(induct "a + b" arbitrary: a b rule: less_induct)
1091 have "a = b \<or> a < b \<or> b < a" by arith
1092 moreover {assume eq: "a= b"
1093 from add[rule_format, OF z[rule_format, of a]] have "P a b" using eq
1097 hence "a + b - a < a + b \<or> a = 0" by arith
1099 {assume "a =0" with z c have "P a b" by blast }
1101 {assume "a + b - a < a + b"
1102 also have th0: "a + b - a = a + (b - a)" using lt by arith
1103 finally have "a + (b - a) < a + b" .
1104 then have "P a (a + (b - a))" by (rule add[rule_format, OF less])
1105 then have "P a b" by (simp add: th0[symmetric])}
1106 ultimately have "P a b" by blast}
1109 hence "b + a - b < a + b \<or> b = 0" by arith
1111 {assume "b =0" with z c have "P a b" by blast }
1113 {assume "b + a - b < a + b"
1114 also have th0: "b + a - b = b + (a - b)" using lt by arith
1115 finally have "b + (a - b) < a + b" .
1116 then have "P b (b + (a - b))" by (rule add[rule_format, OF less])
1117 then have "P b a" by (simp add: th0[symmetric])
1118 hence "P a b" using c by blast }
1119 ultimately have "P a b" by blast}
1120 ultimately show "P a b" by blast
1123 lemma bezout_lemma_nat:
1124 assumes ex: "\<exists>(d::nat) x y. d dvd a \<and> d dvd b \<and>
1125 (a * x = b * y + d \<or> b * x = a * y + d)"
1126 shows "\<exists>d x y. d dvd a \<and> d dvd a + b \<and>
1127 (a * x = (a + b) * y + d \<or> (a + b) * x = a * y + d)"
1130 apply (rule_tac x="d" in exI, simp)
1131 apply (case_tac "a * x = b * y + d" , simp_all)
1132 apply (rule_tac x="x + y" in exI)
1133 apply (rule_tac x="y" in exI)
1135 apply (rule_tac x="x" in exI)
1136 apply (rule_tac x="x + y" in exI)
1140 lemma bezout_add_nat: "\<exists>(d::nat) x y. d dvd a \<and> d dvd b \<and>
1141 (a * x = b * y + d \<or> b * x = a * y + d)"
1142 apply(induct a b rule: ind_euclid)
1145 apply (rule_tac x="a" in exI, simp)
1147 apply (rule_tac x="d" in exI)
1148 apply (case_tac "a * x = b * y + d", simp_all)
1149 apply (rule_tac x="x+y" in exI)
1150 apply (rule_tac x="y" in exI)
1152 apply (rule_tac x="x" in exI)
1153 apply (rule_tac x="x+y" in exI)
1157 lemma bezout1_nat: "\<exists>(d::nat) x y. d dvd a \<and> d dvd b \<and>
1158 (a * x - b * y = d \<or> b * x - a * y = d)"
1159 using bezout_add_nat[of a b]
1161 apply (rule_tac x="d" in exI, simp)
1162 apply (rule_tac x="x" in exI)
1163 apply (rule_tac x="y" in exI)
1167 lemma bezout_add_strong_nat: assumes nz: "a \<noteq> (0::nat)"
1168 shows "\<exists>d x y. d dvd a \<and> d dvd b \<and> a * x = b * y + d"
1170 from nz have ap: "a > 0" by simp
1171 from bezout_add_nat[of a b]
1172 have "(\<exists>d x y. d dvd a \<and> d dvd b \<and> a * x = b * y + d) \<or>
1173 (\<exists>d x y. d dvd a \<and> d dvd b \<and> b * x = a * y + d)" by blast
1175 {fix d x y assume H: "d dvd a" "d dvd b" "a * x = b * y + d"
1176 from H have ?thesis by blast }
1178 {fix d x y assume H: "d dvd a" "d dvd b" "b * x = a * y + d"
1179 {assume b0: "b = 0" with H have ?thesis by simp}
1181 {assume b: "b \<noteq> 0" hence bp: "b > 0" by simp
1182 from b dvd_imp_le [OF H(2)] have "d < b \<or> d = b"
1186 with nz H have ?thesis apply simp
1187 apply (rule exI[where x = b], simp)
1188 apply (rule exI[where x = b])
1189 by (rule exI[where x = "a - 1"], simp add: diff_mult_distrib2)}
1192 {assume "x=0" hence ?thesis using nz H by simp }
1194 {assume x0: "x \<noteq> 0" hence xp: "x > 0" by simp
1195 from db have "d \<le> b - 1" by simp
1196 hence "d*b \<le> b*(b - 1)" by simp
1197 with xp mult_mono[of "1" "x" "d*b" "b*(b - 1)"]
1198 have dble: "d*b \<le> x*b*(b - 1)" using bp by simp
1199 from H (3) have "d + (b - 1) * (b*x) = d + (b - 1) * (a*y + d)"
1201 hence "d + (b - 1) * a * y + (b - 1) * d = d + (b - 1) * b * x"
1202 by (simp only: mult_assoc distrib_left)
1203 hence "a * ((b - 1) * y) + d * (b - 1 + 1) = d + x*b*(b - 1)"
1205 hence "a * ((b - 1) * y) = d + x*b*(b - 1) - d*b" using bp by simp
1206 hence "a * ((b - 1) * y) = d + (x*b*(b - 1) - d*b)"
1207 by (simp only: diff_add_assoc[OF dble, of d, symmetric])
1208 hence "a * ((b - 1) * y) = b*(x*(b - 1) - d) + d"
1209 by (simp only: diff_mult_distrib2 add_commute mult_ac)
1210 hence ?thesis using H(1,2)
1212 apply (rule exI[where x=d], simp)
1213 apply (rule exI[where x="(b - 1) * y"])
1214 by (rule exI[where x="x*(b - 1) - d"], simp)}
1215 ultimately have ?thesis by blast}
1216 ultimately have ?thesis by blast}
1217 ultimately have ?thesis by blast}
1218 ultimately show ?thesis by blast
1221 lemma bezout_nat: assumes a: "(a::nat) \<noteq> 0"
1222 shows "\<exists>x y. a * x = b * y + gcd a b"
1225 from bezout_add_strong_nat[OF a, of b]
1226 obtain d x y where d: "d dvd a" "d dvd b" "a * x = b * y + d" by blast
1227 from d(1,2) have "d dvd ?g" by simp
1228 then obtain k where k: "?g = d*k" unfolding dvd_def by blast
1229 from d(3) have "a * x * k = (b * y + d) *k " by auto
1230 hence "a * (x * k) = b * (y*k) + ?g" by (algebra add: k)
1231 thus ?thesis by blast
1235 subsection {* LCM properties *}
1237 lemma lcm_altdef_int [code]: "lcm (a::int) b = (abs a) * (abs b) div gcd a b"
1238 by (simp add: lcm_int_def lcm_nat_def zdiv_int
1239 of_nat_mult gcd_int_def)
1241 lemma prod_gcd_lcm_nat: "(m::nat) * n = gcd m n * lcm m n"
1242 unfolding lcm_nat_def
1243 by (simp add: dvd_mult_div_cancel [OF gcd_dvd_prod_nat])
1245 lemma prod_gcd_lcm_int: "abs(m::int) * abs n = gcd m n * lcm m n"
1246 unfolding lcm_int_def gcd_int_def
1247 apply (subst int_mult [symmetric])
1248 apply (subst prod_gcd_lcm_nat [symmetric])
1249 apply (subst nat_abs_mult_distrib [symmetric])
1250 apply (simp, simp add: abs_mult)
1253 lemma lcm_0_nat [simp]: "lcm (m::nat) 0 = 0"
1254 unfolding lcm_nat_def by simp
1256 lemma lcm_0_int [simp]: "lcm (m::int) 0 = 0"
1257 unfolding lcm_int_def by simp
1259 lemma lcm_0_left_nat [simp]: "lcm (0::nat) n = 0"
1260 unfolding lcm_nat_def by simp
1262 lemma lcm_0_left_int [simp]: "lcm (0::int) n = 0"
1263 unfolding lcm_int_def by simp
1266 "(m::nat) > 0 \<Longrightarrow> n>0 \<Longrightarrow> lcm m n > 0"
1267 by (metis gr0I mult_is_0 prod_gcd_lcm_nat)
1270 "(m::int) ~= 0 \<Longrightarrow> n ~= 0 \<Longrightarrow> lcm m n > 0"
1271 apply (subst lcm_abs_int)
1272 apply (rule lcm_pos_nat [transferred])
1278 assumes "n > 0" and "m dvd n"
1280 using assms by (cases m) auto
1282 lemma lcm_least_nat:
1283 assumes "(m::nat) dvd k" and "n dvd k"
1284 shows "lcm m n dvd k"
1286 case 0 then show ?thesis by auto
1288 case (Suc _) then have pos_k: "k > 0" by auto
1289 from assms dvd_pos_nat [OF this] have pos_mn: "m > 0" "n > 0" by auto
1290 with gcd_zero_nat [of m n] have pos_gcd: "gcd m n > 0" by simp
1291 from assms obtain p where k_m: "k = m * p" using dvd_def by blast
1292 from assms obtain q where k_n: "k = n * q" using dvd_def by blast
1293 from pos_k k_m have pos_p: "p > 0" by auto
1294 from pos_k k_n have pos_q: "q > 0" by auto
1295 have "k * k * gcd q p = k * gcd (k * q) (k * p)"
1296 by (simp add: mult_ac gcd_mult_distrib_nat)
1297 also have "\<dots> = k * gcd (m * p * q) (n * q * p)"
1298 by (simp add: k_m [symmetric] k_n [symmetric])
1299 also have "\<dots> = k * p * q * gcd m n"
1300 by (simp add: mult_ac gcd_mult_distrib_nat)
1301 finally have "(m * p) * (n * q) * gcd q p = k * p * q * gcd m n"
1302 by (simp only: k_m [symmetric] k_n [symmetric])
1303 then have "p * q * m * n * gcd q p = p * q * k * gcd m n"
1304 by (simp add: mult_ac)
1305 with pos_p pos_q have "m * n * gcd q p = k * gcd m n"
1307 with prod_gcd_lcm_nat [of m n]
1308 have "lcm m n * gcd q p * gcd m n = k * gcd m n"
1309 by (simp add: mult_ac)
1310 with pos_gcd have "lcm m n * gcd q p = k" by auto
1311 then show ?thesis using dvd_def by auto
1314 lemma lcm_least_int:
1315 "(m::int) dvd k \<Longrightarrow> n dvd k \<Longrightarrow> lcm m n dvd k"
1316 apply (subst lcm_abs_int)
1317 apply (rule dvd_trans)
1318 apply (rule lcm_least_nat [transferred, of _ "abs k" _])
1322 lemma lcm_dvd1_nat: "(m::nat) dvd lcm m n"
1324 case 0 then show ?thesis by simp
1327 then have mpos: "m > 0" by simp
1330 case 0 then show ?thesis by simp
1333 then have npos: "n > 0" by simp
1334 have "gcd m n dvd n" by simp
1335 then obtain k where "n = gcd m n * k" using dvd_def by auto
1336 then have "m * n div gcd m n = m * (gcd m n * k) div gcd m n"
1337 by (simp add: mult_ac)
1338 also have "\<dots> = m * k" using mpos npos gcd_zero_nat by simp
1339 finally show ?thesis by (simp add: lcm_nat_def)
1343 lemma lcm_dvd1_int: "(m::int) dvd lcm m n"
1344 apply (subst lcm_abs_int)
1345 apply (rule dvd_trans)
1347 apply (rule lcm_dvd1_nat [transferred])
1351 lemma lcm_dvd2_nat: "(n::nat) dvd lcm m n"
1352 using lcm_dvd1_nat [of n m] by (simp only: lcm_nat_def mult.commute gcd_nat.commute)
1354 lemma lcm_dvd2_int: "(n::int) dvd lcm m n"
1355 using lcm_dvd1_int [of n m] by (simp only: lcm_int_def lcm_nat_def mult.commute gcd_nat.commute)
1357 lemma dvd_lcm_I1_nat[simp]: "(k::nat) dvd m \<Longrightarrow> k dvd lcm m n"
1358 by(metis lcm_dvd1_nat dvd_trans)
1360 lemma dvd_lcm_I2_nat[simp]: "(k::nat) dvd n \<Longrightarrow> k dvd lcm m n"
1361 by(metis lcm_dvd2_nat dvd_trans)
1363 lemma dvd_lcm_I1_int[simp]: "(i::int) dvd m \<Longrightarrow> i dvd lcm m n"
1364 by(metis lcm_dvd1_int dvd_trans)
1366 lemma dvd_lcm_I2_int[simp]: "(i::int) dvd n \<Longrightarrow> i dvd lcm m n"
1367 by(metis lcm_dvd2_int dvd_trans)
1369 lemma lcm_unique_nat: "(a::nat) dvd d \<and> b dvd d \<and>
1370 (\<forall>e. a dvd e \<and> b dvd e \<longrightarrow> d dvd e) \<longleftrightarrow> d = lcm a b"
1371 by (auto intro: dvd_antisym lcm_least_nat lcm_dvd1_nat lcm_dvd2_nat)
1373 lemma lcm_unique_int: "d >= 0 \<and> (a::int) dvd d \<and> b dvd d \<and>
1374 (\<forall>e. a dvd e \<and> b dvd e \<longrightarrow> d dvd e) \<longleftrightarrow> d = lcm a b"
1375 by (auto intro: dvd_antisym [transferred] lcm_least_int)
1377 interpretation lcm_nat: abel_semigroup "lcm :: nat \<Rightarrow> nat \<Rightarrow> nat"
1380 show "lcm (lcm n m) p = lcm n (lcm m p)"
1381 by (rule lcm_unique_nat [THEN iffD1]) (metis dvd.order_trans lcm_unique_nat)
1382 show "lcm m n = lcm n m"
1383 by (simp add: lcm_nat_def gcd_commute_nat field_simps)
1386 interpretation lcm_int: abel_semigroup "lcm :: int \<Rightarrow> int \<Rightarrow> int"
1389 show "lcm (lcm n m) p = lcm n (lcm m p)"
1390 by (rule lcm_unique_int [THEN iffD1]) (metis dvd_trans lcm_unique_int)
1391 show "lcm m n = lcm n m"
1392 by (simp add: lcm_int_def lcm_nat.commute)
1395 lemmas lcm_assoc_nat = lcm_nat.assoc
1396 lemmas lcm_commute_nat = lcm_nat.commute
1397 lemmas lcm_left_commute_nat = lcm_nat.left_commute
1398 lemmas lcm_assoc_int = lcm_int.assoc
1399 lemmas lcm_commute_int = lcm_int.commute
1400 lemmas lcm_left_commute_int = lcm_int.left_commute
1402 lemmas lcm_ac_nat = lcm_assoc_nat lcm_commute_nat lcm_left_commute_nat
1403 lemmas lcm_ac_int = lcm_assoc_int lcm_commute_int lcm_left_commute_int
1405 lemma lcm_proj2_if_dvd_nat [simp]: "(x::nat) dvd y \<Longrightarrow> lcm x y = y"
1407 apply (subst lcm_unique_nat [symmetric])
1411 lemma lcm_proj2_if_dvd_int [simp]: "(x::int) dvd y \<Longrightarrow> lcm x y = abs y"
1413 apply (subst lcm_unique_int [symmetric])
1417 lemma lcm_proj1_if_dvd_nat [simp]: "(x::nat) dvd y \<Longrightarrow> lcm y x = y"
1418 by (subst lcm_commute_nat, erule lcm_proj2_if_dvd_nat)
1420 lemma lcm_proj1_if_dvd_int [simp]: "(x::int) dvd y \<Longrightarrow> lcm y x = abs y"
1421 by (subst lcm_commute_int, erule lcm_proj2_if_dvd_int)
1423 lemma lcm_proj1_iff_nat[simp]: "lcm m n = (m::nat) \<longleftrightarrow> n dvd m"
1424 by (metis lcm_proj1_if_dvd_nat lcm_unique_nat)
1426 lemma lcm_proj2_iff_nat[simp]: "lcm m n = (n::nat) \<longleftrightarrow> m dvd n"
1427 by (metis lcm_proj2_if_dvd_nat lcm_unique_nat)
1429 lemma lcm_proj1_iff_int[simp]: "lcm m n = abs(m::int) \<longleftrightarrow> n dvd m"
1430 by (metis dvd_abs_iff lcm_proj1_if_dvd_int lcm_unique_int)
1432 lemma lcm_proj2_iff_int[simp]: "lcm m n = abs(n::int) \<longleftrightarrow> m dvd n"
1433 by (metis dvd_abs_iff lcm_proj2_if_dvd_int lcm_unique_int)
1435 lemma comp_fun_idem_gcd_nat: "comp_fun_idem (gcd :: nat\<Rightarrow>nat\<Rightarrow>nat)"
1436 proof qed (auto simp add: gcd_ac_nat)
1438 lemma comp_fun_idem_gcd_int: "comp_fun_idem (gcd :: int\<Rightarrow>int\<Rightarrow>int)"
1439 proof qed (auto simp add: gcd_ac_int)
1441 lemma comp_fun_idem_lcm_nat: "comp_fun_idem (lcm :: nat\<Rightarrow>nat\<Rightarrow>nat)"
1442 proof qed (auto simp add: lcm_ac_nat)
1444 lemma comp_fun_idem_lcm_int: "comp_fun_idem (lcm :: int\<Rightarrow>int\<Rightarrow>int)"
1445 proof qed (auto simp add: lcm_ac_int)
1448 (* FIXME introduce selimattice_bot/top and derive the following lemmas in there: *)
1450 lemma lcm_0_iff_nat[simp]: "lcm (m::nat) n = 0 \<longleftrightarrow> m=0 \<or> n=0"
1451 by (metis lcm_0_left_nat lcm_0_nat mult_is_0 prod_gcd_lcm_nat)
1453 lemma lcm_0_iff_int[simp]: "lcm (m::int) n = 0 \<longleftrightarrow> m=0 \<or> n=0"
1454 by (metis lcm_0_int lcm_0_left_int lcm_pos_int less_le)
1456 lemma lcm_1_iff_nat[simp]: "lcm (m::nat) n = 1 \<longleftrightarrow> m=1 \<and> n=1"
1457 by (metis gcd_1_nat lcm_unique_nat nat_mult_1 prod_gcd_lcm_nat)
1459 lemma lcm_1_iff_int[simp]: "lcm (m::int) n = 1 \<longleftrightarrow> (m=1 \<or> m = -1) \<and> (n=1 \<or> n = -1)"
1460 by (auto simp add: abs_mult_self trans [OF lcm_unique_int eq_commute, symmetric] zmult_eq_1_iff)
1463 subsection {* The complete divisibility lattice *}
1465 interpretation gcd_semilattice_nat: semilattice_inf gcd "op dvd" "(%m n::nat. m dvd n & ~ n dvd m)"
1467 case goal3 thus ?case by(metis gcd_unique_nat)
1470 interpretation lcm_semilattice_nat: semilattice_sup lcm "op dvd" "(%m n::nat. m dvd n & ~ n dvd m)"
1472 case goal3 thus ?case by(metis lcm_unique_nat)
1475 interpretation gcd_lcm_lattice_nat: lattice gcd "op dvd" "(%m n::nat. m dvd n & ~ n dvd m)" lcm ..
1477 text{* Lifting gcd and lcm to sets (Gcd/Lcm).
1478 Gcd is defined via Lcm to facilitate the proof that we have a complete lattice.
1482 fixes Gcd :: "'a set \<Rightarrow> 'a"
1483 fixes Lcm :: "'a set \<Rightarrow> 'a"
1485 instantiation nat :: Gcd
1489 "Lcm (M::nat set) = (if finite M then Finite_Set.fold lcm 1 M else 0)"
1492 "Gcd (M::nat set) = Lcm {d. \<forall>m\<in>M. d dvd m}"
1497 lemma dvd_Lcm_nat [simp]:
1498 fixes M :: "nat set" assumes "m \<in> M" shows "m dvd Lcm M"
1499 using lcm_semilattice_nat.sup_le_fold_sup[OF _ assms, of 1]
1500 by (simp add: Lcm_nat_def)
1502 lemma Lcm_dvd_nat [simp]:
1503 fixes M :: "nat set" assumes "\<forall>m\<in>M. m dvd n" shows "Lcm M dvd n"
1504 proof (cases "n = 0")
1505 assume "n \<noteq> 0"
1506 hence "finite {d. d dvd n}" by (rule finite_divisors_nat)
1507 moreover have "M \<subseteq> {d. d dvd n}" using assms by fast
1508 ultimately have "finite M" by (rule rev_finite_subset)
1510 using lcm_semilattice_nat.fold_sup_le_sup [OF _ assms, of 1]
1511 by (simp add: Lcm_nat_def)
1514 interpretation gcd_lcm_complete_lattice_nat:
1515 complete_lattice Gcd Lcm gcd "op dvd" "%m n::nat. m dvd n & ~ n dvd m" lcm 1 0
1517 case goal1 show ?case by simp
1519 case goal2 show ?case by simp
1521 case goal5 thus ?case by (rule dvd_Lcm_nat)
1523 case goal6 thus ?case by simp
1525 case goal3 thus ?case by (simp add: Gcd_nat_def)
1527 case goal4 thus ?case by (simp add: Gcd_nat_def)
1529 (* bh: This interpretation generates many lemmas about
1530 "complete_lattice.SUPR Lcm" and "complete_lattice.INFI Gcd".
1531 Should we define binder versions of LCM and GCD to correspond
1534 lemma Lcm_empty_nat: "Lcm {} = (1::nat)"
1535 by (fact gcd_lcm_complete_lattice_nat.Sup_empty) (* already simp *)
1537 lemma Gcd_empty_nat: "Gcd {} = (0::nat)"
1538 by (fact gcd_lcm_complete_lattice_nat.Inf_empty) (* already simp *)
1540 lemma Lcm_insert_nat [simp]:
1541 shows "Lcm (insert (n::nat) N) = lcm n (Lcm N)"
1542 by (fact gcd_lcm_complete_lattice_nat.Sup_insert)
1544 lemma Gcd_insert_nat [simp]:
1545 shows "Gcd (insert (n::nat) N) = gcd n (Gcd N)"
1546 by (fact gcd_lcm_complete_lattice_nat.Inf_insert)
1548 lemma Lcm0_iff[simp]: "finite (M::nat set) \<Longrightarrow> M \<noteq> {} \<Longrightarrow> Lcm M = 0 \<longleftrightarrow> 0 : M"
1549 by(induct rule:finite_ne_induct) auto
1551 lemma Lcm_eq_0[simp]: "finite (M::nat set) \<Longrightarrow> 0 : M \<Longrightarrow> Lcm M = 0"
1552 by (metis Lcm0_iff empty_iff)
1554 lemma Gcd_dvd_nat [simp]:
1555 fixes M :: "nat set"
1556 assumes "m \<in> M" shows "Gcd M dvd m"
1557 using assms by (fact gcd_lcm_complete_lattice_nat.Inf_lower)
1559 lemma dvd_Gcd_nat[simp]:
1560 fixes M :: "nat set"
1561 assumes "\<forall>m\<in>M. n dvd m" shows "n dvd Gcd M"
1562 using assms by (simp only: gcd_lcm_complete_lattice_nat.Inf_greatest)
1564 text{* Alternative characterizations of Gcd: *}
1566 lemma Gcd_eq_Max: "finite(M::nat set) \<Longrightarrow> M \<noteq> {} \<Longrightarrow> 0 \<notin> M \<Longrightarrow> Gcd M = Max(\<Inter>m\<in>M. {d. d dvd m})"
1569 apply (metis all_not_in_conv finite_divisors_nat finite_INT)
1571 apply (rule Max_le_iff[THEN iffD2])
1572 apply (metis all_not_in_conv finite_divisors_nat finite_INT)
1575 apply (metis Gcd_dvd_nat Max_in dvd_0_left dvd_Gcd_nat dvd_imp_le linorder_antisym_conv3 not_less0)
1578 lemma Gcd_remove0_nat: "finite M \<Longrightarrow> Gcd M = Gcd (M - {0::nat})"
1579 apply(induct pred:finite)
1581 apply(case_tac "x=0")
1583 apply(subgoal_tac "insert x F - {0} = insert x (F - {0})")
1588 lemma Lcm_in_lcm_closed_set_nat:
1589 "finite M \<Longrightarrow> M \<noteq> {} \<Longrightarrow> ALL m n :: nat. m:M \<longrightarrow> n:M \<longrightarrow> lcm m n : M \<Longrightarrow> Lcm M : M"
1590 apply(induct rule:finite_linorder_min_induct)
1593 apply(subgoal_tac "ALL m n :: nat. m:A \<longrightarrow> n:A \<longrightarrow> lcm m n : A")
1595 apply(case_tac "A={}")
1598 apply (metis lcm_pos_nat lcm_unique_nat linorder_neq_iff nat_dvd_not_less not_less0)
1601 lemma Lcm_eq_Max_nat:
1602 "finite M \<Longrightarrow> M \<noteq> {} \<Longrightarrow> 0 \<notin> M \<Longrightarrow> ALL m n :: nat. m:M \<longrightarrow> n:M \<longrightarrow> lcm m n : M \<Longrightarrow> Lcm M = Max M"
1604 apply(rule Max_ge, assumption)
1605 apply(erule (2) Lcm_in_lcm_closed_set_nat)
1607 apply (metis Lcm0_iff dvd_Lcm_nat dvd_imp_le neq0_conv)
1610 lemma Lcm_set_nat [code_unfold]:
1611 "Lcm (set ns) = fold lcm ns (1::nat)"
1612 by (fact gcd_lcm_complete_lattice_nat.Sup_set_fold)
1614 lemma Gcd_set_nat [code_unfold]:
1615 "Gcd (set ns) = fold gcd ns (0::nat)"
1616 by (fact gcd_lcm_complete_lattice_nat.Inf_set_fold)
1618 lemma mult_inj_if_coprime_nat:
1619 "inj_on f A \<Longrightarrow> inj_on g B \<Longrightarrow> ALL a:A. ALL b:B. coprime (f a) (g b)
1620 \<Longrightarrow> inj_on (%(a,b). f a * g b::nat) (A \<times> B)"
1621 apply(auto simp add:inj_on_def)
1622 apply (metis coprime_dvd_mult_iff_nat dvd.neq_le_trans dvd_triv_left)
1623 apply (metis gcd_semilattice_nat.inf_commute coprime_dvd_mult_iff_nat
1624 dvd.neq_le_trans dvd_triv_right mult_commute)
1629 lemma gcd_eq_nitpick_gcd [nitpick_unfold]: "gcd x y = Nitpick.nat_gcd x y"
1630 by (induct x y rule: nat_gcd.induct)
1631 (simp add: gcd_nat.simps Nitpick.nat_gcd.simps)
1633 lemma lcm_eq_nitpick_lcm [nitpick_unfold]: "lcm x y = Nitpick.nat_lcm x y"
1634 by (simp only: lcm_nat_def Nitpick.nat_lcm_def gcd_eq_nitpick_gcd)
1636 subsubsection {* Setwise gcd and lcm for integers *}
1638 instantiation int :: Gcd
1642 "Lcm M = int (Lcm (nat ` abs ` M))"
1645 "Gcd M = int (Gcd (nat ` abs ` M))"
1650 lemma Lcm_empty_int [simp]: "Lcm {} = (1::int)"
1651 by (simp add: Lcm_int_def)
1653 lemma Gcd_empty_int [simp]: "Gcd {} = (0::int)"
1654 by (simp add: Gcd_int_def)
1656 lemma Lcm_insert_int [simp]:
1657 shows "Lcm (insert (n::int) N) = lcm n (Lcm N)"
1658 by (simp add: Lcm_int_def lcm_int_def)
1660 lemma Gcd_insert_int [simp]:
1661 shows "Gcd (insert (n::int) N) = gcd n (Gcd N)"
1662 by (simp add: Gcd_int_def gcd_int_def)
1664 lemma dvd_int_iff: "x dvd y \<longleftrightarrow> nat (abs x) dvd nat (abs y)"
1665 by (simp add: zdvd_int)
1667 lemma dvd_Lcm_int [simp]:
1668 fixes M :: "int set" assumes "m \<in> M" shows "m dvd Lcm M"
1669 using assms by (simp add: Lcm_int_def dvd_int_iff)
1671 lemma Lcm_dvd_int [simp]:
1672 fixes M :: "int set"
1673 assumes "\<forall>m\<in>M. m dvd n" shows "Lcm M dvd n"
1674 using assms by (simp add: Lcm_int_def dvd_int_iff)
1676 lemma Gcd_dvd_int [simp]:
1677 fixes M :: "int set"
1678 assumes "m \<in> M" shows "Gcd M dvd m"
1679 using assms by (simp add: Gcd_int_def dvd_int_iff)
1681 lemma dvd_Gcd_int[simp]:
1682 fixes M :: "int set"
1683 assumes "\<forall>m\<in>M. n dvd m" shows "n dvd Gcd M"
1684 using assms by (simp add: Gcd_int_def dvd_int_iff)
1686 lemma Lcm_set_int [code_unfold]:
1687 "Lcm (set xs) = foldl lcm (1::int) xs"
1688 by (induct xs rule: rev_induct, simp_all add: lcm_commute_int)
1690 lemma Gcd_set_int [code_unfold]:
1691 "Gcd (set xs) = foldl gcd (0::int) xs"
1692 by (induct xs rule: rev_induct, simp_all add: gcd_commute_int)