src/HOL/Integ/IntDiv.ML
author paulson
Fri, 09 Jul 1999 10:47:42 +0200
changeset 6942 f291292d727c
parent 6917 eba301caceea
child 6943 2cde117d2738
permissions -rw-r--r--
more monotonicity laws for times
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
6917
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
     1
(*  Title:      HOL/IntDiv.ML
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
     2
    ID:         $Id$
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
     3
    Author:     Lawrence C Paulson, Cambridge University Computer Laboratory
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
     4
    Copyright   1999  University of Cambridge
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
     5
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
     6
The division operators div, mod and the divides relation "dvd"
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
     7
*)
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
     8
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
     9
Addsimps [zless_nat_conj];
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
    10
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
    11
(*** Uniqueness and monotonicity of quotients and remainders ***)
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
    12
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
    13
Goal "[| r' + b*q' <= r + b*q;  #0 <= r';  #0 < b;  r < b |] \
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
    14
\     ==> q' <= (q::int)";
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
    15
by (subgoal_tac "r' + b * (q'-q) <= r" 1);
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
    16
by (simp_tac (simpset() addsimps zcompare_rls@[zdiff_zmult_distrib2]) 2);
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
    17
by (subgoal_tac "#0 < b * (#1 + q - q')" 1);
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
    18
by (etac order_le_less_trans 2);
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
    19
by (full_simp_tac (simpset() addsimps zcompare_rls@[zdiff_zmult_distrib2,
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
    20
						    zadd_zmult_distrib2]) 2);
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
    21
by (subgoal_tac "b * q' < b * (#1 + q)" 1);
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
    22
by (full_simp_tac (simpset() addsimps zcompare_rls@[zdiff_zmult_distrib2,
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
    23
						    zadd_zmult_distrib2]) 2);
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
    24
by (Asm_full_simp_tac 1);
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
    25
qed "unique_quotient_lemma";
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
    26
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
    27
Goal "[| r' + b*q' <= r + b*q;  r <= #0;  b < #0;  b < r' |] \
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
    28
\     ==> q <= (q'::int)";
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
    29
by (res_inst_tac [("b", "-b"), ("r", "-r'"), ("r'", "-r")] 
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
    30
    unique_quotient_lemma 1);
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
    31
by (auto_tac (claset(), 
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
    32
	      simpset() addsimps zcompare_rls@[zmult_zminus_right])); 
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
    33
qed "unique_quotient_lemma_neg";
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
    34
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
    35
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
    36
Goal "[| quorem ((a,b), (q,r));  quorem ((a,b), (q',r'));  b ~= #0 |] \
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
    37
\     ==> q = q'";
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
    38
by (asm_full_simp_tac 
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
    39
    (simpset() addsimps split_ifs@[quorem_def, linorder_neq_iff]) 1);
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
    40
by Safe_tac; 
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
    41
by (ALLGOALS Asm_full_simp_tac);
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
    42
by (REPEAT 
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
    43
    (blast_tac (claset() addIs [order_antisym]
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
    44
			 addDs [order_eq_refl RS unique_quotient_lemma, 
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
    45
				order_eq_refl RS unique_quotient_lemma_neg,
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
    46
				sym]) 1));
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
    47
qed "unique_quotient";
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
    48
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
    49
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
    50
Goal "[| quorem ((a,b), (q,r));  quorem ((a,b), (q',r'));  b ~= #0 |] \
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
    51
\     ==> r = r'";
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
    52
by (subgoal_tac "q = q'" 1);
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
    53
by (blast_tac (claset() addIs [unique_quotient]) 2);
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
    54
by (asm_full_simp_tac (simpset() addsimps [quorem_def]) 1);
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
    55
qed "unique_remainder";
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
    56
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
    57
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
    58
(*** Correctness of posDivAlg, the division algorithm for a>=0 and b>0 ***)
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
    59
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
    60
Goal "adjust a b (q,r) = (if #0 <= r-b then (#2*q + #1, r-b)  \
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
    61
\                         else (#2*q, r))";
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
    62
by (simp_tac (simpset() addsimps [adjust_def]) 1);
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
    63
qed "adjust_eq";
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
    64
Addsimps [adjust_eq];
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
    65
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
    66
(*Proving posDivAlg's termination condition*)
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
    67
val [tc] = posDivAlg.tcs;
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
    68
goalw_cterm [] (cterm_of (sign_of thy) (HOLogic.mk_Trueprop tc));
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
    69
by (auto_tac (claset(), simpset() addsimps [zmult_2_right]));
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
    70
val lemma = result();
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
    71
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
    72
(* removing the termination condition from the generated theorems *)
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
    73
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
    74
bind_thm ("posDivAlg_raw_eqn", lemma RS hd posDivAlg.rules);
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
    75
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
    76
(**use with simproc to avoid re-proving the premise*)
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
    77
Goal "#0 < b ==> \
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
    78
\     posDivAlg (a,b) =      \
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
    79
\      (if a<b then (#0,a) else adjust a b (posDivAlg(a, #2*b)))";
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
    80
by (rtac (posDivAlg_raw_eqn RS trans) 1);
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
    81
by (Asm_simp_tac 1);
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
    82
qed "posDivAlg_eqn";
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
    83
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
    84
val posDivAlg_induct = lemma RS posDivAlg.induct;
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
    85
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
    86
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
    87
(*Correctness of posDivAlg: it computes quotients correctly*)
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
    88
Goal "#0 <= a --> #0 < b --> quorem ((a, b), posDivAlg (a, b))";
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
    89
by (res_inst_tac [("u", "a"), ("v", "b")] posDivAlg_induct 1);
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
    90
by Auto_tac;
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
    91
by (ALLGOALS 
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
    92
    (asm_full_simp_tac (simpset() addsimps [quorem_def,
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
    93
					    pos_times_pos_is_pos])));
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
    94
(*base case: a<b*)
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
    95
by (asm_full_simp_tac (simpset() addsimps [posDivAlg_eqn]) 1);
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
    96
(*main argument*)
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
    97
by (stac posDivAlg_eqn 1);
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
    98
by (ALLGOALS Asm_simp_tac);
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
    99
by (etac splitE 1);
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   100
by Auto_tac;
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   101
(*the "add one" case*)
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   102
by (asm_full_simp_tac (simpset() addsimps [zadd_zmult_distrib2]) 1);
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   103
(*the "just double" case*)
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   104
by (asm_full_simp_tac (simpset() addsimps zcompare_rls@[zmult_2_right]) 1);
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   105
qed_spec_mp "posDivAlg_correct";
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   106
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   107
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   108
(*** Correctness of negDivAlg, the division algorithm for a<0 and b>0 ***)
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   109
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   110
(*Proving negDivAlg's termination condition*)
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   111
val [tc] = negDivAlg.tcs;
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   112
goalw_cterm [] (cterm_of (sign_of thy) (HOLogic.mk_Trueprop tc));
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   113
by (auto_tac (claset(), simpset() addsimps [zmult_2_right]));
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   114
val lemma = result();
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   115
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   116
(* removing the termination condition from the generated theorems *)
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   117
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   118
bind_thm ("negDivAlg_raw_eqn", lemma RS hd negDivAlg.rules);
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   119
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   120
(**use with simproc to avoid re-proving the premise*)
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   121
Goal "#0 < b ==> \
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   122
\     negDivAlg (a,b) =      \
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   123
\      (if #0<=a+b then (#-1,a+b) else adjust a b (negDivAlg(a, #2*b)))";
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   124
by (rtac (negDivAlg_raw_eqn RS trans) 1);
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   125
by (Asm_simp_tac 1);
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   126
qed "negDivAlg_eqn";
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   127
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   128
val negDivAlg_induct = lemma RS negDivAlg.induct;
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   129
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   130
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   131
(*Correctness of negDivAlg: it computes quotients correctly
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   132
  It doesn't work if a=0 because the 0/b=0 rather than -1*)
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   133
Goal "a < #0 --> #0 < b --> quorem ((a, b), negDivAlg (a, b))";
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   134
by (res_inst_tac [("u", "a"), ("v", "b")] negDivAlg_induct 1);
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   135
by Auto_tac;
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   136
by (ALLGOALS 
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   137
    (asm_full_simp_tac (simpset() addsimps [quorem_def,
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   138
					    pos_times_pos_is_pos])));
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   139
(*base case: 0<=a+b*)
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   140
by (asm_full_simp_tac (simpset() addsimps [negDivAlg_eqn]) 1);
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   141
(*main argument*)
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   142
by (stac negDivAlg_eqn 1);
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   143
by (ALLGOALS Asm_simp_tac);
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   144
by (etac splitE 1);
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   145
by Auto_tac;
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   146
(*the "add one" case*)
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   147
by (asm_full_simp_tac (simpset() addsimps [zadd_zmult_distrib2]) 1);
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   148
(*the "just double" case*)
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   149
by (asm_full_simp_tac (simpset() addsimps zcompare_rls@[zmult_2_right]) 1);
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   150
qed_spec_mp "negDivAlg_correct";
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   151
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   152
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   153
(*** Existence shown by proving the division algorithm to be correct ***)
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   154
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   155
(*the case a=0*)
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   156
Goal "b ~= #0 ==> quorem ((#0,b), (#0,#0))";
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   157
by (auto_tac (claset(), 
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   158
	      simpset() addsimps [quorem_def, linorder_neq_iff]));
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   159
qed "quorem_0";
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   160
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   161
Goal "posDivAlg (#0, b) = (#0, #0)";
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   162
by (stac posDivAlg_raw_eqn 1);
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   163
by Auto_tac;
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   164
qed "posDivAlg_0";
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   165
Addsimps [posDivAlg_0];
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   166
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   167
Goal "negDivAlg (#-1, b) = (#-1, b-#1)";
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   168
by (stac negDivAlg_raw_eqn 1);
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   169
by Auto_tac;
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   170
qed "negDivAlg_minus1";
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   171
Addsimps [negDivAlg_minus1];
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   172
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   173
Goalw [negateSnd_def] "negateSnd(q,r) = (q,-r)";
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   174
by Auto_tac;
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   175
qed "negateSnd_eq";
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   176
Addsimps [negateSnd_eq];
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   177
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   178
Goal "quorem ((-a,-b), qr) ==> quorem ((a,b), negateSnd qr)";
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   179
by (auto_tac (claset(), simpset() addsimps split_ifs@[quorem_def]));
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   180
qed "quorem_neg";
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   181
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   182
Goal "b ~= #0 ==> quorem ((a,b), divAlg(a,b))";
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   183
by (auto_tac (claset(), 
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   184
	      simpset() addsimps [quorem_0, divAlg_def]));
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   185
by (REPEAT_FIRST (resolve_tac [quorem_neg, posDivAlg_correct,
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   186
			       negDivAlg_correct]));
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   187
by (auto_tac (claset(), 
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   188
	      simpset() addsimps [quorem_def, linorder_neq_iff]));
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   189
qed "divAlg_correct";
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   190
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   191
Goal "b ~= (#0::int) ==> a = b * (a div b) + (a mod b)";
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   192
by (cut_inst_tac [("a","a"),("b","b")] divAlg_correct 1);
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   193
by (auto_tac (claset(), 
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   194
	      simpset() addsimps [quorem_def, div_def, mod_def]));
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   195
qed "zmod_zdiv_equality";  
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   196
   (*the name mod_div_equality would hide the other one proved in Divides.ML
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   197
     existing users aren't using name spaces for theorems*)
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   198
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   199
Goal "(#0::int) < b ==> #0 <= a mod b & a mod b < b";
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   200
by (cut_inst_tac [("a","a"),("b","b")] divAlg_correct 1);
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   201
by (auto_tac (claset(), 
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   202
	      simpset() addsimps [quorem_def, mod_def]));
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   203
bind_thm ("pos_mod_sign", result() RS conjunct1);
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   204
bind_thm ("pos_mod_bound", result() RS conjunct2);
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   205
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   206
Goal "b < (#0::int) ==> a mod b <= #0 & b < a mod b";
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   207
by (cut_inst_tac [("a","a"),("b","b")] divAlg_correct 1);
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   208
by (auto_tac (claset(), 
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   209
	      simpset() addsimps [quorem_def, div_def, mod_def]));
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   210
bind_thm ("neg_mod_sign", result() RS conjunct1);
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   211
bind_thm ("neg_mod_bound", result() RS conjunct2);
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   212
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   213
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   214
(*** Computation of division and remainder ***)
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   215
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   216
Goal "(#0::int) div b = #0";
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   217
by (simp_tac (simpset() addsimps [div_def, divAlg_def]) 1);
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   218
qed "div_zero";
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   219
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   220
Goal "(#0::int) mod b = #0";
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   221
by (simp_tac (simpset() addsimps [mod_def, divAlg_def]) 1);
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   222
qed "mod_zero";
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   223
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   224
Addsimps [div_zero, mod_zero];
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   225
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   226
(** a positive, b positive **)
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   227
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   228
Goal "[| #0 < a;  #0 < b |] ==> a div b = fst (posDivAlg(a,b))";
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   229
by (asm_simp_tac (simpset() addsimps [div_def, divAlg_def]) 1);
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   230
qed "div_pos_pos";
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   231
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   232
Goal "[| #0 < a;  #0 < b |] ==> a mod b = snd (posDivAlg(a,b))";
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   233
by (asm_simp_tac (simpset() addsimps [mod_def, divAlg_def]) 1);
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   234
qed "mod_pos_pos";
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   235
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   236
(** a negative, b positive **)
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   237
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   238
Goal "[| a < #0;  #0 < b |] ==> a div b = fst (negDivAlg(a,b))";
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   239
by (asm_simp_tac (simpset() addsimps [div_def, divAlg_def]) 1);
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   240
qed "div_neg_pos";
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   241
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   242
Goal "[| a < #0;  #0 < b |] ==> a mod b = snd (negDivAlg(a,b))";
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   243
by (asm_simp_tac (simpset() addsimps [mod_def, divAlg_def]) 1);
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   244
qed "mod_neg_pos";
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   245
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   246
(** a positive, b negative **)
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   247
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   248
Goal "[| #0 < a;  b < #0 |] ==> a div b = fst (negateSnd(negDivAlg(-a,-b)))";
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   249
by (asm_simp_tac (simpset() addsimps [div_def, divAlg_def]) 1);
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   250
qed "div_pos_neg";
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   251
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   252
Goal "[| #0 < a;  b < #0 |] ==> a mod b = snd (negateSnd(negDivAlg(-a,-b)))";
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   253
by (asm_simp_tac (simpset() addsimps [mod_def, divAlg_def]) 1);
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   254
qed "mod_pos_neg";
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   255
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   256
(** a negative, b negative **)
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   257
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   258
Goal "[| a < #0;  b < #0 |] ==> a div b = fst (negateSnd(posDivAlg(-a,-b)))";
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   259
by (asm_simp_tac (simpset() addsimps [div_def, divAlg_def]) 1);
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   260
qed "div_neg_neg";
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   261
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   262
Goal "[| a < #0;  b < #0 |] ==> a mod b = snd (negateSnd(posDivAlg(-a,-b)))";
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   263
by (asm_simp_tac (simpset() addsimps [mod_def, divAlg_def]) 1);
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   264
qed "mod_neg_neg";
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   265
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   266
Addsimps (map (read_instantiate_sg (sign_of IntDiv.thy)
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   267
	       [("a", "number_of ?v"), ("b", "number_of ?w")])
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   268
	  [div_pos_pos, div_neg_pos, div_pos_neg, div_neg_neg,
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   269
	   mod_pos_pos, mod_neg_pos, mod_pos_neg, mod_neg_neg,
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   270
	   posDivAlg_eqn, negDivAlg_eqn]);
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   271
	   
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   272
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   273
(** Special-case simplification **)
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   274
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   275
Goal "a mod (#1::int) = #0";
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   276
by (cut_inst_tac [("a","a"),("b","#1")] pos_mod_sign 1);
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   277
by (cut_inst_tac [("a","a"),("b","#1")] pos_mod_bound 2);
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   278
by Auto_tac;
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   279
qed "zmod_1";
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   280
Addsimps [zmod_1];
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   281
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   282
Goal "a div (#1::int) = a";
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   283
by (cut_inst_tac [("a","a"),("b","#1")] zmod_zdiv_equality 1);
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   284
by Auto_tac;
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   285
qed "zdiv_1";
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   286
Addsimps [zdiv_1];
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   287
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   288
Goal "a mod (#-1::int) = #0";
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   289
by (cut_inst_tac [("a","a"),("b","#-1")] neg_mod_sign 1);
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   290
by (cut_inst_tac [("a","a"),("b","#-1")] neg_mod_bound 2);
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   291
by Auto_tac;
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   292
qed "zmod_minus1";
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   293
Addsimps [zmod_minus1];
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   294
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   295
Goal "a div (#-1::int) = -a";
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   296
by (cut_inst_tac [("a","a"),("b","#-1")] zmod_zdiv_equality 1);
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   297
by Auto_tac;
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   298
qed "zdiv_minus1";
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   299
Addsimps [zdiv_minus1];
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   300
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   301
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   302
(** Monotonicity results **)
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   303
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   304
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   305
Goal "[| a <= a';  #0 < (b::int) |] ==> a div b <= a' div b";
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   306
by (cut_inst_tac [("a","a"),("b","b")] zmod_zdiv_equality 1);
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   307
by (cut_inst_tac [("a","a'"),("b","b")] zmod_zdiv_equality 2);
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   308
by Auto_tac;
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   309
by (rtac unique_quotient_lemma 1);
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   310
by (etac subst 1);
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   311
by (etac subst 1);
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   312
by (ALLGOALS (asm_simp_tac (simpset() addsimps [pos_mod_sign,pos_mod_bound])));
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   313
qed "zdiv_mono1";
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   314
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   315
Goal "[| a <= a';  (b::int) < #0 |] ==> a' div b <= a div b";
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   316
by (cut_inst_tac [("a","a"),("b","b")] zmod_zdiv_equality 1);
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   317
by (cut_inst_tac [("a","a'"),("b","b")] zmod_zdiv_equality 2);
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   318
by Auto_tac;
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   319
by (rtac unique_quotient_lemma_neg 1);
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   320
by (etac subst 1);
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   321
by (etac subst 1);
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   322
by (ALLGOALS (asm_simp_tac (simpset() addsimps [neg_mod_sign,neg_mod_bound])));
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   323
qed "zdiv_mono1_neg";
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   324
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   325
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   326
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   327
(** The division algorithm in ML **)
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   328
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   329
fun posDivAlg (a,b) =
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   330
  if a<b then (0,a)
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   331
  else let val (q,r) = posDivAlg(a, 2*b)
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   332
           in  if 0<=r-b then (2*q+1, r-b)
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   333
               else (2*q, r)
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   334
       end;
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   335
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   336
fun negDivAlg (a,b) =
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   337
  if 0<=a+b then (~1,a+b)
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   338
  else let val (q,r) = negDivAlg(a, 2*b)
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   339
           in  if 0<=r-b then (2*q+1, r-b)
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   340
               else (2*q, r)
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   341
       end;
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   342
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   343
fun negateSnd (q,r:int) = (q,~r);
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   344
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   345
fun divAlg (a,b) = if 0<=a then 
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   346
                      if b>0 then posDivAlg (a,b) 
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   347
                       else if a=0 then (0,0)
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   348
                            else negateSnd (negDivAlg (~a,~b))
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   349
                   else 
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   350
                      if 0<b then negDivAlg (a,b)
eba301caceea Introduction of integer division algorithm
paulson
parents:
diff changeset
   351
                      else        negateSnd (posDivAlg (~a,~b));