| 
3366
 | 
     1  | 
(*  Title:      HOL/Divides.ML
  | 
| 
 | 
     2  | 
    ID:         $Id$
  | 
| 
 | 
     3  | 
    Author:     Lawrence C Paulson, Cambridge University Computer Laboratory
  | 
| 
 | 
     4  | 
    Copyright   1993  University of Cambridge
  | 
| 
 | 
     5  | 
  | 
| 
 | 
     6  | 
The division operators div, mod and the divides relation "dvd"
  | 
| 
 | 
     7  | 
*)
  | 
| 
 | 
     8  | 
  | 
| 
 | 
     9  | 
  | 
| 
 | 
    10  | 
(** Less-then properties **)
  | 
| 
 | 
    11  | 
  | 
| 
 | 
    12  | 
(*In ordinary notation: if 0<n and n<=m then m-n < m *)
  | 
| 
 | 
    13  | 
goal Arith.thy "!!m. [| 0<n; ~ m<n |] ==> m - n < m";
  | 
| 
 | 
    14  | 
by (subgoal_tac "0<n --> ~ m<n --> m - n < m" 1);
  | 
| 
 | 
    15  | 
by (Blast_tac 1);
  | 
| 
 | 
    16  | 
by (res_inst_tac [("m","m"),("n","n")] diff_induct 1);
 | 
| 
 | 
    17  | 
by (ALLGOALS(asm_simp_tac(!simpset addsimps [diff_less_Suc])));
  | 
| 
 | 
    18  | 
qed "diff_less";
  | 
| 
 | 
    19  | 
  | 
| 
 | 
    20  | 
val wf_less_trans = [eq_reflection, wf_pred_nat RS wf_trancl] MRS 
  | 
| 
 | 
    21  | 
                    def_wfrec RS trans;
  | 
| 
 | 
    22  | 
  | 
| 
 | 
    23  | 
(*** Remainder ***)
  | 
| 
 | 
    24  | 
  | 
| 
 | 
    25  | 
goal thy "(%m. m mod n) = wfrec (trancl pred_nat) \
  | 
| 
 | 
    26  | 
             \                      (%f j. if j<n then j else f (j-n))";
  | 
| 
 | 
    27  | 
by (simp_tac (!simpset addsimps [mod_def]) 1);
  | 
| 
 | 
    28  | 
qed "mod_eq";
  | 
| 
 | 
    29  | 
  | 
| 
 | 
    30  | 
goal thy "!!m. m<n ==> m mod n = m";
  | 
| 
 | 
    31  | 
by (rtac (mod_eq RS wf_less_trans) 1);
  | 
| 
 | 
    32  | 
by (Asm_simp_tac 1);
  | 
| 
 | 
    33  | 
qed "mod_less";
  | 
| 
 | 
    34  | 
  | 
| 
 | 
    35  | 
goal thy "!!m. [| 0<n;  ~m<n |] ==> m mod n = (m-n) mod n";
  | 
| 
 | 
    36  | 
by (rtac (mod_eq RS wf_less_trans) 1);
  | 
| 
 | 
    37  | 
by (asm_simp_tac (!simpset addsimps [diff_less, cut_apply, less_eq]) 1);
  | 
| 
 | 
    38  | 
qed "mod_geq";
  | 
| 
 | 
    39  | 
  | 
| 
 | 
    40  | 
goal thy "m mod 1 = 0";
  | 
| 
 | 
    41  | 
by (induct_tac "m" 1);
  | 
| 
 | 
    42  | 
by (ALLGOALS (asm_simp_tac (!simpset addsimps [mod_less, mod_geq])));
  | 
| 
 | 
    43  | 
qed "mod_1";
  | 
| 
 | 
    44  | 
Addsimps [mod_1];
  | 
| 
 | 
    45  | 
  | 
| 
 | 
    46  | 
goal thy "!!n. 0<n ==> n mod n = 0";
  | 
| 
 | 
    47  | 
by (asm_simp_tac (!simpset addsimps [mod_less, mod_geq]) 1);
  | 
| 
 | 
    48  | 
qed "mod_self";
  | 
| 
 | 
    49  | 
  | 
| 
 | 
    50  | 
goal thy "!!n. 0<n ==> (m+n) mod n = m mod n";
  | 
| 
 | 
    51  | 
