1 (* Title: HOL/Library/IArray.thy |
1 (* Title: HOL/Library/IArray.thy |
2 Author: Tobias Nipkow, TU Muenchen |
2 Author: Tobias Nipkow, TU Muenchen |
|
3 Author: Jose Divasón <jose.divasonm at unirioja.es> |
|
4 Author: Jesús Aransay <jesus-maria.aransay at unirioja.es> |
3 *) |
5 *) |
4 |
6 |
5 section \<open>Immutable Arrays with Code Generation\<close> |
7 section \<open>Immutable Arrays with Code Generation\<close> |
6 |
8 |
7 theory IArray |
9 theory IArray |
30 [simp]: "as !! n = IArray.list_of as ! n" |
32 [simp]: "as !! n = IArray.list_of as ! n" |
31 |
33 |
32 qualified definition length :: "'a iarray \<Rightarrow> nat" where |
34 qualified definition length :: "'a iarray \<Rightarrow> nat" where |
33 [simp]: "length as = List.length (IArray.list_of as)" |
35 [simp]: "length as = List.length (IArray.list_of as)" |
34 |
36 |
35 qualified primrec all :: "('a \<Rightarrow> bool) \<Rightarrow> 'a iarray \<Rightarrow> bool" where |
37 qualified definition all :: "('a \<Rightarrow> bool) \<Rightarrow> 'a iarray \<Rightarrow> bool" where |
36 "all p (IArray as) \<longleftrightarrow> (\<forall>a \<in> set as. p a)" |
38 [simp]: "all p as \<longleftrightarrow> (\<forall>a \<in> set (list_of as). p a)" |
37 |
39 |
38 qualified primrec exists :: "('a \<Rightarrow> bool) \<Rightarrow> 'a iarray \<Rightarrow> bool" where |
40 qualified definition exists :: "('a \<Rightarrow> bool) \<Rightarrow> 'a iarray \<Rightarrow> bool" where |
39 "exists p (IArray as) \<longleftrightarrow> (\<exists>a \<in> set as. p a)" |
41 [simp]: "exists p as \<longleftrightarrow> (\<exists>a \<in> set (list_of as). p a)" |
40 |
|
41 lemma list_of_code [code]: |
|
42 "IArray.list_of as = map (\<lambda>n. as !! n) [0 ..< IArray.length as]" |
|
43 by (cases as) (simp add: map_nth) |
|
44 |
42 |
45 lemma of_fun_nth: |
43 lemma of_fun_nth: |
46 "IArray.of_fun f n !! i = f i" if "i < n" |
44 "IArray.of_fun f n !! i = f i" if "i < n" |
47 using that by (simp add: map_nth) |
45 using that by (simp add: map_nth) |
48 |
46 |
77 |
75 |
78 lemma [code]: |
76 lemma [code]: |
79 "rel_iarray r as bs = list_all2 r (IArray.list_of as) (IArray.list_of bs)" |
77 "rel_iarray r as bs = list_all2 r (IArray.list_of as) (IArray.list_of bs)" |
80 by (cases as, cases bs) auto |
78 by (cases as, cases bs) auto |
81 |
79 |
|
80 lemma list_of_code [code]: |
|
81 "IArray.list_of as = map (\<lambda>n. as !! n) [0 ..< IArray.length as]" |
|
82 by (cases as) (simp add: map_nth) |
|
83 |
82 lemma [code]: |
84 lemma [code]: |
83 "HOL.equal as bs \<longleftrightarrow> HOL.equal (IArray.list_of as) (IArray.list_of bs)" |
85 "HOL.equal as bs \<longleftrightarrow> HOL.equal (IArray.list_of as) (IArray.list_of bs)" |
84 by (cases as, cases bs) (simp add: equal) |
86 by (cases as, cases bs) (simp add: equal) |
|
87 |
|
88 lemma [code]: |
|
89 "IArray.all p = Not \<circ> IArray.exists (Not \<circ> p)" |
|
90 by (simp add: fun_eq_iff) |
85 |
91 |
86 context term_syntax |
92 context term_syntax |
87 begin |
93 begin |
88 |
94 |
89 lemma [code]: |
95 lemma [code]: |
105 lemma [code]: |
111 lemma [code]: |
106 "IArray.of_fun f n = IArray.tabulate (integer_of_nat n, f \<circ> nat_of_integer)" |
112 "IArray.of_fun f n = IArray.tabulate (integer_of_nat n, f \<circ> nat_of_integer)" |
107 by simp |
113 by simp |
108 |
114 |
109 qualified primrec sub' :: "'a iarray \<times> integer \<Rightarrow> 'a" where |
115 qualified primrec sub' :: "'a iarray \<times> integer \<Rightarrow> 'a" where |
110 "sub' (as, n) = IArray.list_of as ! nat_of_integer n" |
116 "sub' (as, n) = as !! nat_of_integer n" |
111 |
117 |
112 lemma [code]: |
118 lemma [code]: |
113 "IArray.sub' (IArray as, n) = as ! nat_of_integer n" |
119 "IArray.sub' (IArray as, n) = as ! nat_of_integer n" |
114 by simp |
120 by simp |
115 |
121 |
125 by simp |
131 by simp |
126 |
132 |
127 lemma [code]: |
133 lemma [code]: |
128 "IArray.length as = nat_of_integer (IArray.length' as)" |
134 "IArray.length as = nat_of_integer (IArray.length' as)" |
129 by simp |
135 by simp |
|
136 |
|
137 qualified definition exists_upto :: "('a \<Rightarrow> bool) \<Rightarrow> integer \<Rightarrow> 'a iarray \<Rightarrow> bool" where |
|
138 [simp]: "exists_upto p k as \<longleftrightarrow> (\<exists>l. 0 \<le> l \<and> l < k \<and> p (sub' (as, l)))" |
|
139 |
|
140 lemma exists_upto_of_nat: |
|
141 "exists_upto p (of_nat n) as \<longleftrightarrow> (\<exists>m<n. p (as !! m))" |
|
142 including integer.lifting by (simp, transfer) |
|
143 (metis nat_int nat_less_iff of_nat_0_le_iff) |
|
144 |
|
145 lemma [code]: |
|
146 "exists_upto p k as \<longleftrightarrow> (if k \<le> 0 then False else |
|
147 let l = k - 1 in p (sub' (as, l)) \<or> exists_upto p l as)" |
|
148 proof (cases "k \<ge> 1") |
|
149 case False |
|
150 then show ?thesis |
|
151 by (auto simp add: not_le discrete) |
|
152 next |
|
153 case True |
|
154 then have less: "k \<le> 0 \<longleftrightarrow> False" |
|
155 by simp |
|
156 define n where "n = nat_of_integer (k - 1)" |
|
157 with True have k: "k - 1 = of_nat n" "k = of_nat (Suc n)" |
|
158 by simp_all |
|
159 show ?thesis unfolding less Let_def k(1) unfolding k(2) exists_upto_of_nat |
|
160 using less_Suc_eq by auto |
|
161 qed |
|
162 |
|
163 lemma [code]: |
|
164 "IArray.exists p as \<longleftrightarrow> exists_upto p (length' as) as" |
|
165 including integer.lifting by (simp, transfer) |
|
166 (auto, metis in_set_conv_nth less_imp_of_nat_less nat_int of_nat_0_le_iff) |
130 |
167 |
131 end |
168 end |
132 |
169 |
133 |
170 |
134 subsection \<open>Code Generation for SML\<close> |
171 subsection \<open>Code Generation for SML\<close> |
146 | constant IArray.exists \<rightharpoonup> (SML) "Vector.exists" |
183 | constant IArray.exists \<rightharpoonup> (SML) "Vector.exists" |
147 | constant IArray.tabulate \<rightharpoonup> (SML) "Vector.tabulate" |
184 | constant IArray.tabulate \<rightharpoonup> (SML) "Vector.tabulate" |
148 | constant IArray.sub' \<rightharpoonup> (SML) "Vector.sub" |
185 | constant IArray.sub' \<rightharpoonup> (SML) "Vector.sub" |
149 | constant IArray.length' \<rightharpoonup> (SML) "Vector.length" |
186 | constant IArray.length' \<rightharpoonup> (SML) "Vector.length" |
150 |
187 |
151 end |
188 |
|
189 subsection \<open>Code Generation for Haskell\<close> |
|
190 |
|
191 text \<open>We map @{typ "'a iarray"}s in Isabelle/HOL to @{text Data.Array.IArray.array} |
|
192 in Haskell. Performance mapping to @{text Data.Array.Unboxed.Array} and |
|
193 @{text Data.Array.Array} is similar.\<close> |
|
194 |
|
195 code_printing |
|
196 code_module "IArray" \<rightharpoonup> (Haskell) \<open> |
|
197 import Prelude (Bool(True, False), not, Maybe(Nothing, Just), |
|
198 Integer, (+), (-), (<), fromInteger, toInteger, map, seq, (.)); |
|
199 import qualified Prelude; |
|
200 import qualified Data.Array.IArray; |
|
201 import qualified Data.Array.Base; |
|
202 import qualified Data.Ix; |
|
203 |
|
204 newtype IArray e = IArray (Data.Array.IArray.Array Integer e); |
|
205 |
|
206 tabulate :: (Integer, (Integer -> e)) -> IArray e; |
|
207 tabulate (k, f) = IArray (Data.Array.IArray.array (0, k - 1) (map (\i -> let fi = f i in fi `seq` (i, fi)) [0..k - 1])); |
|
208 |
|
209 of_list :: [e] -> IArray e; |
|
210 of_list l = IArray (Data.Array.IArray.listArray (0, (toInteger . Prelude.length) l - 1) l); |
|
211 |
|
212 sub :: (IArray e, Integer) -> e; |
|
213 sub (IArray v, i) = v `Data.Array.Base.unsafeAt` fromInteger i; |
|
214 |
|
215 length :: IArray e -> Integer; |
|
216 length (IArray v) = toInteger (Data.Ix.rangeSize (Data.Array.IArray.bounds v));\<close> |
|
217 |
|
218 code_reserved Haskell IArray_Impl |
|
219 |
|
220 code_printing |
|
221 type_constructor iarray \<rightharpoonup> (Haskell) "IArray.IArray _" |
|
222 | constant IArray \<rightharpoonup> (Haskell) "IArray.of'_list" |
|
223 | constant IArray.tabulate \<rightharpoonup> (Haskell) "IArray.tabulate" |
|
224 | constant IArray.sub' \<rightharpoonup> (Haskell) "IArray.sub" |
|
225 | constant IArray.length' \<rightharpoonup> (Haskell) "IArray.length" |
|
226 |
|
227 end |