# HG changeset patch # User paulson # Date 864998157 -7200 # Node ID 2402c6ab1561f0bfda901c17da02c4447eadd5a6 # Parent 86c0d19886226e6c7658f170de026440b8582d92 Moving div and mod from Arith to Divides Moving dvd from ex/Primes to Divides diff -r 86c0d1988622 -r 2402c6ab1561 src/HOL/Arith.ML --- a/src/HOL/Arith.ML Fri May 30 15:14:59 1997 +0200 +++ b/src/HOL/Arith.ML Fri May 30 15:15:57 1997 +0200 @@ -388,6 +388,13 @@ qed "diff_add_inverse2"; Addsimps [diff_add_inverse2]; +goal Arith.thy "!!i j k::nat. i<=j ==> (j-i=k) = (j=k+i)"; +by (Step_tac 1); +by (ALLGOALS + (asm_simp_tac + (!simpset addsimps [add_diff_inverse, not_less_iff_le, add_commute]))); +qed "le_imp_diff_is_add"; + val [prem] = goal Arith.thy "m < Suc(n) ==> m-n = 0"; by (rtac (prem RS rev_mp) 1); by (res_inst_tac [("m","m"),("n","n")] diff_induct 1); @@ -470,154 +477,6 @@ (*NOT added as rewrites, since sometimes they are used from right-to-left*) -(** Less-then properties **) - -(*In ordinary notation: if 0 m - n < m"; -by (subgoal_tac "0 ~ m m - n < m" 1); -by (Blast_tac 1); -by (res_inst_tac [("m","m"),("n","n")] diff_induct 1); -by (ALLGOALS(asm_simp_tac(!simpset addsimps [diff_less_Suc]))); -qed "diff_less"; - -val wf_less_trans = [eq_reflection, wf_pred_nat RS wf_trancl] MRS - def_wfrec RS trans; - -goalw Nat.thy [less_def] "(m,n) : pred_nat^+ = (m m mod n = m"; -by (rtac (mod_eq RS wf_less_trans) 1); -by (Asm_simp_tac 1); -qed "mod_less"; - -goal Arith.thy "!!m. [| 0 m mod n = (m-n) mod n"; -by (rtac (mod_eq RS wf_less_trans) 1); -by (asm_simp_tac (!simpset addsimps [diff_less, cut_apply, less_eq]) 1); -qed "mod_geq"; - -goal thy "!!n. 0 n mod n = 0"; -by (rtac (mod_eq RS wf_less_trans) 1); -by (asm_simp_tac (!simpset addsimps [mod_less, diff_self_eq_0, - cut_def, less_eq]) 1); -qed "mod_nn_is_0"; - -goal thy "!!n. 0 (m+n) mod n = m mod n"; -by (subgoal_tac "(n + m) mod n = (n+m-n) mod n" 1); -by (stac (mod_geq RS sym) 2); -by (ALLGOALS (asm_full_simp_tac (!simpset addsimps [add_commute]))); -qed "mod_eq_add"; - -goal thy "!!n. 0 m*n mod n = 0"; -by (induct_tac "m" 1); -by (asm_simp_tac (!simpset addsimps [mod_less]) 1); -by (dres_inst_tac [("m","m*n")] mod_eq_add 1); -by (asm_full_simp_tac (!simpset addsimps [add_commute]) 1); -qed "mod_prod_nn_is_0"; - - -(*** Quotient ***) - -goal Arith.thy "(%m. m div n) = wfrec (trancl pred_nat) \ - \ (%f j. if j m div n = 0"; -by (rtac (div_eq RS wf_less_trans) 1); -by (Asm_simp_tac 1); -qed "div_less"; - -goal Arith.thy "!!M. [| 0 m div n = Suc((m-n) div n)"; -by (rtac (div_eq RS wf_less_trans) 1); -by (asm_simp_tac (!simpset addsimps [diff_less, cut_apply, less_eq]) 1); -qed "div_geq"; - -(*Main Result about quotient and remainder.*) -goal Arith.thy "!!m. 0 (m div n)*n + m mod n = m"; -by (res_inst_tac [("n","m")] less_induct 1); -by (rename_tac "k" 1); (*Variable name used in line below*) -by (case_tac "k \ -\ Suc(m) mod n = (if Suc(m mod n) = n then 0 else Suc(m mod n))"; -by (res_inst_tac [("n","m")] less_induct 1); -by (excluded_middle_tac "Suc(na) m mod n < n"; -by (res_inst_tac [("n","m")] less_induct 1); -by (excluded_middle_tac "na k mod 2 = b | k mod 2 = (if b=1 then 0 else 1)"; -by (subgoal_tac "k mod 2 < 2" 1); -by (asm_simp_tac (!simpset addsimps [mod_less_divisor]) 2); -by (asm_simp_tac (!simpset setloop split_tac [expand_if]) 1); -by (Blast_tac 1); -qed "mod2_cases"; - -goal thy "Suc(Suc(m)) mod 2 = m mod 2"; -by (subgoal_tac "m mod 2 < 2" 1); -by (asm_simp_tac (!simpset addsimps [mod_less_divisor]) 2); -by (Step_tac 1); -by (ALLGOALS (asm_simp_tac (!simpset addsimps [mod_Suc]))); -qed "mod2_Suc_Suc"; -Addsimps [mod2_Suc_Suc]; - -goal Arith.thy "!!m. m mod 2 ~= 0 ==> m mod 2 = 1"; -by (subgoal_tac "m mod 2 < 2" 1); -by (asm_simp_tac (!simpset addsimps [mod_less_divisor]) 2); -by (safe_tac (!claset addSEs [lessE])); -by (ALLGOALS (blast_tac (!claset addIs [sym]))); -qed "mod2_neq_0"; - -goal thy "(m+m) mod 2 = 0"; -by (induct_tac "m" 1); -by (simp_tac (!simpset addsimps [mod_less]) 1); -by (asm_simp_tac (!simpset addsimps [mod2_Suc_Suc, add_Suc_right]) 1); -qed "mod2_add_self"; -Addsimps [mod2_add_self]; - -Delrules [less_SucE]; - - (*** Monotonicity of Multiplication ***) goal Arith.thy "!!i::nat. i<=j ==> i*k<=j*k"; @@ -688,44 +547,6 @@ Addsimps [mult_cancel1, mult_cancel2]; -(*** More division laws ***) - -goal thy "!!n. 0 m*n div n = m"; -by (cut_inst_tac [("m", "m*n")] mod_div_equality 1); -ba 1; -by (asm_full_simp_tac (!simpset addsimps [mod_prod_nn_is_0]) 1); -qed "div_prod_nn_is_m"; -Addsimps [div_prod_nn_is_m]; - -(*Cancellation law for division*) -goal Arith.thy "!!k. [| 0 (k*m) div (k*n) = m div n"; -by (res_inst_tac [("n","m")] less_induct 1); -by (case_tac "na (k*m) mod (k*n) = k * (m mod n)"; -by (res_inst_tac [("n","m")] less_induct 1); -by (case_tac "na n=1 | m=0"; diff -r 86c0d1988622 -r 2402c6ab1561 src/HOL/Arith.thy --- a/src/HOL/Arith.thy Fri May 30 15:14:59 1997 +0200 +++ b/src/HOL/Arith.thy Fri May 30 15:15:57 1997 +0200 @@ -3,38 +3,32 @@ Author: Lawrence C Paulson, Cambridge University Computer Laboratory Copyright 1993 University of Cambridge -Arithmetic operators and their definitions +Arithmetic operators + - and * (for div, mod and dvd, see Divides) *) Arith = Nat + instance - nat :: {plus, minus, times} + nat :: {plus, minus, times, power} consts pred :: nat => nat - div, mod :: [nat, nat] => nat (infixl 70) (* size of a datatype value; overloaded *) size :: 'a => nat defs pred_def "pred(m) == case m of 0 => 0 | Suc n => n" - mod_def "m mod n == wfrec (trancl pred_nat) - (%f j. if j m - n < m"; +by (subgoal_tac "0 ~ m m - n < m" 1); +by (Blast_tac 1); +by (res_inst_tac [("m","m"),("n","n")] diff_induct 1); +by (ALLGOALS(asm_simp_tac(!simpset addsimps [diff_less_Suc]))); +qed "diff_less"; + +val wf_less_trans = [eq_reflection, wf_pred_nat RS wf_trancl] MRS + def_wfrec RS trans; + +(*** Remainder ***) + +goal thy "(%m. m mod n) = wfrec (trancl pred_nat) \ + \ (%f j. if j m mod n = m"; +by (rtac (mod_eq RS wf_less_trans) 1); +by (Asm_simp_tac 1); +qed "mod_less"; + +goal thy "!!m. [| 0 m mod n = (m-n) mod n"; +by (rtac (mod_eq RS wf_less_trans) 1); +by (asm_simp_tac (!simpset addsimps [diff_less, cut_apply, less_eq]) 1); +qed "mod_geq"; + +goal thy "m mod 1 = 0"; +by (induct_tac "m" 1); +by (ALLGOALS (asm_simp_tac (!simpset addsimps [mod_less, mod_geq]))); +qed "mod_1"; +Addsimps [mod_1]; + +goal thy "!!n. 0 n mod n = 0"; +by (asm_simp_tac (!simpset addsimps [mod_less, mod_geq]) 1); +qed "mod_self"; + +goal thy "!!n. 0 (m+n) mod n = m mod n"; +by (subgoal_tac "(n + m) mod n = (n+m-n) mod n" 1); +by (stac (mod_geq RS sym) 2); +by (ALLGOALS (asm_full_simp_tac (!simpset addsimps [add_commute]))); +qed "mod_eq_add"; + +goal thy "!!k. [| 0 (m mod n)*k = (m*k) mod (n*k)"; +by (res_inst_tac [("n","m")] less_induct 1); +by (case_tac "na k*(m mod n) = (k*m) mod (k*n)"; +by (res_inst_tac [("n","m")] less_induct 1); +by (case_tac "na m*n mod n = 0"; +by (induct_tac "m" 1); +by (asm_simp_tac (!simpset addsimps [mod_less]) 1); +by (dres_inst_tac [("m","m*n")] mod_eq_add 1); +by (asm_full_simp_tac (!simpset addsimps [add_commute]) 1); +qed "mod_mult_self_is_0"; +Addsimps [mod_mult_self_is_0]; + +(*** Quotient ***) + +goal thy "(%m. m div n) = wfrec (trancl pred_nat) \ + \ (%f j. if j m div n = 0"; +by (rtac (div_eq RS wf_less_trans) 1); +by (Asm_simp_tac 1); +qed "div_less"; + +goal thy "!!M. [| 0 m div n = Suc((m-n) div n)"; +by (rtac (div_eq RS wf_less_trans) 1); +by (asm_simp_tac (!simpset addsimps [diff_less, cut_apply, less_eq]) 1); +qed "div_geq"; + +(*Main Result about quotient and remainder.*) +goal thy "!!m. 0 (m div n)*n + m mod n = m"; +by (res_inst_tac [("n","m")] less_induct 1); +by (rename_tac "k" 1); (*Variable name used in line below*) +by (case_tac "k n div n = 1"; +by (asm_simp_tac (!simpset addsimps [div_less, div_geq]) 1); +qed "div_self"; + + +(*** Further facts about mod (mainly for the mutilated chess board ***) + +goal thy + "!!m n. 0 \ +\ Suc(m) mod n = (if Suc(m mod n) = n then 0 else Suc(m mod n))"; +by (res_inst_tac [("n","m")] less_induct 1); +by (excluded_middle_tac "Suc(na) m mod n < n"; +by (res_inst_tac [("n","m")] less_induct 1); +by (excluded_middle_tac "na k mod 2 = b | k mod 2 = (if b=1 then 0 else 1)"; +by (subgoal_tac "k mod 2 < 2" 1); +by (asm_simp_tac (!simpset addsimps [mod_less_divisor]) 2); +by (asm_simp_tac (!simpset setloop split_tac [expand_if]) 1); +by (Blast_tac 1); +qed "mod2_cases"; + +goal thy "Suc(Suc(m)) mod 2 = m mod 2"; +by (subgoal_tac "m mod 2 < 2" 1); +by (asm_simp_tac (!simpset addsimps [mod_less_divisor]) 2); +by (Step_tac 1); +by (ALLGOALS (asm_simp_tac (!simpset addsimps [mod_Suc]))); +qed "mod2_Suc_Suc"; +Addsimps [mod2_Suc_Suc]; + +goal thy "!!m. m mod 2 ~= 0 ==> m mod 2 = 1"; +by (subgoal_tac "m mod 2 < 2" 1); +by (asm_simp_tac (!simpset addsimps [mod_less_divisor]) 2); +by (safe_tac (!claset addSEs [lessE])); +by (ALLGOALS (blast_tac (!claset addIs [sym]))); +qed "mod2_neq_0"; + +goal thy "(m+m) mod 2 = 0"; +by (induct_tac "m" 1); +by (simp_tac (!simpset addsimps [mod_less]) 1); +by (asm_simp_tac (!simpset addsimps [mod2_Suc_Suc, add_Suc_right]) 1); +qed "mod2_add_self"; +Addsimps [mod2_add_self]; + +Delrules [less_SucE]; + + +(*** More division laws ***) + +goal thy "!!n. 0 m*n div n = m"; +by (cut_inst_tac [("m", "m*n")] mod_div_equality 1); +ba 1; +by (asm_full_simp_tac (!simpset addsimps [mod_mult_self_is_0]) 1); +qed "div_mult_self_is_m"; +Addsimps [div_mult_self_is_m]; + +(*Cancellation law for division*) +goal thy "!!k. [| 0 (k*m) div (k*n) = m div n"; +by (res_inst_tac [("n","m")] less_induct 1); +by (case_tac "na (k*m) mod (k*n) = k * (m mod n)"; +by (res_inst_tac [("n","m")] less_induct 1); +by (case_tac "na m = 0"; +by (fast_tac (!claset addss !simpset) 1); +qed "dvd_0_left"; + +goalw thy [dvd_def] "1 dvd k"; +by (Simp_tac 1); +qed "dvd_1_left"; +AddIffs [dvd_1_left]; + +goalw thy [dvd_def] "m dvd m"; +by (fast_tac (!claset addIs [mult_1_right RS sym]) 1); +qed "dvd_refl"; +Addsimps [dvd_refl]; + +goalw thy [dvd_def] "!!m n p. [| m dvd n; n dvd p |] ==> m dvd p"; +by (fast_tac (!claset addIs [mult_assoc] ) 1); +qed "dvd_trans"; + +goalw thy [dvd_def] "!!m n. [| m dvd n; n dvd m |] ==> m=n"; +by (fast_tac (!claset addDs [mult_eq_self_implies_10] + addss (!simpset addsimps [mult_assoc, mult_eq_1_iff])) 1); +qed "dvd_anti_sym"; + +goalw thy [dvd_def] "!!k. [| k dvd m; k dvd n |] ==> k dvd (m + n)"; +by (blast_tac (!claset addIs [add_mult_distrib2 RS sym]) 1); +qed "dvd_add"; + +goalw thy [dvd_def] "!!k. [| k dvd m; k dvd n |] ==> k dvd (m-n)"; +by (blast_tac (!claset addIs [diff_mult_distrib2 RS sym]) 1); +qed "dvd_diff"; + +goal thy "!!k. [| k dvd (m-n); k dvd n; n<=m |] ==> k dvd m"; +be (not_less_iff_le RS iffD2 RS add_diff_inverse RS subst) 1; +by (blast_tac (!claset addIs [dvd_add]) 1); +qed "dvd_diffD"; + +goalw thy [dvd_def] "!!k. k dvd n ==> k dvd (m*n)"; +by (blast_tac (!claset addIs [mult_left_commute]) 1); +qed "dvd_mult"; + +goal thy "!!k. k dvd m ==> k dvd (m*n)"; +by (stac mult_commute 1); +by (etac dvd_mult 1); +qed "dvd_mult2"; + +(* k dvd (m*k) *) +AddIffs [dvd_refl RS dvd_mult, dvd_refl RS dvd_mult2]; + +goalw thy [dvd_def] "!!m. [| f dvd m; f dvd n; 0 f dvd (m mod n)"; +by (Step_tac 1); +by (full_simp_tac (!simpset addsimps [zero_less_mult_iff]) 1); +by (res_inst_tac + [("x", "(((k div ka)*ka + k mod ka) - ((f*k) div (f*ka)) * ka)")] + exI 1); +by (asm_simp_tac (!simpset addsimps [diff_mult_distrib2, + mult_mod_distrib, add_mult_distrib2]) 1); +qed "dvd_mod"; + +goal thy "!!k. [| k dvd (m mod n); k dvd n; n~=0 |] ==> k dvd m"; +by (subgoal_tac "k dvd ((m div n)*n + m mod n)" 1); +by (asm_simp_tac (!simpset addsimps [dvd_add, dvd_mult]) 2); +by (asm_full_simp_tac (!simpset addsimps [mod_div_equality, zero_less_eq]) 1); +qed "dvd_mod_imp_dvd"; + +goalw thy [dvd_def] "!!k m n. [| (k*m) dvd (k*n); 0 m dvd n"; +by (etac exE 1); +by (asm_full_simp_tac (!simpset addsimps mult_ac) 1); +by (Blast_tac 1); +qed "dvd_mult_cancel"; + +goalw thy [dvd_def] "!!i j. [| i dvd m; j dvd n|] ==> (i*j) dvd (m*n)"; +by (Step_tac 1); +by (res_inst_tac [("x","k*ka")] exI 1); +by (asm_simp_tac (!simpset addsimps mult_ac) 1); +qed "mult_dvd_mono"; + +goalw thy [dvd_def] "!!c. (i*j) dvd k ==> i dvd k"; +by (full_simp_tac (!simpset addsimps [mult_assoc]) 1); +by (Blast_tac 1); +qed "dvd_mult_left"; + +goalw thy [dvd_def] "!!n. [| k dvd n; 0 < n |] ==> k <= n"; +by (Step_tac 1); +by (ALLGOALS (full_simp_tac (!simpset addsimps [zero_less_mult_iff]))); +be conjE 1; +br le_trans 1; +br (le_refl RS mult_le_mono) 2; +by (etac Suc_leI 2); +by (Simp_tac 1); +qed "dvd_imp_le"; + +goalw thy [dvd_def] "!!k. 0 (k dvd n) = (n mod k = 0)"; +by (Step_tac 1); +by (stac mult_commute 1); +by (Asm_simp_tac 1); +by (eres_inst_tac [("t","n")] (mod_div_equality RS subst) 1); +by (asm_simp_tac (!simpset addsimps [mult_commute]) 1); +by (Blast_tac 1); +qed "dvd_eq_mod_eq_0"; diff -r 86c0d1988622 -r 2402c6ab1561 src/HOL/Divides.thy --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/HOL/Divides.thy Fri May 30 15:15:57 1997 +0200 @@ -0,0 +1,24 @@ +(* Title: HOL/Divides.thy + ID: $Id$ + Author: Lawrence C Paulson, Cambridge University Computer Laboratory + Copyright 1993 University of Cambridge + +The division operators div, mod and the divides relation "dvd" +*) + +Divides = Arith + + +consts + div, mod :: [nat, nat] => nat (infixl 70) + dvd :: [nat,nat]=>bool (infixl 70) + + +defs + mod_def "m mod n == wfrec (trancl pred_nat) + (%f j. if j