by (subgoal_tac "(n + m) mod n = (n+m-n) mod n" 1);
  | 
| 
 | 
    52  | 
by (stac (mod_geq RS sym) 2);
  | 
| 
 | 
    53  | 
by (ALLGOALS (asm_full_simp_tac (!simpset addsimps [add_commute])));
  | 
| 
 | 
    54  | 
qed "mod_eq_add";
  | 
| 
 | 
    55  | 
  | 
| 
 | 
    56  | 
goal thy "!!k. [| 0<k; 0<n |] ==> (m mod n)*k = (m*k) mod (n*k)";
  | 
| 
 | 
    57  | 
by (res_inst_tac [("n","m")] less_induct 1);
 | 
| 
 | 
    58  | 
by (case_tac "na<n" 1);
  | 
| 
 | 
    59  | 
(*case na<n*)
  | 
| 
 | 
    60  | 
by (asm_simp_tac (!simpset addsimps [mod_less]) 1);
  | 
| 
 | 
    61  | 
(*case n<=na*)
  | 
| 
 | 
    62  | 
by (asm_simp_tac (!simpset addsimps [mod_geq, diff_less, zero_less_mult_iff, 
  | 
| 
 | 
    63  | 
				     diff_mult_distrib]) 1);
  | 
| 
 | 
    64  | 
qed "mod_mult_distrib";
  | 
| 
 | 
    65  | 
  | 
| 
 | 
    66  | 
goal thy "!!k. [| 0<k; 0<n |] ==> k*(m mod n) = (k*m) mod (k*n)";
  | 
| 
 | 
    67  | 
by (res_inst_tac [("n","m")] less_induct 1);
 | 
| 
 | 
    68  | 
by (case_tac "na<n" 1);
  | 
| 
 | 
    69  | 
(*case na<n*)
  | 
| 
 | 
    70  | 
by (asm_simp_tac (!simpset addsimps [mod_less]) 1);
  | 
| 
 | 
    71  | 
(*case n<=na*)
  | 
| 
 | 
    72  | 
by (asm_simp_tac (!simpset addsimps [mod_geq, diff_less, zero_less_mult_iff, 
  | 
| 
 | 
    73  | 
				     diff_mult_distrib2]) 1);
  | 
| 
 | 
    74  | 
qed "mod_mult_distrib2";
  | 
| 
 | 
    75  | 
  | 
| 
 | 
    76  | 
goal thy "!!n. 0<n ==> m*n mod n = 0";
  | 
| 
 | 
    77  | 
by (induct_tac "m" 1);
  | 
| 
 | 
    78  | 
by (asm_simp_tac (!simpset addsimps [mod_less]) 1);
  | 
| 
 | 
    79  | 
by (dres_inst_tac [("m","m*n")] mod_eq_add 1);
 | 
| 
 | 
    80  | 
by (asm_full_simp_tac (!simpset addsimps [add_commute]) 1);
  | 
| 
 | 
    81  | 
qed "mod_mult_self_is_0";
  | 
| 
 | 
    82  | 
Addsimps [mod_mult_self_is_0];
  | 
| 
 | 
    83  | 
  | 
| 
 | 
    84  | 
(*** Quotient ***)
  | 
| 
 | 
    85  | 
  | 
| 
 | 
    86  | 
goal thy "(%m. m div n) = wfrec (trancl pred_nat) \
  | 
| 
 | 
    87  | 
                        \            (%f j. if j<n then 0 else Suc (f (j-n)))";
  | 
| 
 | 
    88  | 
by (simp_tac (!simpset addsimps [div_def]) 1);
  | 
| 
 | 
    89  | 
qed "div_eq";
  | 
| 
 | 
    90  | 
  | 
| 
 | 
    91  | 
goal thy "!!m. m<n ==> m div n = 0";
  | 
| 
 | 
    92  | 
by (rtac (div_eq RS wf_less_trans) 1);
  | 
| 
 | 
    93  | 
by (Asm_simp_tac 1);
  | 
| 
 | 
    94  | 
qed "div_less";
  | 
| 
 | 
    95  | 
  | 
| 
 | 
    96  | 
goal thy "!!M. [| 0<n;  ~m<n |] ==> m div n = Suc((m-n) div n)";
  | 
| 
 | 
    97  | 
by (rtac (div_eq RS wf_less_trans) 1);
  | 
| 
 | 
    98  | 
by (asm_simp_tac (!simpset addsimps [diff_less, cut_apply, less_eq]) 1);
  | 
| 
 | 
    99  | 
qed "div_geq";
  | 
| 
 | 
   100  | 
  | 
| 
 | 
   101  | 
(*Main Result about quotient and remainder.*)
  | 
| 
 | 
   102  | 
goal thy "!!m. 0<n ==> (m div n)*n + m mod n = m";
  | 
| 
 | 
   103  | 
by (res_inst_tac [("n","m")] less_induct 1);
 | 
| 
 | 
   104  | 
by (rename_tac "k" 1);    (*Variable name used in line below*)
  | 
| 
 | 
   105  | 
by (case_tac "k<n" 1);
  | 
| 
 | 
   106  | 
by (ALLGOALS (asm_simp_tac(!simpset addsimps ([add_assoc] @
  | 
| 
 | 
   107  | 
                       [mod_less, mod_geq, div_less, div_geq,
  | 
| 
 | 
   108  | 
                        add_diff_inverse, diff_less]))));
  | 
| 
 | 
   109  | 
qed "mod_div_equality";
  | 
| 
 | 
   110  | 
  | 
| 
 | 
   111  | 
goal thy "m div 1 = m";
  | 
| 
 | 
   112  | 
by (induct_tac "m" 1);
  | 
| 
 | 
   113  | 
by (ALLGOALS (asm_simp_tac (!simpset addsimps [div_less, div_geq])));
  | 
| 
 | 
   114  | 
qed "div_1";
  | 
| 
 | 
   115  | 
Addsimps [div_1];
  | 
| 
 | 
   116  | 
  | 
| 
 | 
   117  | 
goal thy "!!n. 0<n ==> n div n = 1";
  | 
| 
 | 
   118  | 
by (asm_simp_tac (!simpset addsimps [div_less, div_geq]) 1);
  | 
| 
 | 
   119  | 
qed "div_self";
  | 
| 
 | 
   120  | 
  | 
| 
 | 
   121  | 
  | 
| 
 | 
   122  | 
