src/HOL/GCD.thy
changeset 60686 ea5bc46c11e6
parent 60597 2da9b632069b
child 60687 33dbbcb6a8a3
equal deleted inserted replaced
60685:cb21b7022b00 60686:ea5bc46c11e6
    29 
    29 
    30 theory GCD
    30 theory GCD
    31 imports Main
    31 imports Main
    32 begin
    32 begin
    33 
    33 
       
    34 context semidom_divide
       
    35 begin
       
    36 
       
    37 lemma divide_1 [simp]:
       
    38   "a div 1 = a"
       
    39   using nonzero_mult_divide_cancel_left [of 1 a] by simp
       
    40 
       
    41 lemma dvd_mult_cancel_left [simp]:
       
    42   assumes "a \<noteq> 0"
       
    43   shows "a * b dvd a * c \<longleftrightarrow> b dvd c" (is "?P \<longleftrightarrow> ?Q")
       
    44 proof
       
    45   assume ?P then obtain d where "a * c = a * b * d" ..
       
    46   with assms have "c = b * d" by (simp add: ac_simps)
       
    47   then show ?Q ..
       
    48 next
       
    49   assume ?Q then obtain d where "c = b * d" .. 
       
    50   then have "a * c = a * b * d" by (simp add: ac_simps)
       
    51   then show ?P ..
       
    52 qed
       
    53   
       
    54 lemma dvd_mult_cancel_right [simp]:
       
    55   assumes "a \<noteq> 0"
       
    56   shows "b * a dvd c * a \<longleftrightarrow> b dvd c" (is "?P \<longleftrightarrow> ?Q")
       
    57 using dvd_mult_cancel_left [of a b c] assms by (simp add: ac_simps)
       
    58   
       
    59 lemma div_dvd_iff_mult:
       
    60   assumes "b \<noteq> 0" and "b dvd a"
       
    61   shows "a div b dvd c \<longleftrightarrow> a dvd c * b"
       
    62 proof -
       
    63   from \<open>b dvd a\<close> obtain d where "a = b * d" ..
       
    64   with \<open>b \<noteq> 0\<close> show ?thesis by (simp add: ac_simps)
       
    65 qed
       
    66 
       
    67 lemma dvd_div_iff_mult:
       
    68   assumes "c \<noteq> 0" and "c dvd b"
       
    69   shows "a dvd b div c \<longleftrightarrow> a * c dvd b"
       
    70 proof -
       
    71   from \<open>c dvd b\<close> obtain d where "b = c * d" ..
       
    72   with \<open>c \<noteq> 0\<close> show ?thesis by (simp add: mult.commute [of a])
       
    73 qed
       
    74 
       
    75 end
       
    76 
       
    77 context algebraic_semidom
       
    78 begin
       
    79 
       
    80 lemma associated_1 [simp]:
       
    81   "associated 1 a \<longleftrightarrow> is_unit a"
       
    82   "associated a 1 \<longleftrightarrow> is_unit a"
       
    83   by (auto simp add: associated_def)
       
    84 
       
    85 end
       
    86 
    34 declare One_nat_def [simp del]
    87 declare One_nat_def [simp del]
    35 
    88 
    36 subsection {* GCD and LCM definitions *}
    89 subsection {* GCD and LCM definitions *}
    37 
    90 
    38 class gcd = zero + one + dvd +
    91 class gcd = zero + one + dvd +
    39   fixes gcd :: "'a \<Rightarrow> 'a \<Rightarrow> 'a"
    92   fixes gcd :: "'a \<Rightarrow> 'a \<Rightarrow> 'a"
    40     and lcm :: "'a \<Rightarrow> 'a \<Rightarrow> 'a"
    93     and lcm :: "'a \<Rightarrow> 'a \<Rightarrow> 'a"
    41 begin
    94 begin
    42 
    95 
    43 abbreviation
    96 abbreviation coprime :: "'a \<Rightarrow> 'a \<Rightarrow> bool"
    44   coprime :: "'a \<Rightarrow> 'a \<Rightarrow> bool"
    97   where "coprime x y \<equiv> gcd x y = 1"
    45 where
       
    46   "coprime x y == (gcd x y = 1)"
       
    47 
    98 
    48 end
    99 end
    49 
   100 
    50 class semiring_gcd = comm_semiring_1 + gcd +
   101 class Gcd = gcd +
       
   102   fixes Gcd :: "'a set \<Rightarrow> 'a"
       
   103     and Lcm :: "'a set \<Rightarrow> 'a"
       
   104 
       
   105 class semiring_gcd = normalization_semidom + gcd +
    51   assumes gcd_dvd1 [iff]: "gcd a b dvd a"
   106   assumes gcd_dvd1 [iff]: "gcd a b dvd a"
    52     and gcd_dvd2 [iff]: "gcd a b dvd b"
   107     and gcd_dvd2 [iff]: "gcd a b dvd b"
    53     and gcd_greatest: "c dvd a \<Longrightarrow> c dvd b \<Longrightarrow> c dvd gcd a b"
   108     and gcd_greatest: "c dvd a \<Longrightarrow> c dvd b \<Longrightarrow> c dvd gcd a b"
       
   109     and normalize_gcd [simp]: "normalize (gcd a b) = gcd a b"
       
   110     and lcm_gcd: "lcm a b = normalize (a * b) div gcd a b"
       
   111 begin    
       
   112 
       
   113 lemma gcd_greatest_iff [iff]:
       
   114   "a dvd gcd b c \<longleftrightarrow> a dvd b \<and> a dvd c"
       
   115   by (blast intro!: gcd_greatest intro: dvd_trans)
       
   116 
       
   117 lemma gcd_0_left [simp]:
       
   118   "gcd 0 a = normalize a"
       
   119 proof (rule associated_eqI)
       
   120   show "associated (gcd 0 a) (normalize a)"
       
   121     by (auto intro!: associatedI gcd_greatest)
       
   122   show "unit_factor (gcd 0 a) = 1" if "gcd 0 a \<noteq> 0"
       
   123   proof -
       
   124     from that have "unit_factor (normalize (gcd 0 a)) = 1"
       
   125       by (rule unit_factor_normalize)
       
   126     then show ?thesis by simp
       
   127   qed
       
   128 qed simp
       
   129 
       
   130 lemma gcd_0_right [simp]:
       
   131   "gcd a 0 = normalize a"
       
   132 proof (rule associated_eqI)
       
   133   show "associated (gcd a 0) (normalize a)"
       
   134     by (auto intro!: associatedI gcd_greatest)
       
   135   show "unit_factor (gcd a 0) = 1" if "gcd a 0 \<noteq> 0"
       
   136   proof -
       
   137     from that have "unit_factor (normalize (gcd a 0)) = 1"
       
   138       by (rule unit_factor_normalize)
       
   139     then show ?thesis by simp
       
   140   qed
       
   141 qed simp
       
   142   
       
   143 lemma gcd_eq_0_iff [simp]:
       
   144   "gcd a b = 0 \<longleftrightarrow> a = 0 \<and> b = 0" (is "?P \<longleftrightarrow> ?Q")
       
   145 proof
       
   146   assume ?P then have "0 dvd gcd a b" by simp
       
   147   then have "0 dvd a" and "0 dvd b" by (blast intro: dvd_trans)+
       
   148   then show ?Q by simp
       
   149 next
       
   150   assume ?Q then show ?P by simp
       
   151 qed
       
   152 
       
   153 lemma unit_factor_gcd:
       
   154   "unit_factor (gcd a b) = (if a = 0 \<and> b = 0 then 0 else 1)"
       
   155 proof (cases "gcd a b = 0")
       
   156   case True then show ?thesis by simp
       
   157 next
       
   158   case False
       
   159   have "unit_factor (gcd a b) * normalize (gcd a b) = gcd a b"
       
   160     by (rule unit_factor_mult_normalize)
       
   161   then have "unit_factor (gcd a b) * gcd a b = gcd a b"
       
   162     by simp
       
   163   then have "unit_factor (gcd a b) * gcd a b div gcd a b = gcd a b div gcd a b"
       
   164     by simp
       
   165   with False show ?thesis by simp
       
   166 qed
       
   167 
       
   168 sublocale gcd!: abel_semigroup gcd
       
   169 proof
       
   170   fix a b c
       
   171   show "gcd a b = gcd b a"
       
   172     by (rule associated_eqI) (auto intro: associatedI gcd_greatest simp add: unit_factor_gcd)
       
   173   from gcd_dvd1 have "gcd (gcd a b) c dvd a"
       
   174     by (rule dvd_trans) simp
       
   175   moreover from gcd_dvd1 have "gcd (gcd a b) c dvd b"
       
   176     by (rule dvd_trans) simp
       
   177   ultimately have P1: "gcd (gcd a b) c dvd gcd a (gcd b c)"
       
   178     by (auto intro!: gcd_greatest)
       
   179   from gcd_dvd2 have "gcd a (gcd b c) dvd b"
       
   180     by (rule dvd_trans) simp
       
   181   moreover from gcd_dvd2 have "gcd a (gcd b c) dvd c"
       
   182     by (rule dvd_trans) simp
       
   183   ultimately have P2: "gcd a (gcd b c) dvd gcd (gcd a b) c"
       
   184     by (auto intro!: gcd_greatest)
       
   185   from P1 P2 have "associated (gcd (gcd a b) c) (gcd a (gcd b c))"
       
   186     by (rule associatedI)
       
   187   then show "gcd (gcd a b) c = gcd a (gcd b c)"
       
   188     by (rule associated_eqI) (simp_all add: unit_factor_gcd)
       
   189 qed
       
   190 
       
   191 lemma gcd_self [simp]:
       
   192   "gcd a a = normalize a"
       
   193 proof -
       
   194   have "a dvd gcd a a"
       
   195     by (rule gcd_greatest) simp_all
       
   196   then have "associated (gcd a a) (normalize a)"
       
   197     by (auto intro: associatedI)
       
   198   then show ?thesis
       
   199     by (auto intro: associated_eqI simp add: unit_factor_gcd)
       
   200 qed
       
   201     
       
   202 lemma coprime_1_left [simp]:
       
   203   "coprime 1 a"
       
   204   by (rule associated_eqI) (simp_all add: unit_factor_gcd)
       
   205 
       
   206 lemma coprime_1_right [simp]:
       
   207   "coprime a 1"
       
   208   using coprime_1_left [of a] by (simp add: ac_simps)
       
   209 
       
   210 lemma gcd_mult_left:
       
   211   "gcd (c * a) (c * b) = normalize c * gcd a b"
       
   212 proof (cases "c = 0")
       
   213   case True then show ?thesis by simp
       
   214 next
       
   215   case False
       
   216   then have "c * gcd a b dvd gcd (c * a) (c * b)"
       
   217     by (auto intro: gcd_greatest)
       
   218   moreover from calculation False have "gcd (c * a) (c * b) dvd c * gcd a b"
       
   219     by (metis div_dvd_iff_mult dvd_mult_left gcd_dvd1 gcd_dvd2 gcd_greatest mult_commute)
       
   220   ultimately have "normalize (gcd (c * a) (c * b)) = normalize (c * gcd a b)"
       
   221     by - (rule associated_eqI, auto intro: associated_eqI associatedI simp add: unit_factor_gcd)
       
   222   then show ?thesis by (simp add: normalize_mult)
       
   223 qed
       
   224 
       
   225 lemma gcd_mult_right:
       
   226   "gcd (a * c) (b * c) = gcd b a * normalize c"
       
   227   using gcd_mult_left [of c a b] by (simp add: ac_simps)
       
   228 
       
   229 lemma mult_gcd_left:
       
   230   "c * gcd a b = unit_factor c * gcd (c * a) (c * b)"
       
   231   by (simp add: gcd_mult_left mult.assoc [symmetric])
       
   232 
       
   233 lemma mult_gcd_right:
       
   234   "gcd a b * c = gcd (a * c) (b * c) * unit_factor c"
       
   235   using mult_gcd_left [of c a b] by (simp add: ac_simps)
       
   236 
       
   237 lemma lcm_dvd1 [iff]:
       
   238   "a dvd lcm a b"
       
   239 proof -
       
   240   have "normalize (a * b) div gcd a b = normalize a * (normalize b div gcd a b)"
       
   241     by (simp add: lcm_gcd normalize_mult div_mult_swap)
       
   242   then show ?thesis
       
   243     by (simp add: lcm_gcd)
       
   244 qed
       
   245   
       
   246 lemma lcm_dvd2 [iff]:
       
   247   "b dvd lcm a b"
       
   248 proof -
       
   249   have "normalize (a * b) div gcd a b = normalize b * (normalize a div gcd a b)"
       
   250     by (simp add: lcm_gcd normalize_mult div_mult_swap ac_simps)
       
   251   then show ?thesis
       
   252     by (simp add: lcm_gcd)
       
   253 qed
       
   254 
       
   255 lemma lcm_least:
       
   256   assumes "a dvd c" and "b dvd c"
       
   257   shows "lcm a b dvd c"
       
   258 proof (cases "c = 0")
       
   259   case True then show ?thesis by simp
       
   260 next
       
   261   case False then have U: "is_unit (unit_factor c)" by simp
       
   262   show ?thesis
       
   263   proof (cases "gcd a b = 0")
       
   264     case True with assms show ?thesis by simp
       
   265   next
       
   266     case False then have "a \<noteq> 0 \<or> b \<noteq> 0" by simp
       
   267     with \<open>c \<noteq> 0\<close> assms have "a * b dvd a * c" "a * b dvd c * b"
       
   268       by (simp_all add: mult_dvd_mono)
       
   269     then have "normalize (a * b) dvd gcd (a * c) (b * c)"
       
   270       by (auto intro: gcd_greatest simp add: ac_simps)
       
   271     then have "normalize (a * b) dvd gcd (a * c) (b * c) * unit_factor c"
       
   272       using U by (simp add: dvd_mult_unit_iff)
       
   273     then have "normalize (a * b) dvd gcd a b * c"
       
   274       by (simp add: mult_gcd_right [of a b c])
       
   275     then have "normalize (a * b) div gcd a b dvd c"
       
   276       using False by (simp add: div_dvd_iff_mult ac_simps)
       
   277     then show ?thesis by (simp add: lcm_gcd)
       
   278   qed
       
   279 qed
       
   280 
       
   281 lemma lcm_least_iff [iff]:
       
   282   "lcm a b dvd c \<longleftrightarrow> a dvd c \<and> b dvd c"
       
   283   by (blast intro!: lcm_least intro: dvd_trans)
       
   284 
       
   285 lemma normalize_lcm [simp]:
       
   286   "normalize (lcm a b) = lcm a b"
       
   287   by (simp add: lcm_gcd dvd_normalize_div)
       
   288 
       
   289 lemma lcm_0_left [simp]:
       
   290   "lcm 0 a = 0"
       
   291   by (simp add: lcm_gcd)
       
   292   
       
   293 lemma lcm_0_right [simp]:
       
   294   "lcm a 0 = 0"
       
   295   by (simp add: lcm_gcd)
       
   296 
       
   297 lemma lcm_eq_0_iff:
       
   298   "lcm a b = 0 \<longleftrightarrow> a = 0 \<or> b = 0" (is "?P \<longleftrightarrow> ?Q")
       
   299 proof
       
   300   assume ?P then have "0 dvd lcm a b" by simp
       
   301   then have "0 dvd normalize (a * b) div gcd a b"
       
   302     by (simp add: lcm_gcd)
       
   303   then have "0 * gcd a b dvd normalize (a * b)"
       
   304     using dvd_div_iff_mult [of "gcd a b" _ 0] by (cases "gcd a b = 0") simp_all
       
   305   then have "normalize (a * b) = 0"
       
   306     by simp
       
   307   then show ?Q by simp
       
   308 next
       
   309   assume ?Q then show ?P by auto
       
   310 qed
       
   311 
       
   312 lemma unit_factor_lcm :
       
   313   "unit_factor (lcm a b) = (if a = 0 \<or> b = 0 then 0 else 1)"
       
   314   by (simp add: unit_factor_gcd dvd_unit_factor_div lcm_gcd)
       
   315 
       
   316 sublocale lcm!: abel_semigroup lcm
       
   317 proof
       
   318   fix a b c
       
   319   show "lcm a b = lcm b a"
       
   320     by (simp add: lcm_gcd ac_simps normalize_mult dvd_normalize_div)
       
   321   have "associated (lcm (lcm a b) c) (lcm a (lcm b c))"
       
   322     by (auto intro!: associatedI lcm_least
       
   323       dvd_trans [of b "lcm b c" "lcm a (lcm b c)"]
       
   324       dvd_trans [of c "lcm b c" "lcm a (lcm b c)"]
       
   325       dvd_trans [of a "lcm a b" "lcm (lcm a b) c"]
       
   326       dvd_trans [of b "lcm a b" "lcm (lcm a b) c"])
       
   327   then show "lcm (lcm a b) c = lcm a (lcm b c)"
       
   328     by (rule associated_eqI) (simp_all add: unit_factor_lcm lcm_eq_0_iff)
       
   329 qed
       
   330 
       
   331 lemma lcm_self [simp]:
       
   332   "lcm a a = normalize a"
       
   333 proof -
       
   334   have "lcm a a dvd a"
       
   335     by (rule lcm_least) simp_all
       
   336   then have "associated (lcm a a) (normalize a)"
       
   337     by (auto intro: associatedI)
       
   338   then show ?thesis
       
   339     by (rule associated_eqI) (auto simp add: unit_factor_lcm)
       
   340 qed
       
   341 
       
   342 lemma gcd_mult_lcm [simp]:
       
   343   "gcd a b * lcm a b = normalize a * normalize b"
       
   344   by (simp add: lcm_gcd normalize_mult)
       
   345 
       
   346 lemma lcm_mult_gcd [simp]:
       
   347   "lcm a b * gcd a b = normalize a * normalize b"
       
   348   using gcd_mult_lcm [of a b] by (simp add: ac_simps) 
       
   349 
       
   350 lemma gcd_lcm:
       
   351   assumes "a \<noteq> 0" and "b \<noteq> 0"
       
   352   shows "gcd a b = normalize (a * b) div lcm a b"
       
   353 proof -
       
   354   from assms have "lcm a b \<noteq> 0"
       
   355     by (simp add: lcm_eq_0_iff)
       
   356   have "gcd a b * lcm a b = normalize a * normalize b" by simp
       
   357   then have "gcd a b * lcm a b div lcm a b = normalize (a * b) div lcm a b"
       
   358     by (simp_all add: normalize_mult)
       
   359   with \<open>lcm a b \<noteq> 0\<close> show ?thesis
       
   360     using nonzero_mult_divide_cancel_right [of "lcm a b" "gcd a b"] by simp
       
   361 qed
       
   362 
       
   363 lemma lcm_1_left [simp]:
       
   364   "lcm 1 a = normalize a"
       
   365   by (simp add: lcm_gcd)
       
   366 
       
   367 lemma lcm_1_right [simp]:
       
   368   "lcm a 1 = normalize a"
       
   369   by (simp add: lcm_gcd)
       
   370   
       
   371 lemma lcm_mult_left:
       
   372   "lcm (c * a) (c * b) = normalize c * lcm a b"
       
   373   by (cases "c = 0")
       
   374     (simp_all add: gcd_mult_right lcm_gcd div_mult_swap normalize_mult ac_simps,
       
   375       simp add: dvd_div_mult2_eq mult.left_commute [of "normalize c", symmetric])
       
   376 
       
   377 lemma lcm_mult_right:
       
   378   "lcm (a * c) (b * c) = lcm b a * normalize c"
       
   379   using lcm_mult_left [of c a b] by (simp add: ac_simps)
       
   380 
       
   381 lemma mult_lcm_left:
       
   382   "c * lcm a b = unit_factor c * lcm (c * a) (c * b)"
       
   383   by (simp add: lcm_mult_left mult.assoc [symmetric])
       
   384 
       
   385 lemma mult_lcm_right:
       
   386   "lcm a b * c = lcm (a * c) (b * c) * unit_factor c"
       
   387   using mult_lcm_left [of c a b] by (simp add: ac_simps)
       
   388   
       
   389 end
       
   390 
       
   391 class semiring_Gcd = semiring_gcd + Gcd +
       
   392   assumes Gcd_dvd: "a \<in> A \<Longrightarrow> Gcd A dvd a"
       
   393     and Gcd_greatest: "(\<And>b. b \<in> A \<Longrightarrow> a dvd b) \<Longrightarrow> a dvd Gcd A"
       
   394     and normalize_Gcd [simp]: "normalize (Gcd A) = Gcd A"
       
   395 begin
       
   396 
       
   397 lemma Gcd_empty [simp]:
       
   398   "Gcd {} = 0"
       
   399   by (rule dvd_0_left, rule Gcd_greatest) simp
       
   400 
       
   401 lemma Gcd_0_iff [simp]:
       
   402   "Gcd A = 0 \<longleftrightarrow> (\<forall>a\<in>A. a = 0)" (is "?P \<longleftrightarrow> ?Q")
       
   403 proof
       
   404   assume ?P
       
   405   show ?Q
       
   406   proof
       
   407     fix a
       
   408     assume "a \<in> A"
       
   409     then have "Gcd A dvd a" by (rule Gcd_dvd)
       
   410     with \<open>?P\<close> show "a = 0" by simp
       
   411   qed
       
   412 next
       
   413   assume ?Q
       
   414   have "0 dvd Gcd A"
       
   415   proof (rule Gcd_greatest)
       
   416     fix a
       
   417     assume "a \<in> A"
       
   418     with \<open>?Q\<close> have "a = 0" by simp
       
   419     then show "0 dvd a" by simp
       
   420   qed
       
   421   then show ?P by simp
       
   422 qed
       
   423 
       
   424 lemma unit_factor_Gcd:
       
   425   "unit_factor (Gcd A) = (if \<forall>a\<in>A. a = 0 then 0 else 1)"
       
   426 proof (cases "Gcd A = 0")
       
   427   case True then show ?thesis by simp
       
   428 next
       
   429   case False
       
   430   from unit_factor_mult_normalize
       
   431   have "unit_factor (Gcd A) * normalize (Gcd A) = Gcd A" .
       
   432   then have "unit_factor (Gcd A) * Gcd A = Gcd A" by simp
       
   433   then have "unit_factor (Gcd A) * Gcd A div Gcd A = Gcd A div Gcd A" by simp
       
   434   with False have "unit_factor (Gcd A) = 1" by simp
       
   435   with False show ?thesis by simp
       
   436 qed
       
   437 
       
   438 lemma Gcd_UNIV [simp]:
       
   439   "Gcd UNIV = 1"
       
   440   by (rule associated_eqI) (auto intro: Gcd_dvd simp add: unit_factor_Gcd)
       
   441 
       
   442 lemma Gcd_eq_1_I:
       
   443   assumes "is_unit a" and "a \<in> A"
       
   444   shows "Gcd A = 1"
       
   445 proof -
       
   446   from assms have "is_unit (Gcd A)"
       
   447     by (blast intro: Gcd_dvd dvd_unit_imp_unit)
       
   448   then have "normalize (Gcd A) = 1"
       
   449     by (rule is_unit_normalize)
       
   450   then show ?thesis
       
   451     by simp
       
   452 qed
       
   453 
       
   454 lemma Gcd_insert [simp]:
       
   455   "Gcd (insert a A) = gcd a (Gcd A)"
       
   456 proof -
       
   457   have "Gcd (insert a A) dvd gcd a (Gcd A)"
       
   458     by (auto intro: Gcd_dvd Gcd_greatest)
       
   459   moreover have "gcd a (Gcd A) dvd Gcd (insert a A)"
       
   460   proof (rule Gcd_greatest)
       
   461     fix b
       
   462     assume "b \<in> insert a A"
       
   463     then show "gcd a (Gcd A) dvd b"
       
   464     proof
       
   465       assume "b = a" then show ?thesis by simp
       
   466     next
       
   467       assume "b \<in> A"
       
   468       then have "Gcd A dvd b" by (rule Gcd_dvd)
       
   469       moreover have "gcd a (Gcd A) dvd Gcd A" by simp
       
   470       ultimately show ?thesis by (blast intro: dvd_trans)
       
   471     qed
       
   472   qed
       
   473   ultimately have "associated (Gcd (insert a A)) (gcd a (Gcd A))"
       
   474     by (rule associatedI)
       
   475   then show ?thesis
       
   476     by (rule associated_eqI) (simp_all add: unit_factor_gcd unit_factor_Gcd)
       
   477 qed
       
   478 
       
   479 lemma dvd_Gcd: -- \<open>FIXME remove\<close>
       
   480   "\<forall>b\<in>A. a dvd b \<Longrightarrow> a dvd Gcd A"
       
   481   by (blast intro: Gcd_greatest)
       
   482 
       
   483 lemma Gcd_set [code_unfold]:
       
   484   "Gcd (set as) = foldr gcd as 0"
       
   485   by (induct as) simp_all
       
   486 
       
   487 end  
       
   488 
       
   489 class semiring_Lcm = semiring_Gcd +
       
   490   assumes Lcm_Gcd: "Lcm A = Gcd {b. \<forall>a\<in>A. a dvd b}"
       
   491 begin
       
   492 
       
   493 lemma dvd_Lcm:
       
   494   assumes "a \<in> A"
       
   495   shows "a dvd Lcm A"
       
   496   using assms by (auto intro: Gcd_greatest simp add: Lcm_Gcd)
       
   497 
       
   498 lemma Gcd_image_normalize [simp]:
       
   499   "Gcd (normalize ` A) = Gcd A"
       
   500 proof -
       
   501   have "Gcd (normalize ` A) dvd a" if "a \<in> A" for a
       
   502   proof -
       
   503     from that obtain B where "A = insert a B" by blast
       
   504     moreover have " gcd (normalize a) (Gcd (normalize ` B)) dvd normalize a"
       
   505       by (rule gcd_dvd1)
       
   506     ultimately show "Gcd (normalize ` A) dvd a"
       
   507       by simp
       
   508   qed
       
   509   then have "associated (Gcd (normalize ` A)) (Gcd A)"
       
   510     by (auto intro!: associatedI Gcd_greatest intro: Gcd_dvd)
       
   511   then show ?thesis
       
   512     by (rule associated_eqI) (simp_all add: unit_factor_Gcd)
       
   513 qed
       
   514 
       
   515 lemma Lcm_least:
       
   516   assumes "\<And>b. b \<in> A \<Longrightarrow> b dvd a"
       
   517   shows "Lcm A dvd a"
       
   518   using assms by (auto intro: Gcd_dvd simp add: Lcm_Gcd)
       
   519 
       
   520 lemma normalize_Lcm [simp]:
       
   521   "normalize (Lcm A) = Lcm A"
       
   522   by (simp add: Lcm_Gcd)
       
   523 
       
   524 lemma unit_factor_Lcm:
       
   525   "unit_factor (Lcm A) = (if Lcm A = 0 then 0 else 1)"
       
   526 proof (cases "Lcm A = 0")
       
   527   case True then show ?thesis by simp
       
   528 next
       
   529   case False
       
   530   with unit_factor_normalize have "unit_factor (normalize (Lcm A)) = 1"
       
   531     by blast
       
   532   with False show ?thesis
       
   533     by simp
       
   534 qed
       
   535   
       
   536 lemma Lcm_empty [simp]:
       
   537   "Lcm {} = 1"
       
   538   by (simp add: Lcm_Gcd)
       
   539 
       
   540 lemma Lcm_1_iff [simp]:
       
   541   "Lcm A = 1 \<longleftrightarrow> (\<forall>a\<in>A. is_unit a)" (is "?P \<longleftrightarrow> ?Q")
       
   542 proof
       
   543   assume ?P
       
   544   show ?Q
       
   545   proof
       
   546     fix a
       
   547     assume "a \<in> A"
       
   548     then have "a dvd Lcm A"
       
   549       by (rule dvd_Lcm)
       
   550     with \<open>?P\<close> show "is_unit a"
       
   551       by simp
       
   552   qed
       
   553 next
       
   554   assume ?Q
       
   555   then have "is_unit (Lcm A)"
       
   556     by (blast intro: Lcm_least)
       
   557   then have "normalize (Lcm A) = 1"
       
   558     by (rule is_unit_normalize)
       
   559   then show ?P
       
   560     by simp
       
   561 qed
       
   562 
       
   563 lemma Lcm_UNIV [simp]:
       
   564   "Lcm UNIV = 0"
       
   565 proof -
       
   566   have "0 dvd Lcm UNIV"
       
   567     by (rule dvd_Lcm) simp
       
   568   then show ?thesis
       
   569     by simp
       
   570 qed
       
   571 
       
   572 lemma Lcm_eq_0_I:
       
   573   assumes "0 \<in> A"
       
   574   shows "Lcm A = 0"
       
   575 proof -
       
   576   from assms have "0 dvd Lcm A"
       
   577     by (rule dvd_Lcm)
       
   578   then show ?thesis
       
   579     by simp
       
   580 qed
       
   581 
       
   582 lemma Gcd_Lcm:
       
   583   "Gcd A = Lcm {b. \<forall>a\<in>A. b dvd a}"
       
   584   by (rule associated_eqI) (auto intro: associatedI Gcd_dvd dvd_Lcm Gcd_greatest Lcm_least
       
   585     simp add: unit_factor_Gcd unit_factor_Lcm)
       
   586 
       
   587 lemma Lcm_insert [simp]:
       
   588   "Lcm (insert a A) = lcm a (Lcm A)"
       
   589 proof (rule sym)
       
   590   have "lcm a (Lcm A) dvd Lcm (insert a A)"
       
   591     by (auto intro: dvd_Lcm Lcm_least)
       
   592   moreover have "Lcm (insert a A) dvd lcm a (Lcm A)"
       
   593   proof (rule Lcm_least)
       
   594     fix b
       
   595     assume "b \<in> insert a A"
       
   596     then show "b dvd lcm a (Lcm A)"
       
   597     proof
       
   598       assume "b = a" then show ?thesis by simp
       
   599     next
       
   600       assume "b \<in> A"
       
   601       then have "b dvd Lcm A" by (rule dvd_Lcm)
       
   602       moreover have "Lcm A dvd lcm a (Lcm A)" by simp
       
   603       ultimately show ?thesis by (blast intro: dvd_trans)
       
   604     qed
       
   605   qed
       
   606   ultimately have "associated (lcm a (Lcm A)) (Lcm (insert a A))"
       
   607     by (rule associatedI)
       
   608   then show "lcm a (Lcm A) = Lcm (insert a A)"
       
   609     by (rule associated_eqI) (simp_all add: unit_factor_lcm unit_factor_Lcm lcm_eq_0_iff)
       
   610 qed
       
   611   
       
   612 lemma Lcm_set [code_unfold]:
       
   613   "Lcm (set as) = foldr lcm as 1"
       
   614   by (induct as) simp_all
       
   615   
       
   616 end
    54 
   617 
    55 class ring_gcd = comm_ring_1 + semiring_gcd
   618 class ring_gcd = comm_ring_1 + semiring_gcd
    56 
   619 
    57 instantiation nat :: gcd
   620 instantiation nat :: gcd
    58 begin
   621 begin
   263 next
   826 next
   264   fix m n k :: nat
   827   fix m n k :: nat
   265   assume "k dvd m" and "k dvd n"
   828   assume "k dvd m" and "k dvd n"
   266   then show "k dvd gcd m n"
   829   then show "k dvd gcd m n"
   267     by (induct m n rule: gcd_nat_induct) (simp_all add: gcd_non_0_nat dvd_mod gcd_0_nat)
   830     by (induct m n rule: gcd_nat_induct) (simp_all add: gcd_non_0_nat dvd_mod gcd_0_nat)
   268 qed
   831 qed (simp_all add: lcm_nat_def)
   269 
   832 
   270 instance int :: ring_gcd
   833 instance int :: ring_gcd
   271   by intro_classes (simp_all add: dvd_int_unfold_dvd_nat gcd_int_def gcd_greatest)
   834   by standard
       
   835     (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)
   272 
   836 
   273 lemma dvd_gcd_D1_nat: "k dvd gcd m n \<Longrightarrow> (k::nat) dvd m"
   837 lemma dvd_gcd_D1_nat: "k dvd gcd m n \<Longrightarrow> (k::nat) dvd m"
   274   by (metis gcd_dvd1 dvd_trans)
   838   by (metis gcd_dvd1 dvd_trans)
   275 
   839 
   276 lemma dvd_gcd_D2_nat: "k dvd gcd m n \<Longrightarrow> (k::nat) dvd n"
   840 lemma dvd_gcd_D2_nat: "k dvd gcd m n \<Longrightarrow> (k::nat) dvd n"
   330  apply (auto intro: gcd_greatest)
   894  apply (auto intro: gcd_greatest)
   331 done
   895 done
   332 
   896 
   333 interpretation gcd_nat: abel_semigroup "gcd :: nat \<Rightarrow> nat \<Rightarrow> nat"
   897 interpretation gcd_nat: abel_semigroup "gcd :: nat \<Rightarrow> nat \<Rightarrow> nat"
   334   + gcd_nat: semilattice_neutr_order "gcd :: nat \<Rightarrow> nat \<Rightarrow> nat" 0 "op dvd" "(\<lambda>m n. m dvd n \<and> \<not> n dvd m)"
   898   + gcd_nat: semilattice_neutr_order "gcd :: nat \<Rightarrow> nat \<Rightarrow> nat" 0 "op dvd" "(\<lambda>m n. m dvd n \<and> \<not> n dvd m)"
   335 apply default
   899 apply standard
   336 apply (auto intro: dvd_antisym dvd_trans)[4]
   900 apply (auto intro: dvd_antisym dvd_trans)[2]
   337 apply (metis dvd.dual_order.refl gcd_unique_nat)+
   901 apply (metis dvd.dual_order.refl gcd_unique_nat)+
   338 done
   902 done
   339 
   903 
   340 interpretation gcd_int: abel_semigroup "gcd :: int \<Rightarrow> int \<Rightarrow> int"
   904 interpretation gcd_int: abel_semigroup "gcd :: int \<Rightarrow> int \<Rightarrow> int" ..
   341 proof
   905 
   342 qed (simp_all add: gcd_int_def gcd_nat.assoc gcd_nat.commute gcd_nat.left_commute)
   906 lemmas gcd_assoc_nat = gcd.assoc [where ?'a = nat]
   343 
   907 lemmas gcd_commute_nat = gcd.commute [where ?'a = nat]
   344 lemmas gcd_assoc_nat = gcd_nat.assoc
   908 lemmas gcd_left_commute_nat = gcd.left_commute [where ?'a = nat]
   345 lemmas gcd_commute_nat = gcd_nat.commute
   909 lemmas gcd_assoc_int = gcd.assoc [where ?'a = int]
   346 lemmas gcd_left_commute_nat = gcd_nat.left_commute
   910 lemmas gcd_commute_int = gcd.commute [where ?'a = int]
   347 lemmas gcd_assoc_int = gcd_int.assoc
   911 lemmas gcd_left_commute_int = gcd.left_commute [where ?'a = int]
   348 lemmas gcd_commute_int = gcd_int.commute
       
   349 lemmas gcd_left_commute_int = gcd_int.left_commute
       
   350 
   912 
   351 lemmas gcd_ac_nat = gcd_assoc_nat gcd_commute_nat gcd_left_commute_nat
   913 lemmas gcd_ac_nat = gcd_assoc_nat gcd_commute_nat gcd_left_commute_nat
   352 
   914 
   353 lemmas gcd_ac_int = gcd_assoc_int gcd_commute_int gcd_left_commute_int
   915 lemmas gcd_ac_int = gcd_assoc_int gcd_commute_int gcd_left_commute_int
   354 
   916 
   760 
  1322 
   761 lemma coprime_exp_int: "coprime (d::int) a \<Longrightarrow> coprime d (a^n)"
  1323 lemma coprime_exp_int: "coprime (d::int) a \<Longrightarrow> coprime d (a^n)"
   762   by (induct n) (simp_all add: coprime_mult_int)
  1324   by (induct n) (simp_all add: coprime_mult_int)
   763 
  1325 
   764 lemma coprime_exp2_nat [intro]: "coprime (a::nat) b \<Longrightarrow> coprime (a^n) (b^m)"
  1326 lemma coprime_exp2_nat [intro]: "coprime (a::nat) b \<Longrightarrow> coprime (a^n) (b^m)"
   765   by (simp add: coprime_exp_nat gcd_nat.commute)
  1327   by (simp add: coprime_exp_nat ac_simps)
   766 
  1328 
   767 lemma coprime_exp2_int [intro]: "coprime (a::int) b \<Longrightarrow> coprime (a^n) (b^m)"
  1329 lemma coprime_exp2_int [intro]: "coprime (a::int) b \<Longrightarrow> coprime (a^n) (b^m)"
   768   by (simp add: coprime_exp_int gcd_int.commute)
  1330   by (simp add: coprime_exp_int ac_simps)
   769 
  1331 
   770 lemma gcd_exp_nat: "gcd ((a::nat)^n) (b^n) = (gcd a b)^n"
  1332 lemma gcd_exp_nat: "gcd ((a::nat)^n) (b^n) = (gcd a b)^n"
   771 proof (cases)
  1333 proof (cases)
   772   assume "a = 0 & b = 0"
  1334   assume "a = 0 & b = 0"
   773   thus ?thesis by simp
  1335   thus ?thesis by simp
   925   then obtain k where k: "n' = m*k" unfolding dvd_def by blast
  1487   then obtain k where k: "n' = m*k" unfolding dvd_def by blast
   926   from n' k show ?thesis unfolding dvd_def by auto
  1488   from n' k show ?thesis unfolding dvd_def by auto
   927 qed
  1489 qed
   928 
  1490 
   929 lemma coprime_plus_one_nat [simp]: "coprime ((n::nat) + 1) n"
  1491 lemma coprime_plus_one_nat [simp]: "coprime ((n::nat) + 1) n"
   930   by (simp add: gcd_nat.commute)
  1492   by (simp add: gcd.commute)
   931 
  1493 
   932 lemma coprime_Suc_nat [simp]: "coprime (Suc n) n"
  1494 lemma coprime_Suc_nat [simp]: "coprime (Suc n) n"
   933   using coprime_plus_one_nat by (simp add: One_nat_def)
  1495   using coprime_plus_one_nat by (simp add: One_nat_def)
   934 
  1496 
   935 lemma coprime_plus_one_int [simp]: "coprime ((n::int) + 1) n"
  1497 lemma coprime_plus_one_int [simp]: "coprime ((n::int) + 1) n"
   936   by (simp add: gcd_int.commute)
  1498   by (simp add: gcd.commute)
   937 
  1499 
   938 lemma coprime_minus_one_nat: "(n::nat) \<noteq> 0 \<Longrightarrow> coprime (n - 1) n"
  1500 lemma coprime_minus_one_nat: "(n::nat) \<noteq> 0 \<Longrightarrow> coprime (n - 1) n"
   939   using coprime_plus_one_nat [of "n - 1"]
  1501   using coprime_plus_one_nat [of "n - 1"]
   940     gcd_commute_nat [of "n - 1" n] by auto
  1502     gcd_commute_nat [of "n - 1" n] by auto
   941 
  1503 
   956   apply (induct set: finite)
  1518   apply (induct set: finite)
   957   apply (auto simp add: gcd_mult_cancel_int)
  1519   apply (auto simp add: gcd_mult_cancel_int)
   958 done
  1520 done
   959 
  1521 
   960 lemma coprime_common_divisor_nat: 
  1522 lemma coprime_common_divisor_nat: 
   961     "coprime (a::nat) b \<Longrightarrow> x dvd a \<Longrightarrow> x dvd b \<Longrightarrow> x = 1"
  1523   "coprime (a::nat) b \<Longrightarrow> x dvd a \<Longrightarrow> x dvd b \<Longrightarrow> x = 1"
   962   by (metis gcd_greatest_iff_nat nat_dvd_1_iff_1)
  1524   by (metis gcd_greatest_iff_nat nat_dvd_1_iff_1)
   963 
  1525 
   964 lemma coprime_common_divisor_int:
  1526 lemma coprime_common_divisor_int:
   965     "coprime (a::int) b \<Longrightarrow> x dvd a \<Longrightarrow> x dvd b \<Longrightarrow> abs x = 1"
  1527   "coprime (a::int) b \<Longrightarrow> x dvd a \<Longrightarrow> x dvd b \<Longrightarrow> abs x = 1"
   966   using gcd_greatest by fastforce
  1528   using gcd_greatest_iff [of x a b] by auto
   967 
  1529 
   968 lemma coprime_divisors_nat:
  1530 lemma coprime_divisors_nat:
   969     "(d::int) dvd a \<Longrightarrow> e dvd b \<Longrightarrow> coprime a b \<Longrightarrow> coprime d e"
  1531     "(d::int) dvd a \<Longrightarrow> e dvd b \<Longrightarrow> coprime a b \<Longrightarrow> coprime d e"
   970   by (meson coprime_int dvd_trans gcd_dvd1 gcd_dvd2 gcd_ge_0_int)
  1532   by (meson coprime_int dvd_trans gcd_dvd1 gcd_dvd2 gcd_ge_0_int)
   971 
  1533 
  1264 using assms by (cases m) auto
  1826 using assms by (cases m) auto
  1265 
  1827 
  1266 lemma lcm_least_nat:
  1828 lemma lcm_least_nat:
  1267   assumes "(m::nat) dvd k" and "n dvd k"
  1829   assumes "(m::nat) dvd k" and "n dvd k"
  1268   shows "lcm m n dvd k"
  1830   shows "lcm m n dvd k"
  1269 proof (cases k)
  1831   using assms by (rule lcm_least)
  1270   case 0 then show ?thesis by auto
       
  1271 next
       
  1272   case (Suc _) then have pos_k: "k > 0" by auto
       
  1273   from assms dvd_pos_nat [OF this] have pos_mn: "m > 0" "n > 0" by auto
       
  1274   with gcd_zero_nat [of m n] have pos_gcd: "gcd m n > 0" by simp
       
  1275   from assms obtain p where k_m: "k = m * p" using dvd_def by blast
       
  1276   from assms obtain q where k_n: "k = n * q" using dvd_def by blast
       
  1277   from pos_k k_m have pos_p: "p > 0" by auto
       
  1278   from pos_k k_n have pos_q: "q > 0" by auto
       
  1279   have "k * k * gcd q p = k * gcd (k * q) (k * p)"
       
  1280     by (simp add: ac_simps gcd_mult_distrib_nat)
       
  1281   also have "\<dots> = k * gcd (m * p * q) (n * q * p)"
       
  1282     by (simp add: k_m [symmetric] k_n [symmetric])
       
  1283   also have "\<dots> = k * p * q * gcd m n"
       
  1284     by (simp add: ac_simps gcd_mult_distrib_nat)
       
  1285   finally have "(m * p) * (n * q) * gcd q p = k * p * q * gcd m n"
       
  1286     by (simp only: k_m [symmetric] k_n [symmetric])
       
  1287   then have "p * q * m * n * gcd q p = p * q * k * gcd m n"
       
  1288     by (simp add: ac_simps)
       
  1289   with pos_p pos_q have "m * n * gcd q p = k * gcd m n"
       
  1290     by simp
       
  1291   with prod_gcd_lcm_nat [of m n]
       
  1292   have "lcm m n * gcd q p * gcd m n = k * gcd m n"
       
  1293     by (simp add: ac_simps)
       
  1294   with pos_gcd have "lcm m n * gcd q p = k" by auto
       
  1295   then show ?thesis using dvd_def by auto
       
  1296 qed
       
  1297 
  1832 
  1298 lemma lcm_least_int:
  1833 lemma lcm_least_int:
  1299   "(m::int) dvd k \<Longrightarrow> n dvd k \<Longrightarrow> lcm m n dvd k"
  1834   "(m::int) dvd k \<Longrightarrow> n dvd k \<Longrightarrow> lcm m n dvd k"
  1300 apply (subst lcm_abs_int)
  1835   by (rule lcm_least)
  1301 apply (rule dvd_trans)
       
  1302 apply (rule lcm_least_nat [transferred, of _ "abs k" _])
       
  1303 apply auto
       
  1304 done
       
  1305 
  1836 
  1306 lemma lcm_dvd1_nat: "(m::nat) dvd lcm m n"
  1837 lemma lcm_dvd1_nat: "(m::nat) dvd lcm m n"
  1307 proof (cases m)
  1838 proof (cases m)
  1308   case 0 then show ?thesis by simp
  1839   case 0 then show ?thesis by simp
  1309 next
  1840 next
  1331   apply (rule lcm_dvd1_nat [transferred])
  1862   apply (rule lcm_dvd1_nat [transferred])
  1332   apply auto
  1863   apply auto
  1333 done
  1864 done
  1334 
  1865 
  1335 lemma lcm_dvd2_nat: "(n::nat) dvd lcm m n"
  1866 lemma lcm_dvd2_nat: "(n::nat) dvd lcm m n"
  1336   using lcm_dvd1_nat [of n m] by (simp only: lcm_nat_def mult.commute gcd_nat.commute)
  1867   by (rule lcm_dvd2)
  1337 
  1868 
  1338 lemma lcm_dvd2_int: "(n::int) dvd lcm m n"
  1869 lemma lcm_dvd2_int: "(n::int) dvd lcm m n"
  1339   using lcm_dvd1_int [of n m] by (simp only: lcm_int_def lcm_nat_def mult.commute gcd_nat.commute)
  1870   by (rule lcm_dvd2)
  1340 
  1871 
  1341 lemma dvd_lcm_I1_nat[simp]: "(k::nat) dvd m \<Longrightarrow> k dvd lcm m n"
  1872 lemma dvd_lcm_I1_nat[simp]: "(k::nat) dvd m \<Longrightarrow> k dvd lcm m n"
  1342 by(metis lcm_dvd1_nat dvd_trans)
  1873 by(metis lcm_dvd1_nat dvd_trans)
  1343 
  1874 
  1344 lemma dvd_lcm_I2_nat[simp]: "(k::nat) dvd n \<Longrightarrow> k dvd lcm m n"
  1875 lemma dvd_lcm_I2_nat[simp]: "(k::nat) dvd n \<Longrightarrow> k dvd lcm m n"
  1358     (\<forall>e. a dvd e \<and> b dvd e \<longrightarrow> d dvd e) \<longleftrightarrow> d = lcm a b"
  1889     (\<forall>e. a dvd e \<and> b dvd e \<longrightarrow> d dvd e) \<longleftrightarrow> d = lcm a b"
  1359   using lcm_least_int zdvd_antisym_nonneg by auto
  1890   using lcm_least_int zdvd_antisym_nonneg by auto
  1360 
  1891 
  1361 interpretation lcm_nat: abel_semigroup "lcm :: nat \<Rightarrow> nat \<Rightarrow> nat"
  1892 interpretation lcm_nat: abel_semigroup "lcm :: nat \<Rightarrow> nat \<Rightarrow> nat"
  1362   + lcm_nat: semilattice_neutr "lcm :: nat \<Rightarrow> nat \<Rightarrow> nat" 1
  1893   + lcm_nat: semilattice_neutr "lcm :: nat \<Rightarrow> nat \<Rightarrow> nat" 1
  1363 proof
  1894   by standard simp_all
  1364   fix n m p :: nat
  1895 
  1365   show "lcm (lcm n m) p = lcm n (lcm m p)"
  1896 interpretation lcm_int: abel_semigroup "lcm :: int \<Rightarrow> int \<Rightarrow> int" ..
  1366     by (rule lcm_unique_nat [THEN iffD1]) (metis dvd.order_trans lcm_unique_nat)
  1897 
  1367   show "lcm m n = lcm n m"
  1898 lemmas lcm_assoc_nat = lcm.assoc [where ?'a = nat]
  1368     by (simp add: lcm_nat_def gcd_commute_nat field_simps)
  1899 lemmas lcm_commute_nat = lcm.commute [where ?'a = nat]
  1369   show "lcm m m = m"
  1900 lemmas lcm_left_commute_nat = lcm.left_commute [where ?'a = nat]
  1370     by (metis dvd.order_refl lcm_unique_nat)
  1901 lemmas lcm_assoc_int = lcm.assoc [where ?'a = int]
  1371   show "lcm m 1 = m"
  1902 lemmas lcm_commute_int = lcm.commute [where ?'a = int]
  1372     by (metis dvd.dual_order.refl lcm_unique_nat one_dvd)
  1903 lemmas lcm_left_commute_int = lcm.left_commute [where ?'a = int]
  1373 qed
       
  1374 
       
  1375 interpretation lcm_int: abel_semigroup "lcm :: int \<Rightarrow> int \<Rightarrow> int"
       
  1376 proof
       
  1377   fix n m p :: int
       
  1378   show "lcm (lcm n m) p = lcm n (lcm m p)"
       
  1379     by (rule lcm_unique_int [THEN iffD1]) (metis dvd_trans lcm_unique_int)
       
  1380   show "lcm m n = lcm n m"
       
  1381     by (simp add: lcm_int_def lcm_nat.commute)
       
  1382 qed
       
  1383 
       
  1384 lemmas lcm_assoc_nat = lcm_nat.assoc
       
  1385 lemmas lcm_commute_nat = lcm_nat.commute
       
  1386 lemmas lcm_left_commute_nat = lcm_nat.left_commute
       
  1387 lemmas lcm_assoc_int = lcm_int.assoc
       
  1388 lemmas lcm_commute_int = lcm_int.commute
       
  1389 lemmas lcm_left_commute_int = lcm_int.left_commute
       
  1390 
  1904 
  1391 lemmas lcm_ac_nat = lcm_assoc_nat lcm_commute_nat lcm_left_commute_nat
  1905 lemmas lcm_ac_nat = lcm_assoc_nat lcm_commute_nat lcm_left_commute_nat
  1392 lemmas lcm_ac_int = lcm_assoc_int lcm_commute_int lcm_left_commute_int
  1906 lemmas lcm_ac_int = lcm_assoc_int lcm_commute_int lcm_left_commute_int
  1393 
  1907 
  1394 lemma lcm_proj2_if_dvd_nat [simp]: "(x::nat) dvd y \<Longrightarrow> lcm x y = y"
  1908 lemma lcm_proj2_if_dvd_nat [simp]: "(x::nat) dvd y \<Longrightarrow> lcm x y = y"
  1450 
  1964 
  1451 
  1965 
  1452 subsection {* The complete divisibility lattice *}
  1966 subsection {* The complete divisibility lattice *}
  1453 
  1967 
  1454 interpretation gcd_semilattice_nat: semilattice_inf gcd "op dvd" "(\<lambda>m n::nat. m dvd n \<and> \<not> n dvd m)"
  1968 interpretation gcd_semilattice_nat: semilattice_inf gcd "op dvd" "(\<lambda>m n::nat. m dvd n \<and> \<not> n dvd m)"
  1455 proof (default, goals)
  1969   by standard simp_all
  1456   case 3
       
  1457   thus ?case by(metis gcd_unique_nat)
       
  1458 qed auto
       
  1459 
  1970 
  1460 interpretation lcm_semilattice_nat: semilattice_sup lcm "op dvd" "(\<lambda>m n::nat. m dvd n \<and> \<not> n dvd m)"
  1971 interpretation lcm_semilattice_nat: semilattice_sup lcm "op dvd" "(\<lambda>m n::nat. m dvd n \<and> \<not> n dvd m)"
  1461 proof (default, goals)
  1972   by standard simp_all
  1462   case 3
       
  1463   thus ?case by(metis lcm_unique_nat)
       
  1464 qed auto
       
  1465 
  1973 
  1466 interpretation gcd_lcm_lattice_nat: lattice gcd "op dvd" "(\<lambda>m n::nat. m dvd n & ~ n dvd m)" lcm ..
  1974 interpretation gcd_lcm_lattice_nat: lattice gcd "op dvd" "(\<lambda>m n::nat. m dvd n & ~ n dvd m)" lcm ..
  1467 
  1975 
  1468 text{* Lifting gcd and lcm to sets (Gcd/Lcm).
  1976 text{* Lifting gcd and lcm to sets (Gcd/Lcm).
  1469 Gcd is defined via Lcm to facilitate the proof that we have a complete lattice.
  1977 Gcd is defined via Lcm to facilitate the proof that we have a complete lattice.
  1470 *}
  1978 *}
  1471 
  1979 
  1472 class Gcd = gcd +
       
  1473   fixes Gcd :: "'a set \<Rightarrow> 'a"
       
  1474   fixes Lcm :: "'a set \<Rightarrow> 'a"
       
  1475 
       
  1476 instantiation nat :: Gcd
  1980 instantiation nat :: Gcd
  1477 begin
  1981 begin
  1478 
  1982 
  1479 definition
  1983 definition
  1480   "Lcm (M::nat set) = (if finite M then semilattice_neutr_set.F lcm 1 M else 0)"
  1984   "Lcm (M::nat set) = (if finite M then semilattice_neutr_set.F lcm 1 M else 0)"
  1496 definition
  2000 definition
  1497   "Gcd (M::nat set) = Lcm {d. \<forall>m\<in>M. d dvd m}"
  2001   "Gcd (M::nat set) = Lcm {d. \<forall>m\<in>M. d dvd m}"
  1498 
  2002 
  1499 instance ..
  2003 instance ..
  1500 
  2004 
  1501 end
       
  1502 
       
  1503 class semiring_Gcd = semiring_gcd + Gcd +
       
  1504   assumes Gcd_dvd: "a \<in> A \<Longrightarrow> Gcd A dvd a"
       
  1505     and dvd_Gcd: "\<forall>b\<in>A. a dvd b \<Longrightarrow> a dvd Gcd A"
       
  1506     and Gcd_insert [simp]: "Gcd (insert a A) = gcd a (Gcd A)"
       
  1507 begin
       
  1508 
       
  1509 lemma Gcd_empty [simp]:
       
  1510   "Gcd {} = 0"
       
  1511   by (rule dvd_0_left, rule dvd_Gcd) simp
       
  1512 
       
  1513 lemma Gcd_set [code_unfold]:
       
  1514   "Gcd (set as) = foldr gcd as 0"
       
  1515   by (induct as) simp_all
       
  1516   
       
  1517 end
  2005 end
  1518 
  2006 
  1519 lemma dvd_Lcm_nat [simp]:
  2007 lemma dvd_Lcm_nat [simp]:
  1520   fixes M :: "nat set"
  2008   fixes M :: "nat set"
  1521   assumes "m \<in> M"
  2009   assumes "m \<in> M"
  1542   complete_lattice Gcd Lcm gcd Rings.dvd "\<lambda>m n. m dvd n \<and> \<not> n dvd m" lcm 1 "0::nat"
  2030   complete_lattice Gcd Lcm gcd Rings.dvd "\<lambda>m n. m dvd n \<and> \<not> n dvd m" lcm 1 "0::nat"
  1543 where "Inf.INFIMUM Gcd A f = Gcd (f ` A :: nat set)"
  2031 where "Inf.INFIMUM Gcd A f = Gcd (f ` A :: nat set)"
  1544   and "Sup.SUPREMUM Lcm A f = Lcm (f ` A)"
  2032   and "Sup.SUPREMUM Lcm A f = Lcm (f ` A)"
  1545 proof -
  2033 proof -
  1546   show "class.complete_lattice Gcd Lcm gcd Rings.dvd (\<lambda>m n. m dvd n \<and> \<not> n dvd m) lcm 1 (0::nat)"
  2034   show "class.complete_lattice Gcd Lcm gcd Rings.dvd (\<lambda>m n. m dvd n \<and> \<not> n dvd m) lcm 1 (0::nat)"
  1547   proof (default, goals)
  2035     by default (auto simp add: Gcd_nat_def Lcm_nat_empty Lcm_nat_infinite)
  1548     case 1
       
  1549     thus ?case by (simp add: Gcd_nat_def)
       
  1550   next
       
  1551     case 2
       
  1552     thus ?case by (simp add: Gcd_nat_def)
       
  1553   next
       
  1554     case 5
       
  1555     show ?case by (simp add: Gcd_nat_def Lcm_nat_infinite)
       
  1556   next
       
  1557     case 6
       
  1558     show ?case by (simp add: Lcm_nat_empty)
       
  1559   next
       
  1560     case 3
       
  1561     thus ?case by simp
       
  1562   next
       
  1563     case 4
       
  1564     thus ?case by simp
       
  1565   qed
       
  1566   then interpret gcd_lcm_complete_lattice_nat:
  2036   then interpret gcd_lcm_complete_lattice_nat:
  1567     complete_lattice Gcd Lcm gcd Rings.dvd "\<lambda>m n. m dvd n \<and> \<not> n dvd m" lcm 1 "0::nat" .
  2037     complete_lattice Gcd Lcm gcd Rings.dvd "\<lambda>m n. m dvd n \<and> \<not> n dvd m" lcm 1 "0::nat" .
  1568   from gcd_lcm_complete_lattice_nat.INF_def show "Inf.INFIMUM Gcd A f = Gcd (f ` A)" .
  2038   from gcd_lcm_complete_lattice_nat.INF_def show "Inf.INFIMUM Gcd A f = Gcd (f ` A)" .
  1569   from gcd_lcm_complete_lattice_nat.SUP_def show "Sup.SUPREMUM Lcm A f = Lcm (f ` A)" .
  2039   from gcd_lcm_complete_lattice_nat.SUP_def show "Sup.SUPREMUM Lcm A f = Lcm (f ` A)" .
  1570 qed
  2040 qed
  1588 instance nat :: semiring_Gcd
  2058 instance nat :: semiring_Gcd
  1589 proof
  2059 proof
  1590   show "Gcd N dvd n" if "n \<in> N" for N and n :: nat
  2060   show "Gcd N dvd n" if "n \<in> N" for N and n :: nat
  1591     using that by (fact gcd_lcm_complete_lattice_nat.Inf_lower)
  2061     using that by (fact gcd_lcm_complete_lattice_nat.Inf_lower)
  1592 next
  2062 next
  1593   show "n dvd Gcd N" if "\<forall>m\<in>N. n dvd m" for N and n :: nat
  2063   show "n dvd Gcd N" if "\<And>m. m \<in> N \<Longrightarrow> n dvd m" for N and n :: nat
  1594     using that by (simp only: gcd_lcm_complete_lattice_nat.Inf_greatest)
  2064     using that by (simp only: gcd_lcm_complete_lattice_nat.Inf_greatest)
  1595 next
  2065 next
  1596   show "Gcd (insert n N) = gcd n (Gcd N)" for N and n :: nat
  2066   show "normalize (Gcd N) = Gcd N" for N :: "nat set"
  1597     by simp
  2067     by simp
       
  2068 qed
       
  2069 
       
  2070 instance nat :: semiring_Lcm
       
  2071 proof
       
  2072   have uf: "unit_factor (Lcm N) = 1" if "0 < Lcm N" for N :: "nat set"
       
  2073   proof (cases "finite N")
       
  2074     case False with that show ?thesis by (simp add: Lcm_nat_infinite)
       
  2075   next
       
  2076     case True then show ?thesis
       
  2077     using that proof (induct N)
       
  2078       case empty then show ?case by simp
       
  2079     next
       
  2080       case (insert n N)
       
  2081       have "lcm n (Lcm N) \<noteq> 0 \<longleftrightarrow> n \<noteq> 0 \<and> Lcm N \<noteq> 0"
       
  2082         using lcm_eq_0_iff [of n "Lcm N"] by simp
       
  2083       then have "lcm n (Lcm N) > 0 \<longleftrightarrow> n > 0 \<and> Lcm N > 0"
       
  2084         unfolding neq0_conv .
       
  2085       with insert show ?case
       
  2086         by (simp add: Lcm_nat_insert unit_factor_lcm)
       
  2087     qed
       
  2088   qed
       
  2089   show "Lcm N = Gcd {m. \<forall>n\<in>N. n dvd m}" for N :: "nat set"
       
  2090     by (rule associated_eqI) (auto intro!: associatedI Gcd_dvd Gcd_greatest
       
  2091       simp add: unit_factor_Gcd uf)
  1598 qed
  2092 qed
  1599 
  2093 
  1600 text{* Alternative characterizations of Gcd: *}
  2094 text{* Alternative characterizations of Gcd: *}
  1601 
  2095 
  1602 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})"
  2096 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})"
  1680 
  2174 
  1681 definition
  2175 definition
  1682   "Gcd M = int (Gcd (nat ` abs ` M))"
  2176   "Gcd M = int (Gcd (nat ` abs ` M))"
  1683 
  2177 
  1684 instance ..
  2178 instance ..
       
  2179 
  1685 end
  2180 end
       
  2181 
       
  2182 instance int :: semiring_Gcd
       
  2183   by standard (auto intro!: Gcd_dvd Gcd_greatest simp add: Gcd_int_def Lcm_int_def int_dvd_iff dvd_int_iff
       
  2184     dvd_int_unfold_dvd_nat [symmetric])
       
  2185 
       
  2186 instance int :: semiring_Lcm
       
  2187 proof
       
  2188   fix K :: "int set"
       
  2189   have "{n. \<forall>k\<in>K. nat \<bar>k\<bar> dvd n} = ((\<lambda>k. nat \<bar>k\<bar>) ` {l. \<forall>k\<in>K. k dvd l})"
       
  2190   proof (rule set_eqI)
       
  2191     fix n
       
  2192     have "(\<forall>k\<in>K. nat \<bar>k\<bar> dvd n) \<longleftrightarrow> (\<exists>l. (\<forall>k\<in>K. k dvd l) \<and> n = nat \<bar>l\<bar>)" (is "?P \<longleftrightarrow> ?Q")
       
  2193     proof
       
  2194       assume ?P
       
  2195       then have "(\<forall>k\<in>K. k dvd int n) \<and> n = nat \<bar>int n\<bar>"
       
  2196         by (auto simp add: dvd_int_unfold_dvd_nat)
       
  2197       then show ?Q by blast
       
  2198     next
       
  2199       assume ?Q then show ?P
       
  2200         by (auto simp add: dvd_int_unfold_dvd_nat)
       
  2201     qed
       
  2202     then show "n \<in> {n. \<forall>k\<in>K. nat \<bar>k\<bar> dvd n} \<longleftrightarrow> n \<in> (\<lambda>k. nat \<bar>k\<bar>) ` {l. \<forall>k\<in>K. k dvd l}"
       
  2203       by auto
       
  2204   qed
       
  2205   then show "Lcm K = Gcd {l. \<forall>k\<in>K. k dvd l}"
       
  2206     by (simp add: Gcd_int_def Lcm_int_def Lcm_Gcd)
       
  2207 qed
  1686 
  2208 
  1687 lemma Lcm_empty_int [simp]: "Lcm {} = (1::int)"
  2209 lemma Lcm_empty_int [simp]: "Lcm {} = (1::int)"
  1688   by (simp add: Lcm_int_def)
  2210   by (simp add: Lcm_int_def)
  1689 
  2211 
  1690 lemma Lcm_insert_int [simp]:
  2212 lemma Lcm_insert_int [simp]:
  1691   shows "Lcm (insert (n::int) N) = lcm n (Lcm N)"
  2213   shows "Lcm (insert (n::int) N) = lcm n (Lcm N)"
  1692   by (simp add: Lcm_int_def lcm_int_def)
  2214   by (simp add: Lcm_int_def lcm_int_def)
  1693 
  2215 
  1694 lemma dvd_int_iff: "x dvd y \<longleftrightarrow> nat (abs x) dvd nat (abs y)"
  2216 lemma dvd_int_iff: "x dvd y \<longleftrightarrow> nat (abs x) dvd nat (abs y)"
  1695   by (simp add: zdvd_int)
  2217   by (fact dvd_int_unfold_dvd_nat)
  1696 
  2218 
  1697 lemma dvd_Lcm_int [simp]:
  2219 lemma dvd_Lcm_int [simp]:
  1698   fixes M :: "int set" assumes "m \<in> M" shows "m dvd Lcm M"
  2220   fixes M :: "int set" assumes "m \<in> M" shows "m dvd Lcm M"
  1699   using assms by (simp add: Lcm_int_def dvd_int_iff)
  2221   using assms by (simp add: Lcm_int_def dvd_int_iff)
  1700 
  2222 
  1701 lemma Lcm_dvd_int [simp]:
  2223 lemma Lcm_dvd_int [simp]:
  1702   fixes M :: "int set"
  2224   fixes M :: "int set"
  1703   assumes "\<forall>m\<in>M. m dvd n" shows "Lcm M dvd n"
  2225   assumes "\<forall>m\<in>M. m dvd n" shows "Lcm M dvd n"
  1704   using assms by (simp add: Lcm_int_def dvd_int_iff)
  2226   using assms by (simp add: Lcm_int_def dvd_int_iff)
  1705 
  2227 
  1706 instance int :: semiring_Gcd
       
  1707   by intro_classes (simp_all add: Gcd_int_def gcd_int_def dvd_int_iff Gcd_dvd dvd_Gcd)
       
  1708   
       
  1709 lemma Lcm_set_int [code, code_unfold]:
  2228 lemma Lcm_set_int [code, code_unfold]:
  1710   "Lcm (set xs) = fold lcm xs (1::int)"
  2229   "Lcm (set xs) = fold lcm xs (1::int)"
  1711   by (induct xs rule: rev_induct) (simp_all add: lcm_commute_int)
  2230   by (induct xs rule: rev_induct) (simp_all add: lcm_commute_int)
  1712 
  2231 
  1713 lemma Gcd_set_int [code]:
  2232 lemma Gcd_set_int [code]: