author | paulson |
Tue, 18 Nov 2003 11:01:52 +0100 | |
changeset 14259 | 79f7d3451b1e |
parent 13849 | 2584233cf3ef |
child 14266 | 08b34c902618 |
permissions | -rw-r--r-- |
14259 | 1 |
(* Title: HOL/Integ/IntArith.thy |
2 |
ID: $Id$ |
|
3 |
Authors: Larry Paulson and Tobias Nipkow |
|
4 |
*) |
|
12023 | 5 |
|
6 |
header {* Integer arithmetic *} |
|
7 |
||
9436
62bb04ab4b01
rearranged setup of arithmetic procedures, avoiding global reference values;
wenzelm
parents:
9214
diff
changeset
|
8 |
theory IntArith = Bin |
14259 | 9 |
files ("int_arith1.ML"): |
9436
62bb04ab4b01
rearranged setup of arithmetic procedures, avoiding global reference values;
wenzelm
parents:
9214
diff
changeset
|
10 |
|
12023 | 11 |
use "int_arith1.ML" |
12 |
setup int_arith_setup |
|
14259 | 13 |
|
14 |
lemma zle_diff1_eq [simp]: "(w <= z - (1::int)) = (w<(z::int))" |
|
15 |
by arith |
|
16 |
||
17 |
lemma zle_add1_eq_le [simp]: "(w < z + 1) = (w<=(z::int))" |
|
18 |
by arith |
|
19 |
||
20 |
lemma zadd_left_cancel0 [simp]: "(z = z + w) = (w = (0::int))" |
|
21 |
by arith |
|
22 |
||
23 |
subsection{*Results about @{term nat}*} |
|
24 |
||
25 |
lemma nonneg_eq_int: "[| 0 <= z; !!m. z = int m ==> P |] ==> P" |
|
26 |
by (blast dest: nat_0_le sym) |
|
27 |
||
28 |
lemma nat_eq_iff: "(nat w = m) = (if 0 <= w then w = int m else m=0)" |
|
29 |
by auto |
|
30 |
||
31 |
lemma nat_eq_iff2: "(m = nat w) = (if 0 <= w then w = int m else m=0)" |
|
32 |
by auto |
|
33 |
||
34 |
lemma nat_less_iff: "0 <= w ==> (nat w < m) = (w < int m)" |
|
35 |
apply (rule iffI) |
|
36 |
apply (erule nat_0_le [THEN subst]) |
|
37 |
apply (simp_all del: zless_int add: zless_int [symmetric]) |
|
38 |
done |
|
39 |
||
40 |
lemma int_eq_iff: "(int m = z) = (m = nat z & 0 <= z)" |
|
41 |
by (auto simp add: nat_eq_iff2) |
|
42 |
||
43 |
||
44 |
(*Users don't want to see (int 0), int(Suc 0) or w + - z*) |
|
45 |
declare Zero_int_def [symmetric, simp] |
|
46 |
declare One_int_def [symmetric, simp] |
|
47 |
||
48 |
text{*cooper.ML refers to this theorem*} |
|
49 |
lemmas zdiff_def_symmetric = zdiff_def [symmetric, simp] |
|
50 |
||
51 |
lemma nat_0: "nat 0 = 0" |
|
52 |
by (simp add: nat_eq_iff) |
|
53 |
||
54 |
lemma nat_1: "nat 1 = Suc 0" |
|
55 |
by (subst nat_eq_iff, simp) |
|
56 |
||
57 |
lemma nat_2: "nat 2 = Suc (Suc 0)" |
|
58 |
by (subst nat_eq_iff, simp) |
|
59 |
||
60 |
lemma nat_less_eq_zless: "0 <= w ==> (nat w < nat z) = (w<z)" |
|
61 |
apply (case_tac "neg z") |
|
62 |
apply (auto simp add: nat_less_iff) |
|
63 |
apply (auto intro: zless_trans simp add: neg_eq_less_0 zle_def) |
|
64 |
done |
|
65 |
||
66 |
lemma nat_le_eq_zle: "0 < w | 0 <= z ==> (nat w <= nat z) = (w<=z)" |
|
67 |
by (auto simp add: linorder_not_less [symmetric] zless_nat_conj) |
|
68 |
||
69 |
subsection{*@{term abs}: Absolute Value, as an Integer*} |
|
70 |
||
71 |
(* Simpler: use zabs_def as rewrite rule |
|
72 |
but arith_tac is not parameterized by such simp rules |
|
73 |
*) |
|
74 |
||
75 |
lemma zabs_split: "P(abs(i::int)) = ((0 <= i --> P i) & (i < 0 --> P(-i)))" |
|
76 |
by (simp add: zabs_def) |
|
77 |
||
78 |
lemma zero_le_zabs [iff]: "0 <= abs (z::int)" |
|
79 |
by (simp add: zabs_def) |
|
80 |
||
81 |
||
82 |
text{*This simplifies expressions of the form @{term "int n = z"} where |
|
83 |
z is an integer literal.*} |
|
84 |
declare int_eq_iff [of _ "number_of v", standard, simp] |
|
13837
8dd150d36c65
Reorganized, moving many results about the integer dvd relation from IntPrimes
paulson
parents:
13685
diff
changeset
|
85 |
|
12023 | 86 |
declare zabs_split [arith_split] |
87 |
||
13837
8dd150d36c65
Reorganized, moving many results about the integer dvd relation from IntPrimes
paulson
parents:
13685
diff
changeset
|
88 |
lemma zabs_eq_iff: |
8dd150d36c65
Reorganized, moving many results about the integer dvd relation from IntPrimes
paulson
parents:
13685
diff
changeset
|
89 |
"(abs (z::int) = w) = (z = w \<and> 0 <= z \<or> z = -w \<and> z < 0)" |
8dd150d36c65
Reorganized, moving many results about the integer dvd relation from IntPrimes
paulson
parents:
13685
diff
changeset
|
90 |
by (auto simp add: zabs_def) |
8dd150d36c65
Reorganized, moving many results about the integer dvd relation from IntPrimes
paulson
parents:
13685
diff
changeset
|
91 |
|
13849 | 92 |
lemma int_nat_eq [simp]: "int (nat z) = (if 0 \<le> z then z else 0)" |
93 |
by simp |
|
94 |
||
13575 | 95 |
lemma split_nat[arith_split]: |
14259 | 96 |
"P(nat(i::int)) = ((\<forall>n. i = int n \<longrightarrow> P n) & (i < 0 \<longrightarrow> P 0))" |
13575 | 97 |
(is "?P = (?L & ?R)") |
98 |
proof (cases "i < 0") |
|
99 |
case True thus ?thesis by simp |
|
100 |
next |
|
101 |
case False |
|
102 |
have "?P = ?L" |
|
103 |
proof |
|
104 |
assume ?P thus ?L using False by clarsimp |
|
105 |
next |
|
106 |
assume ?L thus ?P using False by simp |
|
107 |
qed |
|
108 |
with False show ?thesis by simp |
|
109 |
qed |
|
110 |
||
13685 | 111 |
subsubsection "Induction principles for int" |
112 |
||
113 |
(* `set:int': dummy construction *) |
|
114 |
theorem int_ge_induct[case_names base step,induct set:int]: |
|
115 |
assumes ge: "k \<le> (i::int)" and |
|
116 |
base: "P(k)" and |
|
117 |
step: "\<And>i. \<lbrakk>k \<le> i; P i\<rbrakk> \<Longrightarrow> P(i+1)" |
|
118 |
shows "P i" |
|
119 |
proof - |
|
120 |
{ fix n have "\<And>i::int. n = nat(i-k) \<Longrightarrow> k <= i \<Longrightarrow> P i" |
|
121 |
proof (induct n) |
|
122 |
case 0 |
|
123 |
hence "i = k" by arith |
|
124 |
thus "P i" using base by simp |
|
125 |
next |
|
126 |
case (Suc n) |
|
127 |
hence "n = nat((i - 1) - k)" by arith |
|
128 |
moreover |
|
129 |
have ki1: "k \<le> i - 1" using Suc.prems by arith |
|
130 |
ultimately |
|
131 |
have "P(i - 1)" by(rule Suc.hyps) |
|
132 |
from step[OF ki1 this] show ?case by simp |
|
133 |
qed |
|
134 |
} |
|
135 |
from this ge show ?thesis by fast |
|
136 |
qed |
|
137 |
||
138 |
(* `set:int': dummy construction *) |
|
139 |
theorem int_gr_induct[case_names base step,induct set:int]: |
|
140 |
assumes gr: "k < (i::int)" and |
|
141 |
base: "P(k+1)" and |
|
142 |
step: "\<And>i. \<lbrakk>k < i; P i\<rbrakk> \<Longrightarrow> P(i+1)" |
|
143 |
shows "P i" |
|
144 |
apply(rule int_ge_induct[of "k + 1"]) |
|
145 |
using gr apply arith |
|
146 |
apply(rule base) |
|
14259 | 147 |
apply (rule step, simp+) |
13685 | 148 |
done |
149 |
||
150 |
theorem int_le_induct[consumes 1,case_names base step]: |
|
151 |
assumes le: "i \<le> (k::int)" and |
|
152 |
base: "P(k)" and |
|
153 |
step: "\<And>i. \<lbrakk>i \<le> k; P i\<rbrakk> \<Longrightarrow> P(i - 1)" |
|
154 |
shows "P i" |
|
155 |
proof - |
|
156 |
{ fix n have "\<And>i::int. n = nat(k-i) \<Longrightarrow> i <= k \<Longrightarrow> P i" |
|
157 |
proof (induct n) |
|
158 |
case 0 |
|
159 |
hence "i = k" by arith |
|
160 |
thus "P i" using base by simp |
|
161 |
next |
|
162 |
case (Suc n) |
|
163 |
hence "n = nat(k - (i+1))" by arith |
|
164 |
moreover |
|
165 |
have ki1: "i + 1 \<le> k" using Suc.prems by arith |
|
166 |
ultimately |
|
167 |
have "P(i+1)" by(rule Suc.hyps) |
|
168 |
from step[OF ki1 this] show ?case by simp |
|
169 |
qed |
|
170 |
} |
|
171 |
from this le show ?thesis by fast |
|
172 |
qed |
|
173 |
||
174 |
theorem int_less_induct[consumes 1,case_names base step]: |
|
175 |
assumes less: "(i::int) < k" and |
|
176 |
base: "P(k - 1)" and |
|
177 |
step: "\<And>i. \<lbrakk>i < k; P i\<rbrakk> \<Longrightarrow> P(i - 1)" |
|
178 |
shows "P i" |
|
179 |
apply(rule int_le_induct[of _ "k - 1"]) |
|
180 |
using less apply arith |
|
181 |
apply(rule base) |
|
14259 | 182 |
apply (rule step, simp+) |
183 |
done |
|
184 |
||
185 |
subsection{*Simple Equations*} |
|
186 |
||
187 |
lemma int_diff_minus_eq [simp]: "x - - y = x + (y::int)" |
|
188 |
by simp |
|
189 |
||
190 |
lemma abs_abs [simp]: "abs(abs(x::int)) = abs(x)" |
|
191 |
by arith |
|
192 |
||
193 |
lemma abs_minus [simp]: "abs(-(x::int)) = abs(x)" |
|
194 |
by arith |
|
195 |
||
196 |
lemma triangle_ineq: "abs(x+y) <= abs(x) + abs(y::int)" |
|
197 |
by arith |
|
198 |
||
199 |
||
200 |
subsection{*Intermediate value theorems*} |
|
201 |
||
202 |
lemma int_val_lemma: |
|
203 |
"(\<forall>i<n::nat. abs(f(i+1) - f i) \<le> 1) --> |
|
204 |
f 0 \<le> k --> k \<le> f n --> (\<exists>i \<le> n. f i = (k::int))" |
|
205 |
apply (induct_tac "n") |
|
206 |
apply (simp (no_asm_simp)) |
|
207 |
apply (intro strip) |
|
208 |
apply (erule impE, simp) |
|
209 |
apply (erule_tac x = n in allE, simp) |
|
210 |
apply (case_tac "k = f (n+1) ") |
|
211 |
apply force |
|
212 |
apply (erule impE) |
|
213 |
apply (simp add: zabs_def split add: split_if_asm) |
|
214 |
apply (blast intro: le_SucI) |
|
215 |
done |
|
216 |
||
217 |
lemmas nat0_intermed_int_val = int_val_lemma [rule_format (no_asm)] |
|
218 |
||
219 |
lemma nat_intermed_int_val: |
|
220 |
"[| \<forall>i. m \<le> i & i < n --> abs(f(i + 1::nat) - f i) \<le> 1; m < n; |
|
221 |
f m \<le> k; k \<le> f n |] ==> ? i. m \<le> i & i \<le> n & f i = (k::int)" |
|
222 |
apply (cut_tac n = "n-m" and f = "%i. f (i+m) " and k = k |
|
223 |
in int_val_lemma) |
|
224 |
apply simp |
|
225 |
apply (erule impE) |
|
226 |
apply (intro strip) |
|
227 |
apply (erule_tac x = "i+m" in allE, arith) |
|
228 |
apply (erule exE) |
|
229 |
apply (rule_tac x = "i+m" in exI, arith) |
|
230 |
done |
|
231 |
||
232 |
||
233 |
subsection{*Some convenient biconditionals for products of signs*} |
|
234 |
||
235 |
lemma zmult_pos: "[| (0::int) < i; 0 < j |] ==> 0 < i*j" |
|
236 |
by (drule zmult_zless_mono1, auto) |
|
237 |
||
238 |
lemma zmult_neg: "[| i < (0::int); j < 0 |] ==> 0 < i*j" |
|
239 |
by (drule zmult_zless_mono1_neg, auto) |
|
240 |
||
241 |
lemma zmult_pos_neg: "[| (0::int) < i; j < 0 |] ==> i*j < 0" |
|
242 |
by (drule zmult_zless_mono1_neg, auto) |
|
243 |
||
244 |
lemma int_0_less_mult_iff: "((0::int) < x*y) = (0 < x & 0 < y | x < 0 & y < 0)" |
|
245 |
apply (auto simp add: order_le_less linorder_not_less zmult_pos zmult_neg) |
|
246 |
apply (rule_tac [!] ccontr) |
|
247 |
apply (auto simp add: order_le_less linorder_not_less) |
|
248 |
apply (erule_tac [!] rev_mp) |
|
249 |
apply (drule_tac [!] zmult_pos_neg) |
|
250 |
apply (auto dest: order_less_not_sym simp add: zmult_commute) |
|
251 |
done |
|
252 |
||
253 |
lemma int_0_le_mult_iff: "((0::int) \<le> x*y) = (0 \<le> x & 0 \<le> y | x \<le> 0 & y \<le> 0)" |
|
254 |
by (auto simp add: order_le_less linorder_not_less int_0_less_mult_iff) |
|
255 |
||
256 |
lemma zmult_less_0_iff: "(x*y < (0::int)) = (0 < x & y < 0 | x < 0 & 0 < y)" |
|
257 |
by (auto simp add: int_0_le_mult_iff linorder_not_le [symmetric]) |
|
258 |
||
259 |
lemma zmult_le_0_iff: "(x*y \<le> (0::int)) = (0 \<le> x & y \<le> 0 | x \<le> 0 & 0 \<le> y)" |
|
260 |
by (auto dest: order_less_not_sym simp add: int_0_less_mult_iff linorder_not_less [symmetric]) |
|
261 |
||
262 |
lemma abs_mult: "abs (x * y) = abs x * abs (y::int)" |
|
263 |
by (simp del: number_of_reorient split |
|
264 |
add: zabs_split split add: zabs_split add: zmult_less_0_iff zle_def) |
|
265 |
||
266 |
lemma abs_eq_0 [iff]: "(abs x = 0) = (x = (0::int))" |
|
267 |
by (simp split add: zabs_split) |
|
268 |
||
269 |
lemma zero_less_abs_iff [iff]: "(0 < abs x) = (x ~= (0::int))" |
|
270 |
by (simp split add: zabs_split, arith) |
|
271 |
||
272 |
(* THIS LOOKS WRONG: [intro]*) |
|
273 |
lemma square_nonzero [simp]: "0 \<le> x * (x::int)" |
|
274 |
apply (subgoal_tac " (- x) * x \<le> 0") |
|
275 |
apply simp |
|
276 |
apply (simp only: zmult_le_0_iff, auto) |
|
277 |
done |
|
278 |
||
279 |
||
280 |
subsection{*Products and 1, by T. M. Rasmussen*} |
|
281 |
||
282 |
lemma zmult_eq_self_iff: "(m = m*(n::int)) = (n = 1 | m = 0)" |
|
283 |
apply auto |
|
284 |
apply (subgoal_tac "m*1 = m*n") |
|
285 |
apply (drule zmult_cancel1 [THEN iffD1], auto) |
|
13685 | 286 |
done |
287 |
||
14259 | 288 |
lemma zless_1_zmult: "[| 1 < m; 1 < n |] ==> 1 < m*(n::int)" |
289 |
apply (rule_tac y = "1*n" in order_less_trans) |
|
290 |
apply (rule_tac [2] zmult_zless_mono1) |
|
291 |
apply (simp_all (no_asm_simp)) |
|
292 |
done |
|
293 |
||
294 |
lemma pos_zmult_eq_1_iff: "0 < (m::int) ==> (m * n = 1) = (m = 1 & n = 1)" |
|
295 |
apply auto |
|
296 |
apply (case_tac "m=1") |
|
297 |
apply (case_tac [2] "n=1") |
|
298 |
apply (case_tac [4] "m=1") |
|
299 |
apply (case_tac [5] "n=1", auto) |
|
300 |
apply (tactic"distinct_subgoals_tac") |
|
301 |
apply (subgoal_tac "1<m*n", simp) |
|
302 |
apply (rule zless_1_zmult, arith) |
|
303 |
apply (subgoal_tac "0<n", arith) |
|
304 |
apply (subgoal_tac "0<m*n") |
|
305 |
apply (drule int_0_less_mult_iff [THEN iffD1], auto) |
|
306 |
done |
|
307 |
||
308 |
lemma zmult_eq_1_iff: "(m*n = (1::int)) = ((m = 1 & n = 1) | (m = -1 & n = -1))" |
|
309 |
apply (case_tac "0<m") |
|
310 |
apply (simp (no_asm_simp) add: pos_zmult_eq_1_iff) |
|
311 |
apply (case_tac "m=0") |
|
312 |
apply (simp (no_asm_simp) del: number_of_reorient) |
|
313 |
apply (subgoal_tac "0 < -m") |
|
314 |
apply (drule_tac n = "-n" in pos_zmult_eq_1_iff, auto) |
|
315 |
done |
|
316 |
||
317 |
||
318 |
subsection{*More about nat*} |
|
319 |
||
320 |
lemma nat_add_distrib: |
|
321 |
"[| (0::int) \<le> z; 0 \<le> z' |] ==> nat (z+z') = nat z + nat z'" |
|
322 |
apply (rule inj_int [THEN injD]) |
|
323 |
apply (simp (no_asm_simp) add: zadd_int [symmetric]) |
|
324 |
done |
|
325 |
||
326 |
lemma nat_diff_distrib: |
|
327 |
"[| (0::int) \<le> z'; z' \<le> z |] ==> nat (z-z') = nat z - nat z'" |
|
328 |
apply (rule inj_int [THEN injD]) |
|
329 |
apply (simp (no_asm_simp) add: zdiff_int [symmetric] nat_le_eq_zle) |
|
330 |
done |
|
331 |
||
332 |
lemma nat_mult_distrib: "(0::int) \<le> z ==> nat (z*z') = nat z * nat z'" |
|
333 |
apply (case_tac "0 \<le> z'") |
|
334 |
apply (rule inj_int [THEN injD]) |
|
335 |
apply (simp (no_asm_simp) add: zmult_int [symmetric] int_0_le_mult_iff) |
|
336 |
apply (simp add: zmult_le_0_iff) |
|
337 |
done |
|
338 |
||
339 |
lemma nat_mult_distrib_neg: "z \<le> (0::int) ==> nat(z*z') = nat(-z) * nat(-z')" |
|
340 |
apply (rule trans) |
|
341 |
apply (rule_tac [2] nat_mult_distrib, auto) |
|
342 |
done |
|
343 |
||
344 |
lemma nat_abs_mult_distrib: "nat (abs (w * z)) = nat (abs w) * nat (abs z)" |
|
345 |
apply (case_tac "z=0 | w=0") |
|
346 |
apply (auto simp add: zabs_def nat_mult_distrib [symmetric] |
|
347 |
nat_mult_distrib_neg [symmetric] zmult_less_0_iff) |
|
348 |
done |
|
349 |
||
350 |
ML |
|
351 |
{* |
|
352 |
val zle_diff1_eq = thm "zle_diff1_eq"; |
|
353 |
val zle_add1_eq_le = thm "zle_add1_eq_le"; |
|
354 |
val nonneg_eq_int = thm "nonneg_eq_int"; |
|
355 |
val nat_eq_iff = thm "nat_eq_iff"; |
|
356 |
val nat_eq_iff2 = thm "nat_eq_iff2"; |
|
357 |
val nat_less_iff = thm "nat_less_iff"; |
|
358 |
val int_eq_iff = thm "int_eq_iff"; |
|
359 |
val nat_0 = thm "nat_0"; |
|
360 |
val nat_1 = thm "nat_1"; |
|
361 |
val nat_2 = thm "nat_2"; |
|
362 |
val nat_less_eq_zless = thm "nat_less_eq_zless"; |
|
363 |
val nat_le_eq_zle = thm "nat_le_eq_zle"; |
|
364 |
val zabs_split = thm "zabs_split"; |
|
365 |
val zero_le_zabs = thm "zero_le_zabs"; |
|
366 |
||
367 |
val int_diff_minus_eq = thm "int_diff_minus_eq"; |
|
368 |
val abs_abs = thm "abs_abs"; |
|
369 |
val abs_minus = thm "abs_minus"; |
|
370 |
val triangle_ineq = thm "triangle_ineq"; |
|
371 |
val nat_intermed_int_val = thm "nat_intermed_int_val"; |
|
372 |
val zmult_pos = thm "zmult_pos"; |
|
373 |
val zmult_neg = thm "zmult_neg"; |
|
374 |
val zmult_pos_neg = thm "zmult_pos_neg"; |
|
375 |
val int_0_less_mult_iff = thm "int_0_less_mult_iff"; |
|
376 |
val int_0_le_mult_iff = thm "int_0_le_mult_iff"; |
|
377 |
val zmult_less_0_iff = thm "zmult_less_0_iff"; |
|
378 |
val zmult_le_0_iff = thm "zmult_le_0_iff"; |
|
379 |
val abs_mult = thm "abs_mult"; |
|
380 |
val abs_eq_0 = thm "abs_eq_0"; |
|
381 |
val zero_less_abs_iff = thm "zero_less_abs_iff"; |
|
382 |
val square_nonzero = thm "square_nonzero"; |
|
383 |
val zmult_eq_self_iff = thm "zmult_eq_self_iff"; |
|
384 |
val zless_1_zmult = thm "zless_1_zmult"; |
|
385 |
val pos_zmult_eq_1_iff = thm "pos_zmult_eq_1_iff"; |
|
386 |
val zmult_eq_1_iff = thm "zmult_eq_1_iff"; |
|
387 |
val nat_add_distrib = thm "nat_add_distrib"; |
|
388 |
val nat_diff_distrib = thm "nat_diff_distrib"; |
|
389 |
val nat_mult_distrib = thm "nat_mult_distrib"; |
|
390 |
val nat_mult_distrib_neg = thm "nat_mult_distrib_neg"; |
|
391 |
val nat_abs_mult_distrib = thm "nat_abs_mult_distrib"; |
|
392 |
*} |
|
393 |
||
7707 | 394 |
end |