(*** Further facts about mod (mainly for the mutilated chess board ***)
  | 
| 
 | 
   123  | 
  | 
| 
 | 
   124  | 
goal thy
  | 
| 
 | 
   125  | 
    "!!m n. 0<n ==> \
  | 
| 
 | 
   126  | 
\           Suc(m) mod n = (if Suc(m mod n) = n then 0 else Suc(m mod n))";
  | 
| 
 | 
   127  | 
by (res_inst_tac [("n","m")] less_induct 1);
 | 
| 
 | 
   128  | 
by (excluded_middle_tac "Suc(na)<n" 1);
  | 
| 
 | 
   129  | 
(* case Suc(na) < n *)
  | 
| 
 | 
   130  | 
by (forward_tac [lessI RS less_trans] 2);
  | 
| 
 | 
   131  | 
by (asm_simp_tac (!simpset addsimps [mod_less, less_not_refl2 RS not_sym]) 2);
  | 
| 
 | 
   132  | 
(* case n <= Suc(na) *)
  | 
| 
 | 
   133  | 
by (asm_full_simp_tac (!simpset addsimps [not_less_iff_le, mod_geq]) 1);
  | 
| 
 | 
   134  | 
by (etac (le_imp_less_or_eq RS disjE) 1);
  | 
| 
 | 
   135  | 
by (asm_simp_tac (!simpset addsimps [Suc_diff_n]) 1);
  | 
| 
 | 
   136  | 
by (asm_full_simp_tac (!simpset addsimps [not_less_eq RS sym, 
  | 
| 
 | 
   137  | 
                                          diff_less, mod_geq]) 1);
  | 
| 
 | 
   138  | 
by (asm_simp_tac (!simpset addsimps [mod_less]) 1);
  | 
| 
 | 
   139  | 
qed "mod_Suc";
  | 
| 
 | 
   140  | 
  | 
| 
 | 
   141  | 
goal thy "!!m n. 0<n ==> m mod n < n";
  | 
| 
 | 
   142  | 
by (res_inst_tac [("n","m")] less_induct 1);
 | 
| 
 | 
   143  | 
by (excluded_middle_tac "na<n" 1);
  | 
| 
 | 
   144  | 
(*case na<n*)
  | 
| 
 | 
   145  | 
by (asm_simp_tac (!simpset addsimps [mod_less]) 2);
  | 
| 
 | 
   146  | 
(*case n le na*)
  | 
| 
 | 
   147  | 
by (asm_full_simp_tac (!simpset addsimps [mod_geq, diff_less]) 1);
  | 
| 
 | 
   148  | 
qed "mod_less_divisor";
  | 
| 
 | 
   149  | 
  | 
| 
 | 
   150  | 
  | 
| 
 | 
   151  | 
(** Evens and Odds **)
  | 
| 
 | 
   152  | 
  | 
| 
 | 
   153  | 
(*With less_zeroE, causes case analysis on b<2*)
  | 
| 
 | 
   154  | 
AddSEs [less_SucE];
  | 
| 
 | 
   155  | 
  | 
| 
 | 
   156  | 
goal thy "!!k b. b<2 ==> k mod 2 = b | k mod 2 = (if b=1 then 0 else 1)";
  | 
| 
 | 
   157  | 
by (subgoal_tac "k mod 2 < 2" 1);
  | 
| 
 | 
   158  | 
by (asm_simp_tac (!simpset addsimps [mod_less_divisor]) 2);
  | 
| 
 | 
   159  | 
by (asm_simp_tac (!simpset setloop split_tac [expand_if]) 1);
  | 
| 
 | 
   160  | 
by (Blast_tac 1);
  | 
| 
 | 
   161  | 
qed "mod2_cases";
  | 
| 
 | 
   162  | 
  | 
| 
 | 
   163  | 
goal thy "Suc(Suc(m)) mod 2 = m mod 2";
  | 
| 
 | 
   164  | 
by (subgoal_tac "m mod 2 < 2" 1);
  | 
| 
 | 
   165  | 
by (asm_simp_tac (!simpset addsimps [mod_less_divisor]) 2);
  | 
| 
 | 
   166  | 
by (Step_tac 1);
  | 
| 
 | 
   167  | 
by (ALLGOALS (asm_simp_tac (!simpset addsimps [mod_Suc])));
  | 
| 
 | 
   168  | 
qed "mod2_Suc_Suc";
  | 
| 
 | 
   169  | 
Addsimps [mod2_Suc_Suc];
  | 
| 
 | 
   170  | 
  | 
| 
 | 
   171  | 
goal thy "!!m. m mod 2 ~= 0 ==> m mod 2 = 1";
  | 
| 
 | 
   172  | 
by (subgoal_tac "m mod 2 < 2" 1);
  | 
| 
 | 
   173  | 
by (asm_simp_tac (!simpset addsimps [mod_less_divisor]) 2);
  | 
| 
 | 
   174  | 
by (safe_tac (!claset addSEs [lessE]));
  | 
| 
 | 
   175  | 
by (ALLGOALS (blast_tac (!claset addIs [sym])));
  | 
| 
 | 
   176  | 
qed "mod2_neq_0";
  | 
| 
 | 
   177  | 
  | 
| 
 | 
   178  | 
goal thy "(m+m) mod 2 = 0";
  | 
| 
 | 
   179  | 
by (induct_tac "m" 1);
  | 
| 
 | 
   180  | 
by (simp_tac (!simpset addsimps [mod_less]) 1);
  | 
| 
 | 
   181  | 
by (asm_simp_tac (!simpset addsimps [mod2_Suc_Suc, add_Suc_right]) 1);
  | 
| 
 | 
   182  | 
qed "mod2_add_self";
  | 
| 
 | 
   183  | 
Addsimps [mod2_add_self];
  | 
| 
 | 
   184  | 
  | 
| 
 | 
   185  | 
Delrules [less_SucE];
  | 
| 
 | 
   186  | 
  | 
| 
 | 
   187  | 
  | 
| 
 | 
   188  | 
(*** More division laws ***)
  | 
| 
 | 
   189  | 
  | 
| 
 | 
   190  | 
goal thy "!!n. 0<n ==> m*n div n = m";
  | 
| 
 | 
   191  | 
by (cut_inst_tac [("m", "m*n")] mod_div_equality 1);
 | 
| 
 | 
   192  | 
ba 1;
  | 
| 
 | 
   193  | 
by (asm_full_simp_tac (!simpset addsimps [mod_mult_self_is_0]) 1);
  | 
| 
 | 
   194  | 
qed "div_mult_self_is_m";
  | 
| 
 | 
   195  | 
Addsimps [div_mult_self_is_m];
  | 
| 
 | 
   196  | 
  | 
| 
 | 
   197  | 
(*Cancellation law for division*)
  | 
| 
 | 
   198  | 
goal thy "!!k. [| 0<n; 0<k |] ==> (k*m) div (k*n) = m div n";
  | 
| 
 | 
   199  | 
by (res_inst_tac [("n","m")] less_induct 1);
 | 
| 
 | 
   200  | 
by (case_tac "na<n" 1);
  | 
| 
 | 
   201  | 
by (asm_simp_tac (!simpset addsimps [div_less, zero_less_mult_iff, 
  | 
| 
 | 
   202  | 
                                     mult_less_mono2]) 1);
  | 
| 
 | 
   203  | 
by (subgoal_tac "~ k*na < k*n" 1);
  | 
| 
 | 
   204  | 
by (asm_simp_tac
  | 
| 
 | 
   205  | 
     (!simpset addsimps [zero_less_mult_iff, div_geq,
  | 
| 
 | 
   206  | 
                         diff_mult_distrib2 RS sym, diff_less]) 1);
  | 
| 
 | 
   207  | 
by (asm_full_simp_tac (!simpset addsimps [not_less_iff_le, 
  | 
| 
 | 
   208  | 
                                          le_refl RS mult_le_mono]) 1);
  | 
| 
 | 
   209  | 
qed "div_cancel";
  | 
| 
 | 
   210  | 
Addsimps [div_cancel];
  | 
| 
 | 
   211  | 
  | 
| 
 | 
   212  | 
goal thy "!!k. [| 0<n; 0<k |] ==> (k*m) mod (k*n) = k * (m mod n)";
  | 
| 
 | 
   213  | 
by (res_inst_tac [("n","m")] less_induct 1);
 | 
| 
 | 
   214  | 
by (case_tac "na<n" 1);
  | 
| 
 | 
   215  | 
by (asm_simp_tac (!simpset addsimps [mod_less, zero_less_mult_iff, 
  | 
| 
 | 
   216  | 
                                     mult_less_mono2]) 1);
  | 
| 
 | 
   217  | 
by (subgoal_tac "~ k*na < k*n" 1);
  | 
| 
 | 
   218  | 
by (asm_simp_tac
  | 
| 
 | 
   219  | 
     (!simpset addsimps [zero_less_mult_iff, mod_geq,
  | 
| 
 | 
   220  | 
                         diff_mult_distrib2 RS sym, diff_less]) 1);
  | 
| 
 | 
   221  | 
by (asm_full_simp_tac (!simpset addsimps [not_less_iff_le, 
  | 
| 
 | 
   222  | 
                                          le_refl RS mult_le_mono]) 1);
  | 
| 
 | 
   223  | 
qed "mult_mod_distrib";
  | 
| 
 | 
   224  | 
  | 
| 
 | 
   225  | 
  | 
| 
 | 
   226  | 
(************************************************)
  | 
| 
 | 
   227  | 
(** Divides Relation                           **)
  | 
| 
 | 
   228  | 
(************************************************)
  | 
| 
 | 
   229  | 
  | 
| 
 | 
   230  | 
goalw thy [dvd_def] "m dvd 0";
  | 
| 
 | 
   231  | 
by (fast_tac (!claset addIs [mult_0_right RS sym]) 1);
  | 
| 
 | 
   232  | 
qed "dvd_0_right";
  | 
| 
 | 
   233  | 
Addsimps [dvd_0_right];
  | 
| 
 | 
   234  | 
  | 
| 
 | 
   235  | 
goalw thy [dvd_def] "!!m. 0 dvd m ==> m = 0";
  | 
| 
 | 
   236  | 
by (fast_tac (!claset addss !simpset) 1);
  | 
| 
 | 
   237  | 
qed "dvd_0_left";
  | 
| 
 | 
   238  | 
  | 
| 
 | 
   239  | 
goalw thy [dvd_def] "1 dvd k";
  | 
| 
 | 
   240  | 
by (Simp_tac 1);
  | 
| 
 | 
   241  | 
qed "dvd_1_left";
  | 
| 
 | 
   242  | 
AddIffs [dvd_1_left];
  | 
| 
 | 
   243  | 
  | 
| 
 | 
   244  | 
goalw thy [dvd_def] "m dvd m";
  | 
| 
 | 
   245  | 
by (fast_tac (!claset addIs [mult_1_right RS sym]) 1);
  | 
| 
 | 
   246  | 
qed "dvd_refl";
  | 
| 
 | 
   247  | 
Addsimps [dvd_refl];
  | 
| 
 | 
   248  | 
  | 
| 
 | 
   249  | 
goalw thy [dvd_def] "!!m n p. [| m dvd n; n dvd p |] ==> m dvd p";
  | 
| 
 | 
   250  | 
by (fast_tac (!claset addIs [mult_assoc] ) 1);
  | 
| 
 | 
   251  | 
qed "dvd_trans";
  | 
| 
 | 
   252  | 
  | 
| 
 | 
   253  | 
goalw thy [dvd_def] "!!m n. [| m dvd n; n dvd m |] ==> m=n";
  | 
| 
 | 
   254  | 
by (fast_tac (!claset addDs [mult_eq_self_implies_10]
  | 
| 
 | 
   255  | 
                     addss (!simpset addsimps [mult_assoc, mult_eq_1_iff])) 1);
  | 
| 
 | 
   256  | 
qed "dvd_anti_sym";
  | 
| 
 | 
   257  | 
  | 
| 
 | 
   258  | 
goalw thy [dvd_def] "!!k. [| k dvd m; k dvd n |] ==> k dvd (m + n)";
  | 
| 
 | 
   259  | 
by (blast_tac (!claset addIs [add_mult_distrib2 RS sym]) 1);
  | 
| 
 | 
   260  | 
qed "dvd_add";
  | 
| 
 | 
   261  | 
  | 
| 
 | 
   262  | 
goalw thy [dvd_def] "!!k. [| k dvd m; k dvd n |] ==> k dvd (m-n)";
  | 
| 
 | 
   263  | 
by (blast_tac (!claset addIs [diff_mult_distrib2 RS sym]) 1);
  | 
| 
 | 
   264  | 
qed "dvd_diff";
  | 
| 
 | 
   265  | 
  | 
| 
 | 
   266  | 
goal thy "!!k. [| k dvd (m-n); k dvd n; n<=m |] ==> k dvd m";
  | 
| 
 | 
   267  | 
be (not_less_iff_le RS iffD2 RS add_diff_inverse RS subst) 1;
  | 
| 
 | 
   268  | 
by (blast_tac (!claset addIs [dvd_add]) 1);
  | 
| 
 | 
   269  | 
qed "dvd_diffD";
  | 
| 
 | 
   270  | 
  | 
| 
 | 
   271  | 
goalw thy [dvd_def] "!!k. k dvd n ==> k dvd (m*n)";
  | 
| 
 | 
   272  | 
by (blast_tac (!claset addIs [mult_left_commute]) 1);
  | 
| 
 | 
   273  | 
qed "dvd_mult";
  | 
| 
 | 
   274  | 
  | 
| 
 | 
   275  | 
goal thy "!!k. k dvd m ==> k dvd (m*n)";
  | 
| 
 | 
   276  | 
by (stac mult_commute 1);
  | 
| 
 | 
   277  | 
by (etac dvd_mult 1);
  | 
| 
 | 
   278  | 
qed "dvd_mult2";
  | 
| 
 | 
   279  | 
  | 
| 
 | 
   280  | 
(* k dvd (m*k) *)
  | 
| 
 | 
   281  | 
AddIffs [dvd_refl RS dvd_mult, dvd_refl RS dvd_mult2];
  | 
| 
 | 
   282  | 
  | 
| 
 | 
   283  | 
goalw thy [dvd_def] "!!m. [| f dvd m; f dvd n; 0<n |] ==> f dvd (m mod n)";
  | 
| 
 | 
   284  | 
by (Step_tac 1);
  | 
| 
 | 
   285  | 
by (full_simp_tac (!simpset addsimps [zero_less_mult_iff]) 1);
  | 
| 
 | 
   286  | 
by (res_inst_tac 
  | 
| 
 | 
   287  | 
    [("x", "(((k div ka)*ka + k mod ka) - ((f*k) div (f*ka)) * ka)")] 
 | 
| 
 | 
   288  | 
    exI 1);
  | 
| 
 | 
   289  | 
by (asm_simp_tac (!simpset addsimps [diff_mult_distrib2, 
  | 
| 
 | 
   290  | 
                                     mult_mod_distrib, add_mult_distrib2]) 1);
  | 
| 
 | 
   291  | 
qed "dvd_mod";
  | 
| 
 | 
   292  | 
  | 
| 
 | 
   293  | 
goal thy "!!k. [| k dvd (m mod n); k dvd n; n~=0 |] ==> k dvd m";
  | 
| 
 | 
   294  | 
by (subgoal_tac "k dvd ((m div n)*n + m mod n)" 1);
  | 
| 
 | 
   295  | 
by (asm_simp_tac (!simpset addsimps [dvd_add, dvd_mult]) 2);
  | 
| 
 | 
   296  | 
by (asm_full_simp_tac (!simpset addsimps [mod_div_equality, zero_less_eq]) 1);
  | 
| 
 | 
   297  | 
qed "dvd_mod_imp_dvd";
  | 
| 
 | 
   298  | 
  | 
| 
 | 
   299  | 
goalw thy [dvd_def]  "!!k m n. [| (k*m) dvd (k*n); 0<k |] ==> m dvd n";
  | 
| 
 | 
   300  | 
by (etac exE 1);
  | 
| 
 | 
   301  | 
by (asm_full_simp_tac (!simpset addsimps mult_ac) 1);
  | 
| 
 | 
   302  | 
by (Blast_tac 1);
  | 
| 
 | 
   303  | 
qed "dvd_mult_cancel";
  | 
| 
 | 
   304  | 
  | 
| 
 | 
   305  | 
goalw thy [dvd_def] "!!i j. [| i dvd m; j dvd n|] ==> (i*j) dvd (m*n)";
  | 
| 
 | 
   306  | 
by (Step_tac 1);
  | 
| 
 | 
   307  | 
by (res_inst_tac [("x","k*ka")] exI 1);
 | 
| 
 | 
   308  | 
by (asm_simp_tac (!simpset addsimps mult_ac) 1);
  | 
| 
 | 
   309  | 
qed "mult_dvd_mono";
  | 
| 
 | 
   310  | 
  | 
| 
 | 
   311  | 
goalw thy [dvd_def] "!!c. (i*j) dvd k ==> i dvd k";
  | 
| 
 | 
   312  | 
by (full_simp_tac (!simpset addsimps [mult_assoc]) 1);
  | 
| 
 | 
   313  | 
by (Blast_tac 1);
  | 
| 
 | 
   314  | 
qed "dvd_mult_left";
  | 
| 
 | 
   315  | 
  | 
| 
 | 
   316  | 
goalw thy [dvd_def] "!!n. [| k dvd n; 0 < n |] ==> k <= n";
  | 
| 
 | 
   317  | 
by (Step_tac 1);
  | 
| 
 | 
   318  | 
by (ALLGOALS (full_simp_tac (!simpset addsimps [zero_less_mult_iff])));
  | 
| 
 | 
   319  | 
be conjE 1;
  | 
| 
 | 
   320  | 
br le_trans 1;
  | 
| 
 | 
   321  | 
br (le_refl RS mult_le_mono) 2;
  | 
| 
 | 
   322  | 
by (etac Suc_leI 2);
  | 
| 
 | 
   323  | 
by (Simp_tac 1);
  | 
| 
 | 
   324  | 
qed "dvd_imp_le";
  | 
| 
 | 
   325  | 
  | 
| 
 | 
   326  | 
goalw thy [dvd_def] "!!k. 0<k ==> (k dvd n) = (n mod k = 0)";
  | 
| 
 | 
   327  | 
by (Step_tac 1);
  | 
| 
 | 
   328  | 
by (stac mult_commute 1);
  | 
| 
 | 
   329  | 
by (Asm_simp_tac 1);
  | 
| 
 | 
   330  | 
by (eres_inst_tac [("t","n")] (mod_div_equality RS subst) 1);
 | 
| 
 | 
   331  | 
by (asm_simp_tac (!simpset addsimps [mult_commute]) 1);
  | 
| 
 | 
   332  | 
by (Blast_tac 1);
  | 
| 
 | 
   333  | 
qed "dvd_eq_mod_eq_0";
  |