1 (* Title: HOL/Library/Code_Numeral_Types.thy |
|
2 Author: Florian Haftmann, TU Muenchen |
|
3 *) |
|
4 |
|
5 header {* Numeric types for code generation onto target language numerals only *} |
|
6 |
|
7 theory Code_Numeral_Types |
|
8 imports Main Nat_Transfer Divides Lifting |
|
9 begin |
|
10 |
|
11 subsection {* Type of target language integers *} |
|
12 |
|
13 typedef integer = "UNIV \<Colon> int set" |
|
14 morphisms int_of_integer integer_of_int .. |
|
15 |
|
16 setup_lifting (no_code) type_definition_integer |
|
17 |
|
18 lemma integer_eq_iff: |
|
19 "k = l \<longleftrightarrow> int_of_integer k = int_of_integer l" |
|
20 by transfer rule |
|
21 |
|
22 lemma integer_eqI: |
|
23 "int_of_integer k = int_of_integer l \<Longrightarrow> k = l" |
|
24 using integer_eq_iff [of k l] by simp |
|
25 |
|
26 lemma int_of_integer_integer_of_int [simp]: |
|
27 "int_of_integer (integer_of_int k) = k" |
|
28 by transfer rule |
|
29 |
|
30 lemma integer_of_int_int_of_integer [simp]: |
|
31 "integer_of_int (int_of_integer k) = k" |
|
32 by transfer rule |
|
33 |
|
34 instantiation integer :: ring_1 |
|
35 begin |
|
36 |
|
37 lift_definition zero_integer :: integer |
|
38 is "0 :: int" |
|
39 . |
|
40 |
|
41 declare zero_integer.rep_eq [simp] |
|
42 |
|
43 lift_definition one_integer :: integer |
|
44 is "1 :: int" |
|
45 . |
|
46 |
|
47 declare one_integer.rep_eq [simp] |
|
48 |
|
49 lift_definition plus_integer :: "integer \<Rightarrow> integer \<Rightarrow> integer" |
|
50 is "plus :: int \<Rightarrow> int \<Rightarrow> int" |
|
51 . |
|
52 |
|
53 declare plus_integer.rep_eq [simp] |
|
54 |
|
55 lift_definition uminus_integer :: "integer \<Rightarrow> integer" |
|
56 is "uminus :: int \<Rightarrow> int" |
|
57 . |
|
58 |
|
59 declare uminus_integer.rep_eq [simp] |
|
60 |
|
61 lift_definition minus_integer :: "integer \<Rightarrow> integer \<Rightarrow> integer" |
|
62 is "minus :: int \<Rightarrow> int \<Rightarrow> int" |
|
63 . |
|
64 |
|
65 declare minus_integer.rep_eq [simp] |
|
66 |
|
67 lift_definition times_integer :: "integer \<Rightarrow> integer \<Rightarrow> integer" |
|
68 is "times :: int \<Rightarrow> int \<Rightarrow> int" |
|
69 . |
|
70 |
|
71 declare times_integer.rep_eq [simp] |
|
72 |
|
73 instance proof |
|
74 qed (transfer, simp add: algebra_simps)+ |
|
75 |
|
76 end |
|
77 |
|
78 lemma [transfer_rule]: |
|
79 "fun_rel HOL.eq cr_integer (of_nat :: nat \<Rightarrow> int) (of_nat :: nat \<Rightarrow> integer)" |
|
80 by (unfold of_nat_def [abs_def]) transfer_prover |
|
81 |
|
82 lemma [transfer_rule]: |
|
83 "fun_rel HOL.eq cr_integer (\<lambda>k :: int. k :: int) (of_int :: int \<Rightarrow> integer)" |
|
84 proof - |
|
85 have "fun_rel HOL.eq cr_integer (of_int :: int \<Rightarrow> int) (of_int :: int \<Rightarrow> integer)" |
|
86 by (unfold of_int_of_nat [abs_def]) transfer_prover |
|
87 then show ?thesis by (simp add: id_def) |
|
88 qed |
|
89 |
|
90 lemma [transfer_rule]: |
|
91 "fun_rel HOL.eq cr_integer (numeral :: num \<Rightarrow> int) (numeral :: num \<Rightarrow> integer)" |
|
92 proof - |
|
93 have "fun_rel HOL.eq cr_integer (numeral :: num \<Rightarrow> int) (\<lambda>n. of_int (numeral n))" |
|
94 by transfer_prover |
|
95 then show ?thesis by simp |
|
96 qed |
|
97 |
|
98 lemma [transfer_rule]: |
|
99 "fun_rel HOL.eq cr_integer (neg_numeral :: num \<Rightarrow> int) (neg_numeral :: num \<Rightarrow> integer)" |
|
100 by (unfold neg_numeral_def [abs_def]) transfer_prover |
|
101 |
|
102 lemma [transfer_rule]: |
|
103 "fun_rel HOL.eq (fun_rel HOL.eq cr_integer) (Num.sub :: _ \<Rightarrow> _ \<Rightarrow> int) (Num.sub :: _ \<Rightarrow> _ \<Rightarrow> integer)" |
|
104 by (unfold Num.sub_def [abs_def]) transfer_prover |
|
105 |
|
106 lemma int_of_integer_of_nat [simp]: |
|
107 "int_of_integer (of_nat n) = of_nat n" |
|
108 by transfer rule |
|
109 |
|
110 lift_definition integer_of_nat :: "nat \<Rightarrow> integer" |
|
111 is "of_nat :: nat \<Rightarrow> int" |
|
112 . |
|
113 |
|
114 lemma int_of_integer_integer_of_nat [simp]: |
|
115 "int_of_integer (integer_of_nat n) = of_nat n" |
|
116 by transfer rule |
|
117 |
|
118 lift_definition nat_of_integer :: "integer \<Rightarrow> nat" |
|
119 is Int.nat |
|
120 . |
|
121 |
|
122 lemma nat_of_integer_of_nat [simp]: |
|
123 "nat_of_integer (of_nat n) = n" |
|
124 by transfer simp |
|
125 |
|
126 lemma int_of_integer_of_int [simp]: |
|
127 "int_of_integer (of_int k) = k" |
|
128 by transfer simp |
|
129 |
|
130 lemma nat_of_integer_integer_of_nat [simp]: |
|
131 "nat_of_integer (integer_of_nat n) = n" |
|
132 by transfer simp |
|
133 |
|
134 lemma integer_of_int_eq_of_int [simp, code_abbrev]: |
|
135 "integer_of_int = of_int" |
|
136 by transfer (simp add: fun_eq_iff) |
|
137 |
|
138 lemma of_int_integer_of [simp]: |
|
139 "of_int (int_of_integer k) = (k :: integer)" |
|
140 by transfer rule |
|
141 |
|
142 lemma int_of_integer_numeral [simp]: |
|
143 "int_of_integer (numeral k) = numeral k" |
|
144 by transfer rule |
|
145 |
|
146 lemma int_of_integer_neg_numeral [simp]: |
|
147 "int_of_integer (neg_numeral k) = neg_numeral k" |
|
148 by transfer rule |
|
149 |
|
150 lemma int_of_integer_sub [simp]: |
|
151 "int_of_integer (Num.sub k l) = Num.sub k l" |
|
152 by transfer rule |
|
153 |
|
154 instantiation integer :: "{ring_div, equal, linordered_idom}" |
|
155 begin |
|
156 |
|
157 lift_definition div_integer :: "integer \<Rightarrow> integer \<Rightarrow> integer" |
|
158 is "Divides.div :: int \<Rightarrow> int \<Rightarrow> int" |
|
159 . |
|
160 |
|
161 declare div_integer.rep_eq [simp] |
|
162 |
|
163 lift_definition mod_integer :: "integer \<Rightarrow> integer \<Rightarrow> integer" |
|
164 is "Divides.mod :: int \<Rightarrow> int \<Rightarrow> int" |
|
165 . |
|
166 |
|
167 declare mod_integer.rep_eq [simp] |
|
168 |
|
169 lift_definition abs_integer :: "integer \<Rightarrow> integer" |
|
170 is "abs :: int \<Rightarrow> int" |
|
171 . |
|
172 |
|
173 declare abs_integer.rep_eq [simp] |
|
174 |
|
175 lift_definition sgn_integer :: "integer \<Rightarrow> integer" |
|
176 is "sgn :: int \<Rightarrow> int" |
|
177 . |
|
178 |
|
179 declare sgn_integer.rep_eq [simp] |
|
180 |
|
181 lift_definition less_eq_integer :: "integer \<Rightarrow> integer \<Rightarrow> bool" |
|
182 is "less_eq :: int \<Rightarrow> int \<Rightarrow> bool" |
|
183 . |
|
184 |
|
185 lift_definition less_integer :: "integer \<Rightarrow> integer \<Rightarrow> bool" |
|
186 is "less :: int \<Rightarrow> int \<Rightarrow> bool" |
|
187 . |
|
188 |
|
189 lift_definition equal_integer :: "integer \<Rightarrow> integer \<Rightarrow> bool" |
|
190 is "HOL.equal :: int \<Rightarrow> int \<Rightarrow> bool" |
|
191 . |
|
192 |
|
193 instance proof |
|
194 qed (transfer, simp add: algebra_simps equal less_le_not_le [symmetric] mult_strict_right_mono linear)+ |
|
195 |
|
196 end |
|
197 |
|
198 lemma [transfer_rule]: |
|
199 "fun_rel cr_integer (fun_rel cr_integer cr_integer) (min :: _ \<Rightarrow> _ \<Rightarrow> int) (min :: _ \<Rightarrow> _ \<Rightarrow> integer)" |
|
200 by (unfold min_def [abs_def]) transfer_prover |
|
201 |
|
202 lemma [transfer_rule]: |
|
203 "fun_rel cr_integer (fun_rel cr_integer cr_integer) (max :: _ \<Rightarrow> _ \<Rightarrow> int) (max :: _ \<Rightarrow> _ \<Rightarrow> integer)" |
|
204 by (unfold max_def [abs_def]) transfer_prover |
|
205 |
|
206 lemma int_of_integer_min [simp]: |
|
207 "int_of_integer (min k l) = min (int_of_integer k) (int_of_integer l)" |
|
208 by transfer rule |
|
209 |
|
210 lemma int_of_integer_max [simp]: |
|
211 "int_of_integer (max k l) = max (int_of_integer k) (int_of_integer l)" |
|
212 by transfer rule |
|
213 |
|
214 lemma nat_of_integer_non_positive [simp]: |
|
215 "k \<le> 0 \<Longrightarrow> nat_of_integer k = 0" |
|
216 by transfer simp |
|
217 |
|
218 lemma of_nat_of_integer [simp]: |
|
219 "of_nat (nat_of_integer k) = max 0 k" |
|
220 by transfer auto |
|
221 |
|
222 |
|
223 subsection {* Code theorems for target language integers *} |
|
224 |
|
225 text {* Constructors *} |
|
226 |
|
227 definition Pos :: "num \<Rightarrow> integer" |
|
228 where |
|
229 [simp, code_abbrev]: "Pos = numeral" |
|
230 |
|
231 lemma [transfer_rule]: |
|
232 "fun_rel HOL.eq cr_integer numeral Pos" |
|
233 by simp transfer_prover |
|
234 |
|
235 definition Neg :: "num \<Rightarrow> integer" |
|
236 where |
|
237 [simp, code_abbrev]: "Neg = neg_numeral" |
|
238 |
|
239 lemma [transfer_rule]: |
|
240 "fun_rel HOL.eq cr_integer neg_numeral Neg" |
|
241 by simp transfer_prover |
|
242 |
|
243 code_datatype "0::integer" Pos Neg |
|
244 |
|
245 |
|
246 text {* Auxiliary operations *} |
|
247 |
|
248 lift_definition dup :: "integer \<Rightarrow> integer" |
|
249 is "\<lambda>k::int. k + k" |
|
250 . |
|
251 |
|
252 lemma dup_code [code]: |
|
253 "dup 0 = 0" |
|
254 "dup (Pos n) = Pos (Num.Bit0 n)" |
|
255 "dup (Neg n) = Neg (Num.Bit0 n)" |
|
256 by (transfer, simp only: neg_numeral_def numeral_Bit0 minus_add_distrib)+ |
|
257 |
|
258 lift_definition sub :: "num \<Rightarrow> num \<Rightarrow> integer" |
|
259 is "\<lambda>m n. numeral m - numeral n :: int" |
|
260 . |
|
261 |
|
262 lemma sub_code [code]: |
|
263 "sub Num.One Num.One = 0" |
|
264 "sub (Num.Bit0 m) Num.One = Pos (Num.BitM m)" |
|
265 "sub (Num.Bit1 m) Num.One = Pos (Num.Bit0 m)" |
|
266 "sub Num.One (Num.Bit0 n) = Neg (Num.BitM n)" |
|
267 "sub Num.One (Num.Bit1 n) = Neg (Num.Bit0 n)" |
|
268 "sub (Num.Bit0 m) (Num.Bit0 n) = dup (sub m n)" |
|
269 "sub (Num.Bit1 m) (Num.Bit1 n) = dup (sub m n)" |
|
270 "sub (Num.Bit1 m) (Num.Bit0 n) = dup (sub m n) + 1" |
|
271 "sub (Num.Bit0 m) (Num.Bit1 n) = dup (sub m n) - 1" |
|
272 by (transfer, simp add: dbl_def dbl_inc_def dbl_dec_def)+ |
|
273 |
|
274 |
|
275 text {* Implementations *} |
|
276 |
|
277 lemma one_integer_code [code, code_unfold]: |
|
278 "1 = Pos Num.One" |
|
279 by simp |
|
280 |
|
281 lemma plus_integer_code [code]: |
|
282 "k + 0 = (k::integer)" |
|
283 "0 + l = (l::integer)" |
|
284 "Pos m + Pos n = Pos (m + n)" |
|
285 "Pos m + Neg n = sub m n" |
|
286 "Neg m + Pos n = sub n m" |
|
287 "Neg m + Neg n = Neg (m + n)" |
|
288 by (transfer, simp)+ |
|
289 |
|
290 lemma uminus_integer_code [code]: |
|
291 "uminus 0 = (0::integer)" |
|
292 "uminus (Pos m) = Neg m" |
|
293 "uminus (Neg m) = Pos m" |
|
294 by simp_all |
|
295 |
|
296 lemma minus_integer_code [code]: |
|
297 "k - 0 = (k::integer)" |
|
298 "0 - l = uminus (l::integer)" |
|
299 "Pos m - Pos n = sub m n" |
|
300 "Pos m - Neg n = Pos (m + n)" |
|
301 "Neg m - Pos n = Neg (m + n)" |
|
302 "Neg m - Neg n = sub n m" |
|
303 by (transfer, simp)+ |
|
304 |
|
305 lemma abs_integer_code [code]: |
|
306 "\<bar>k\<bar> = (if (k::integer) < 0 then - k else k)" |
|
307 by simp |
|
308 |
|
309 lemma sgn_integer_code [code]: |
|
310 "sgn k = (if k = 0 then 0 else if (k::integer) < 0 then - 1 else 1)" |
|
311 by simp |
|
312 |
|
313 lemma times_integer_code [code]: |
|
314 "k * 0 = (0::integer)" |
|
315 "0 * l = (0::integer)" |
|
316 "Pos m * Pos n = Pos (m * n)" |
|
317 "Pos m * Neg n = Neg (m * n)" |
|
318 "Neg m * Pos n = Neg (m * n)" |
|
319 "Neg m * Neg n = Pos (m * n)" |
|
320 by simp_all |
|
321 |
|
322 definition divmod_integer :: "integer \<Rightarrow> integer \<Rightarrow> integer \<times> integer" |
|
323 where |
|
324 "divmod_integer k l = (k div l, k mod l)" |
|
325 |
|
326 lemma fst_divmod [simp]: |
|
327 "fst (divmod_integer k l) = k div l" |
|
328 by (simp add: divmod_integer_def) |
|
329 |
|
330 lemma snd_divmod [simp]: |
|
331 "snd (divmod_integer k l) = k mod l" |
|
332 by (simp add: divmod_integer_def) |
|
333 |
|
334 definition divmod_abs :: "integer \<Rightarrow> integer \<Rightarrow> integer \<times> integer" |
|
335 where |
|
336 "divmod_abs k l = (\<bar>k\<bar> div \<bar>l\<bar>, \<bar>k\<bar> mod \<bar>l\<bar>)" |
|
337 |
|
338 lemma fst_divmod_abs [simp]: |
|
339 "fst (divmod_abs k l) = \<bar>k\<bar> div \<bar>l\<bar>" |
|
340 by (simp add: divmod_abs_def) |
|
341 |
|
342 lemma snd_divmod_abs [simp]: |
|
343 "snd (divmod_abs k l) = \<bar>k\<bar> mod \<bar>l\<bar>" |
|
344 by (simp add: divmod_abs_def) |
|
345 |
|
346 lemma divmod_abs_terminate_code [code]: |
|
347 "divmod_abs (Neg k) (Neg l) = divmod_abs (Pos k) (Pos l)" |
|
348 "divmod_abs (Neg k) (Pos l) = divmod_abs (Pos k) (Pos l)" |
|
349 "divmod_abs (Pos k) (Neg l) = divmod_abs (Pos k) (Pos l)" |
|
350 "divmod_abs j 0 = (0, \<bar>j\<bar>)" |
|
351 "divmod_abs 0 j = (0, 0)" |
|
352 by (simp_all add: prod_eq_iff) |
|
353 |
|
354 lemma divmod_abs_rec_code [code]: |
|
355 "divmod_abs (Pos k) (Pos l) = |
|
356 (let j = sub k l in |
|
357 if j < 0 then (0, Pos k) |
|
358 else let (q, r) = divmod_abs j (Pos l) in (q + 1, r))" |
|
359 apply (simp add: prod_eq_iff Let_def prod_case_beta) |
|
360 apply transfer |
|
361 apply (simp add: sub_non_negative sub_negative div_pos_pos_trivial mod_pos_pos_trivial div_pos_geq mod_pos_geq) |
|
362 done |
|
363 |
|
364 lemma divmod_integer_code [code]: |
|
365 "divmod_integer k l = |
|
366 (if k = 0 then (0, 0) else if l = 0 then (0, k) else |
|
367 (apsnd \<circ> times \<circ> sgn) l (if sgn k = sgn l |
|
368 then divmod_abs k l |
|
369 else (let (r, s) = divmod_abs k l in |
|
370 if s = 0 then (- r, 0) else (- r - 1, \<bar>l\<bar> - s))))" |
|
371 proof - |
|
372 have aux1: "\<And>k l::int. sgn k = sgn l \<longleftrightarrow> k = 0 \<and> l = 0 \<or> 0 < l \<and> 0 < k \<or> l < 0 \<and> k < 0" |
|
373 by (auto simp add: sgn_if) |
|
374 have aux2: "\<And>q::int. - int_of_integer k = int_of_integer l * q \<longleftrightarrow> int_of_integer k = int_of_integer l * - q" by auto |
|
375 show ?thesis |
|
376 by (simp add: prod_eq_iff integer_eq_iff prod_case_beta aux1) |
|
377 (auto simp add: zdiv_zminus1_eq_if zmod_zminus1_eq_if div_minus_right mod_minus_right aux2) |
|
378 qed |
|
379 |
|
380 lemma div_integer_code [code]: |
|
381 "k div l = fst (divmod_integer k l)" |
|
382 by simp |
|
383 |
|
384 lemma mod_integer_code [code]: |
|
385 "k mod l = snd (divmod_integer k l)" |
|
386 by simp |
|
387 |
|
388 lemma equal_integer_code [code]: |
|
389 "HOL.equal 0 (0::integer) \<longleftrightarrow> True" |
|
390 "HOL.equal 0 (Pos l) \<longleftrightarrow> False" |
|
391 "HOL.equal 0 (Neg l) \<longleftrightarrow> False" |
|
392 "HOL.equal (Pos k) 0 \<longleftrightarrow> False" |
|
393 "HOL.equal (Pos k) (Pos l) \<longleftrightarrow> HOL.equal k l" |
|
394 "HOL.equal (Pos k) (Neg l) \<longleftrightarrow> False" |
|
395 "HOL.equal (Neg k) 0 \<longleftrightarrow> False" |
|
396 "HOL.equal (Neg k) (Pos l) \<longleftrightarrow> False" |
|
397 "HOL.equal (Neg k) (Neg l) \<longleftrightarrow> HOL.equal k l" |
|
398 by (simp_all add: equal) |
|
399 |
|
400 lemma equal_integer_refl [code nbe]: |
|
401 "HOL.equal (k::integer) k \<longleftrightarrow> True" |
|
402 by (fact equal_refl) |
|
403 |
|
404 lemma less_eq_integer_code [code]: |
|
405 "0 \<le> (0::integer) \<longleftrightarrow> True" |
|
406 "0 \<le> Pos l \<longleftrightarrow> True" |
|
407 "0 \<le> Neg l \<longleftrightarrow> False" |
|
408 "Pos k \<le> 0 \<longleftrightarrow> False" |
|
409 "Pos k \<le> Pos l \<longleftrightarrow> k \<le> l" |
|
410 "Pos k \<le> Neg l \<longleftrightarrow> False" |
|
411 "Neg k \<le> 0 \<longleftrightarrow> True" |
|
412 "Neg k \<le> Pos l \<longleftrightarrow> True" |
|
413 "Neg k \<le> Neg l \<longleftrightarrow> l \<le> k" |
|
414 by simp_all |
|
415 |
|
416 lemma less_integer_code [code]: |
|
417 "0 < (0::integer) \<longleftrightarrow> False" |
|
418 "0 < Pos l \<longleftrightarrow> True" |
|
419 "0 < Neg l \<longleftrightarrow> False" |
|
420 "Pos k < 0 \<longleftrightarrow> False" |
|
421 "Pos k < Pos l \<longleftrightarrow> k < l" |
|
422 "Pos k < Neg l \<longleftrightarrow> False" |
|
423 "Neg k < 0 \<longleftrightarrow> True" |
|
424 "Neg k < Pos l \<longleftrightarrow> True" |
|
425 "Neg k < Neg l \<longleftrightarrow> l < k" |
|
426 by simp_all |
|
427 |
|
428 lift_definition integer_of_num :: "num \<Rightarrow> integer" |
|
429 is "numeral :: num \<Rightarrow> int" |
|
430 . |
|
431 |
|
432 lemma integer_of_num [code]: |
|
433 "integer_of_num num.One = 1" |
|
434 "integer_of_num (num.Bit0 n) = (let k = integer_of_num n in k + k)" |
|
435 "integer_of_num (num.Bit1 n) = (let k = integer_of_num n in k + k + 1)" |
|
436 by (transfer, simp only: numeral.simps Let_def)+ |
|
437 |
|
438 lift_definition num_of_integer :: "integer \<Rightarrow> num" |
|
439 is "num_of_nat \<circ> nat" |
|
440 . |
|
441 |
|
442 lemma num_of_integer_code [code]: |
|
443 "num_of_integer k = (if k \<le> 1 then Num.One |
|
444 else let |
|
445 (l, j) = divmod_integer k 2; |
|
446 l' = num_of_integer l; |
|
447 l'' = l' + l' |
|
448 in if j = 0 then l'' else l'' + Num.One)" |
|
449 proof - |
|
450 { |
|
451 assume "int_of_integer k mod 2 = 1" |
|
452 then have "nat (int_of_integer k mod 2) = nat 1" by simp |
|
453 moreover assume *: "1 < int_of_integer k" |
|
454 ultimately have **: "nat (int_of_integer k) mod 2 = 1" by (simp add: nat_mod_distrib) |
|
455 have "num_of_nat (nat (int_of_integer k)) = |
|
456 num_of_nat (2 * (nat (int_of_integer k) div 2) + nat (int_of_integer k) mod 2)" |
|
457 by simp |
|
458 then have "num_of_nat (nat (int_of_integer k)) = |
|
459 num_of_nat (nat (int_of_integer k) div 2 + nat (int_of_integer k) div 2 + nat (int_of_integer k) mod 2)" |
|
460 by (simp add: mult_2) |
|
461 with ** have "num_of_nat (nat (int_of_integer k)) = |
|
462 num_of_nat (nat (int_of_integer k) div 2 + nat (int_of_integer k) div 2 + 1)" |
|
463 by simp |
|
464 } |
|
465 note aux = this |
|
466 show ?thesis |
|
467 by (auto simp add: num_of_integer_def nat_of_integer_def Let_def prod_case_beta |
|
468 not_le integer_eq_iff less_eq_integer_def |
|
469 nat_mult_distrib nat_div_distrib num_of_nat_One num_of_nat_plus_distrib |
|
470 mult_2 [where 'a=nat] aux add_One) |
|
471 qed |
|
472 |
|
473 lemma nat_of_integer_code [code]: |
|
474 "nat_of_integer k = (if k \<le> 0 then 0 |
|
475 else let |
|
476 (l, j) = divmod_integer k 2; |
|
477 l' = nat_of_integer l; |
|
478 l'' = l' + l' |
|
479 in if j = 0 then l'' else l'' + 1)" |
|
480 proof - |
|
481 obtain j where "k = integer_of_int j" |
|
482 proof |
|
483 show "k = integer_of_int (int_of_integer k)" by simp |
|
484 qed |
|
485 moreover have "2 * (j div 2) = j - j mod 2" |
|
486 by (simp add: zmult_div_cancel mult_commute) |
|
487 ultimately show ?thesis |
|
488 by (auto simp add: split_def Let_def mod_integer_def nat_of_integer_def not_le |
|
489 nat_add_distrib [symmetric] Suc_nat_eq_nat_zadd1) |
|
490 qed |
|
491 |
|
492 lemma int_of_integer_code [code]: |
|
493 "int_of_integer k = (if k < 0 then - (int_of_integer (- k)) |
|
494 else if k = 0 then 0 |
|
495 else let |
|
496 (l, j) = divmod_integer k 2; |
|
497 l' = 2 * int_of_integer l |
|
498 in if j = 0 then l' else l' + 1)" |
|
499 by (auto simp add: split_def Let_def integer_eq_iff zmult_div_cancel) |
|
500 |
|
501 lemma integer_of_int_code [code]: |
|
502 "integer_of_int k = (if k < 0 then - (integer_of_int (- k)) |
|
503 else if k = 0 then 0 |
|
504 else let |
|
505 (l, j) = divmod_int k 2; |
|
506 l' = 2 * integer_of_int l |
|
507 in if j = 0 then l' else l' + 1)" |
|
508 by (auto simp add: split_def Let_def integer_eq_iff zmult_div_cancel) |
|
509 |
|
510 hide_const (open) Pos Neg sub dup divmod_abs |
|
511 |
|
512 |
|
513 subsection {* Serializer setup for target language integers *} |
|
514 |
|
515 code_reserved Eval abs |
|
516 |
|
517 code_type integer |
|
518 (SML "IntInf.int") |
|
519 (OCaml "Big'_int.big'_int") |
|
520 (Haskell "Integer") |
|
521 (Scala "BigInt") |
|
522 (Eval "int") |
|
523 |
|
524 code_instance integer :: equal |
|
525 (Haskell -) |
|
526 |
|
527 code_const "0::integer" |
|
528 (SML "0") |
|
529 (OCaml "Big'_int.zero'_big'_int") |
|
530 (Haskell "0") |
|
531 (Scala "BigInt(0)") |
|
532 |
|
533 setup {* |
|
534 fold (Numeral.add_code @{const_name Code_Numeral_Types.Pos} |
|
535 false Code_Printer.literal_numeral) ["SML", "OCaml", "Haskell", "Scala"] |
|
536 *} |
|
537 |
|
538 setup {* |
|
539 fold (Numeral.add_code @{const_name Code_Numeral_Types.Neg} |
|
540 true Code_Printer.literal_numeral) ["SML", "OCaml", "Haskell", "Scala"] |
|
541 *} |
|
542 |
|
543 code_const "plus :: integer \<Rightarrow> _ \<Rightarrow> _" |
|
544 (SML "IntInf.+ ((_), (_))") |
|
545 (OCaml "Big'_int.add'_big'_int") |
|
546 (Haskell infixl 6 "+") |
|
547 (Scala infixl 7 "+") |
|
548 (Eval infixl 8 "+") |
|
549 |
|
550 code_const "uminus :: integer \<Rightarrow> _" |
|
551 (SML "IntInf.~") |
|
552 (OCaml "Big'_int.minus'_big'_int") |
|
553 (Haskell "negate") |
|
554 (Scala "!(- _)") |
|
555 (Eval "~/ _") |
|
556 |
|
557 code_const "minus :: integer \<Rightarrow> _" |
|
558 (SML "IntInf.- ((_), (_))") |
|
559 (OCaml "Big'_int.sub'_big'_int") |
|
560 (Haskell infixl 6 "-") |
|
561 (Scala infixl 7 "-") |
|
562 (Eval infixl 8 "-") |
|
563 |
|
564 code_const Code_Numeral_Types.dup |
|
565 (SML "IntInf.*/ (2,/ (_))") |
|
566 (OCaml "Big'_int.mult'_big'_int/ (Big'_int.big'_int'_of'_int/ 2)") |
|
567 (Haskell "!(2 * _)") |
|
568 (Scala "!(2 * _)") |
|
569 (Eval "!(2 * _)") |
|
570 |
|
571 code_const Code_Numeral_Types.sub |
|
572 (SML "!(raise/ Fail/ \"sub\")") |
|
573 (OCaml "failwith/ \"sub\"") |
|
574 (Haskell "error/ \"sub\"") |
|
575 (Scala "!sys.error(\"sub\")") |
|
576 |
|
577 code_const "times :: integer \<Rightarrow> _ \<Rightarrow> _" |
|
578 (SML "IntInf.* ((_), (_))") |
|
579 (OCaml "Big'_int.mult'_big'_int") |
|
580 (Haskell infixl 7 "*") |
|
581 (Scala infixl 8 "*") |
|
582 (Eval infixl 9 "*") |
|
583 |
|
584 code_const Code_Numeral_Types.divmod_abs |
|
585 (SML "IntInf.divMod/ (IntInf.abs _,/ IntInf.abs _)") |
|
586 (OCaml "Big'_int.quomod'_big'_int/ (Big'_int.abs'_big'_int _)/ (Big'_int.abs'_big'_int _)") |
|
587 (Haskell "divMod/ (abs _)/ (abs _)") |
|
588 (Scala "!((k: BigInt) => (l: BigInt) =>/ if (l == 0)/ (BigInt(0), k) else/ (k.abs '/% l.abs))") |
|
589 (Eval "Integer.div'_mod/ (abs _)/ (abs _)") |
|
590 |
|
591 code_const "HOL.equal :: integer \<Rightarrow> _ \<Rightarrow> bool" |
|
592 (SML "!((_ : IntInf.int) = _)") |
|
593 (OCaml "Big'_int.eq'_big'_int") |
|
594 (Haskell infix 4 "==") |
|
595 (Scala infixl 5 "==") |
|
596 (Eval infixl 6 "=") |
|
597 |
|
598 code_const "less_eq :: integer \<Rightarrow> _ \<Rightarrow> bool" |
|
599 (SML "IntInf.<= ((_), (_))") |
|
600 (OCaml "Big'_int.le'_big'_int") |
|
601 (Haskell infix 4 "<=") |
|
602 (Scala infixl 4 "<=") |
|
603 (Eval infixl 6 "<=") |
|
604 |
|
605 code_const "less :: integer \<Rightarrow> _ \<Rightarrow> bool" |
|
606 (SML "IntInf.< ((_), (_))") |
|
607 (OCaml "Big'_int.lt'_big'_int") |
|
608 (Haskell infix 4 "<") |
|
609 (Scala infixl 4 "<") |
|
610 (Eval infixl 6 "<") |
|
611 |
|
612 code_modulename SML |
|
613 Code_Numeral_Types Arith |
|
614 |
|
615 code_modulename OCaml |
|
616 Code_Numeral_Types Arith |
|
617 |
|
618 code_modulename Haskell |
|
619 Code_Numeral_Types Arith |
|
620 |
|
621 |
|
622 subsection {* Type of target language naturals *} |
|
623 |
|
624 typedef natural = "UNIV \<Colon> nat set" |
|
625 morphisms nat_of_natural natural_of_nat .. |
|
626 |
|
627 setup_lifting (no_code) type_definition_natural |
|
628 |
|
629 lemma natural_eq_iff [termination_simp]: |
|
630 "m = n \<longleftrightarrow> nat_of_natural m = nat_of_natural n" |
|
631 by transfer rule |
|
632 |
|
633 lemma natural_eqI: |
|
634 "nat_of_natural m = nat_of_natural n \<Longrightarrow> m = n" |
|
635 using natural_eq_iff [of m n] by simp |
|
636 |
|
637 lemma nat_of_natural_of_nat_inverse [simp]: |
|
638 "nat_of_natural (natural_of_nat n) = n" |
|
639 by transfer rule |
|
640 |
|
641 lemma natural_of_nat_of_natural_inverse [simp]: |
|
642 "natural_of_nat (nat_of_natural n) = n" |
|
643 by transfer rule |
|
644 |
|
645 instantiation natural :: "{comm_monoid_diff, semiring_1}" |
|
646 begin |
|
647 |
|
648 lift_definition zero_natural :: natural |
|
649 is "0 :: nat" |
|
650 . |
|
651 |
|
652 declare zero_natural.rep_eq [simp] |
|
653 |
|
654 lift_definition one_natural :: natural |
|
655 is "1 :: nat" |
|
656 . |
|
657 |
|
658 declare one_natural.rep_eq [simp] |
|
659 |
|
660 lift_definition plus_natural :: "natural \<Rightarrow> natural \<Rightarrow> natural" |
|
661 is "plus :: nat \<Rightarrow> nat \<Rightarrow> nat" |
|
662 . |
|
663 |
|
664 declare plus_natural.rep_eq [simp] |
|
665 |
|
666 lift_definition minus_natural :: "natural \<Rightarrow> natural \<Rightarrow> natural" |
|
667 is "minus :: nat \<Rightarrow> nat \<Rightarrow> nat" |
|
668 . |
|
669 |
|
670 declare minus_natural.rep_eq [simp] |
|
671 |
|
672 lift_definition times_natural :: "natural \<Rightarrow> natural \<Rightarrow> natural" |
|
673 is "times :: nat \<Rightarrow> nat \<Rightarrow> nat" |
|
674 . |
|
675 |
|
676 declare times_natural.rep_eq [simp] |
|
677 |
|
678 instance proof |
|
679 qed (transfer, simp add: algebra_simps)+ |
|
680 |
|
681 end |
|
682 |
|
683 lemma [transfer_rule]: |
|
684 "fun_rel HOL.eq cr_natural (\<lambda>n::nat. n) (of_nat :: nat \<Rightarrow> natural)" |
|
685 proof - |
|
686 have "fun_rel HOL.eq cr_natural (of_nat :: nat \<Rightarrow> nat) (of_nat :: nat \<Rightarrow> natural)" |
|
687 by (unfold of_nat_def [abs_def]) transfer_prover |
|
688 then show ?thesis by (simp add: id_def) |
|
689 qed |
|
690 |
|
691 lemma [transfer_rule]: |
|
692 "fun_rel HOL.eq cr_natural (numeral :: num \<Rightarrow> nat) (numeral :: num \<Rightarrow> natural)" |
|
693 proof - |
|
694 have "fun_rel HOL.eq cr_natural (numeral :: num \<Rightarrow> nat) (\<lambda>n. of_nat (numeral n))" |
|
695 by transfer_prover |
|
696 then show ?thesis by simp |
|
697 qed |
|
698 |
|
699 lemma nat_of_natural_of_nat [simp]: |
|
700 "nat_of_natural (of_nat n) = n" |
|
701 by transfer rule |
|
702 |
|
703 lemma natural_of_nat_of_nat [simp, code_abbrev]: |
|
704 "natural_of_nat = of_nat" |
|
705 by transfer rule |
|
706 |
|
707 lemma of_nat_of_natural [simp]: |
|
708 "of_nat (nat_of_natural n) = n" |
|
709 by transfer rule |
|
710 |
|
711 lemma nat_of_natural_numeral [simp]: |
|
712 "nat_of_natural (numeral k) = numeral k" |
|
713 by transfer rule |
|
714 |
|
715 instantiation natural :: "{semiring_div, equal, linordered_semiring}" |
|
716 begin |
|
717 |
|
718 lift_definition div_natural :: "natural \<Rightarrow> natural \<Rightarrow> natural" |
|
719 is "Divides.div :: nat \<Rightarrow> nat \<Rightarrow> nat" |
|
720 . |
|
721 |
|
722 declare div_natural.rep_eq [simp] |
|
723 |
|
724 lift_definition mod_natural :: "natural \<Rightarrow> natural \<Rightarrow> natural" |
|
725 is "Divides.mod :: nat \<Rightarrow> nat \<Rightarrow> nat" |
|
726 . |
|
727 |
|
728 declare mod_natural.rep_eq [simp] |
|
729 |
|
730 lift_definition less_eq_natural :: "natural \<Rightarrow> natural \<Rightarrow> bool" |
|
731 is "less_eq :: nat \<Rightarrow> nat \<Rightarrow> bool" |
|
732 . |
|
733 |
|
734 declare less_eq_natural.rep_eq [termination_simp] |
|
735 |
|
736 lift_definition less_natural :: "natural \<Rightarrow> natural \<Rightarrow> bool" |
|
737 is "less :: nat \<Rightarrow> nat \<Rightarrow> bool" |
|
738 . |
|
739 |
|
740 declare less_natural.rep_eq [termination_simp] |
|
741 |
|
742 lift_definition equal_natural :: "natural \<Rightarrow> natural \<Rightarrow> bool" |
|
743 is "HOL.equal :: nat \<Rightarrow> nat \<Rightarrow> bool" |
|
744 . |
|
745 |
|
746 instance proof |
|
747 qed (transfer, simp add: algebra_simps equal less_le_not_le [symmetric] linear)+ |
|
748 |
|
749 end |
|
750 |
|
751 lemma [transfer_rule]: |
|
752 "fun_rel cr_natural (fun_rel cr_natural cr_natural) (min :: _ \<Rightarrow> _ \<Rightarrow> nat) (min :: _ \<Rightarrow> _ \<Rightarrow> natural)" |
|
753 by (unfold min_def [abs_def]) transfer_prover |
|
754 |
|
755 lemma [transfer_rule]: |
|
756 "fun_rel cr_natural (fun_rel cr_natural cr_natural) (max :: _ \<Rightarrow> _ \<Rightarrow> nat) (max :: _ \<Rightarrow> _ \<Rightarrow> natural)" |
|
757 by (unfold max_def [abs_def]) transfer_prover |
|
758 |
|
759 lemma nat_of_natural_min [simp]: |
|
760 "nat_of_natural (min k l) = min (nat_of_natural k) (nat_of_natural l)" |
|
761 by transfer rule |
|
762 |
|
763 lemma nat_of_natural_max [simp]: |
|
764 "nat_of_natural (max k l) = max (nat_of_natural k) (nat_of_natural l)" |
|
765 by transfer rule |
|
766 |
|
767 lift_definition natural_of_integer :: "integer \<Rightarrow> natural" |
|
768 is "nat :: int \<Rightarrow> nat" |
|
769 . |
|
770 |
|
771 lift_definition integer_of_natural :: "natural \<Rightarrow> integer" |
|
772 is "of_nat :: nat \<Rightarrow> int" |
|
773 . |
|
774 |
|
775 lemma natural_of_integer_of_natural [simp]: |
|
776 "natural_of_integer (integer_of_natural n) = n" |
|
777 by transfer simp |
|
778 |
|
779 lemma integer_of_natural_of_integer [simp]: |
|
780 "integer_of_natural (natural_of_integer k) = max 0 k" |
|
781 by transfer auto |
|
782 |
|
783 lemma int_of_integer_of_natural [simp]: |
|
784 "int_of_integer (integer_of_natural n) = of_nat (nat_of_natural n)" |
|
785 by transfer rule |
|
786 |
|
787 lemma integer_of_natural_of_nat [simp]: |
|
788 "integer_of_natural (of_nat n) = of_nat n" |
|
789 by transfer rule |
|
790 |
|
791 lemma [measure_function]: |
|
792 "is_measure nat_of_natural" |
|
793 by (rule is_measure_trivial) |
|
794 |
|
795 |
|
796 subsection {* Inductive represenation of target language naturals *} |
|
797 |
|
798 lift_definition Suc :: "natural \<Rightarrow> natural" |
|
799 is Nat.Suc |
|
800 . |
|
801 |
|
802 declare Suc.rep_eq [simp] |
|
803 |
|
804 rep_datatype "0::natural" Suc |
|
805 by (transfer, fact nat.induct nat.inject nat.distinct)+ |
|
806 |
|
807 lemma natural_case [case_names nat, cases type: natural]: |
|
808 fixes m :: natural |
|
809 assumes "\<And>n. m = of_nat n \<Longrightarrow> P" |
|
810 shows P |
|
811 using assms by transfer blast |
|
812 |
|
813 lemma [simp, code]: |
|
814 "natural_size = nat_of_natural" |
|
815 proof (rule ext) |
|
816 fix n |
|
817 show "natural_size n = nat_of_natural n" |
|
818 by (induct n) simp_all |
|
819 qed |
|
820 |
|
821 lemma [simp, code]: |
|
822 "size = nat_of_natural" |
|
823 proof (rule ext) |
|
824 fix n |
|
825 show "size n = nat_of_natural n" |
|
826 by (induct n) simp_all |
|
827 qed |
|
828 |
|
829 lemma natural_decr [termination_simp]: |
|
830 "n \<noteq> 0 \<Longrightarrow> nat_of_natural n - Nat.Suc 0 < nat_of_natural n" |
|
831 by transfer simp |
|
832 |
|
833 lemma natural_zero_minus_one: |
|
834 "(0::natural) - 1 = 0" |
|
835 by simp |
|
836 |
|
837 lemma Suc_natural_minus_one: |
|
838 "Suc n - 1 = n" |
|
839 by transfer simp |
|
840 |
|
841 hide_const (open) Suc |
|
842 |
|
843 |
|
844 subsection {* Code refinement for target language naturals *} |
|
845 |
|
846 lift_definition Nat :: "integer \<Rightarrow> natural" |
|
847 is nat |
|
848 . |
|
849 |
|
850 lemma [code_post]: |
|
851 "Nat 0 = 0" |
|
852 "Nat 1 = 1" |
|
853 "Nat (numeral k) = numeral k" |
|
854 by (transfer, simp)+ |
|
855 |
|
856 lemma [code abstype]: |
|
857 "Nat (integer_of_natural n) = n" |
|
858 by transfer simp |
|
859 |
|
860 lemma [code abstract]: |
|
861 "integer_of_natural (natural_of_nat n) = of_nat n" |
|
862 by simp |
|
863 |
|
864 lemma [code abstract]: |
|
865 "integer_of_natural (natural_of_integer k) = max 0 k" |
|
866 by simp |
|
867 |
|
868 lemma [code_abbrev]: |
|
869 "natural_of_integer (Code_Numeral_Types.Pos k) = numeral k" |
|
870 by transfer simp |
|
871 |
|
872 lemma [code abstract]: |
|
873 "integer_of_natural 0 = 0" |
|
874 by transfer simp |
|
875 |
|
876 lemma [code abstract]: |
|
877 "integer_of_natural 1 = 1" |
|
878 by transfer simp |
|
879 |
|
880 lemma [code abstract]: |
|
881 "integer_of_natural (Code_Numeral_Types.Suc n) = integer_of_natural n + 1" |
|
882 by transfer simp |
|
883 |
|
884 lemma [code]: |
|
885 "nat_of_natural = nat_of_integer \<circ> integer_of_natural" |
|
886 by transfer (simp add: fun_eq_iff) |
|
887 |
|
888 lemma [code, code_unfold]: |
|
889 "natural_case f g n = (if n = 0 then f else g (n - 1))" |
|
890 by (cases n rule: natural.exhaust) (simp_all, simp add: Suc_def) |
|
891 |
|
892 declare natural.recs [code del] |
|
893 |
|
894 lemma [code abstract]: |
|
895 "integer_of_natural (m + n) = integer_of_natural m + integer_of_natural n" |
|
896 by transfer simp |
|
897 |
|
898 lemma [code abstract]: |
|
899 "integer_of_natural (m - n) = max 0 (integer_of_natural m - integer_of_natural n)" |
|
900 by transfer simp |
|
901 |
|
902 lemma [code abstract]: |
|
903 "integer_of_natural (m * n) = integer_of_natural m * integer_of_natural n" |
|
904 by transfer (simp add: of_nat_mult) |
|
905 |
|
906 lemma [code abstract]: |
|
907 "integer_of_natural (m div n) = integer_of_natural m div integer_of_natural n" |
|
908 by transfer (simp add: zdiv_int) |
|
909 |
|
910 lemma [code abstract]: |
|
911 "integer_of_natural (m mod n) = integer_of_natural m mod integer_of_natural n" |
|
912 by transfer (simp add: zmod_int) |
|
913 |
|
914 lemma [code]: |
|
915 "HOL.equal m n \<longleftrightarrow> HOL.equal (integer_of_natural m) (integer_of_natural n)" |
|
916 by transfer (simp add: equal) |
|
917 |
|
918 lemma [code nbe]: |
|
919 "HOL.equal n (n::natural) \<longleftrightarrow> True" |
|
920 by (simp add: equal) |
|
921 |
|
922 lemma [code]: |
|
923 "m \<le> n \<longleftrightarrow> integer_of_natural m \<le> integer_of_natural n" |
|
924 by transfer simp |
|
925 |
|
926 lemma [code]: |
|
927 "m < n \<longleftrightarrow> integer_of_natural m < integer_of_natural n" |
|
928 by transfer simp |
|
929 |
|
930 hide_const (open) Nat |
|
931 |
|
932 |
|
933 code_reflect Code_Numeral_Types |
|
934 datatypes natural = _ |
|
935 functions integer_of_natural natural_of_integer |
|
936 |
|
937 end |
|
938 |
|