src/HOL/Library/IArray.thy
changeset 68659 db0c70767d86
parent 68658 16cc1161ad7f
child 69272 15e9ed5b28fb
equal deleted inserted replaced
68658:16cc1161ad7f 68659:db0c70767d86
     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