blob: 880fd0d672877e085c04a885157a3128039daa42 [file]
(*
* Copyright 2016, NICTA
*
* This software may be distributed and modified according to the terms of
* the GNU General Public License version 2. Note that NO WARRANTY is provided.
* See "LICENSE_GPLv2.txt" for details.
*
* @TAG(NICTA_GPL)
*)
theory WordArrayT
imports
"../adt/BilbyT"
"../lib/Loops"
begin
consts \<alpha>wa :: "'a WordArray \<Rightarrow> 'a list"
consts make :: "'a list \<Rightarrow> 'a WordArray"
definition
mapAccumObs :: "nat \<Rightarrow> nat \<Rightarrow> (('a, 'acc, 'obsv) ElemAO \<Rightarrow> ('a \<times> 'acc))
\<Rightarrow> 'a list \<Rightarrow> 'acc \<Rightarrow> 'obsv \<Rightarrow> 'a list \<times> 'acc"
where
"mapAccumObs frm to fn xs vacc obs =
(let (ys, acc) = fold (\<lambda>elem (ys,acc).
let (elem,acc) = fn (ElemAO.make elem acc obs)
in (ys@[elem], acc)) (slice frm to xs) ([],vacc)
in (take frm xs @ ys @ drop (max frm to) xs, acc))"
lemma length_mapAccum_helper:
"length (fst $ fold (\<lambda>x (ys,a'). let (elem, acc) = loopbody x a'
in (ys@[elem],acc)) (xs) (ys,a)
)
= length ys + length xs"
by (induct xs arbitrary: a ys, auto simp: Let_def slice_def split: prod.split)
lemma length_mapAccum_slice_helper:
"length (let (xs', _) = fold (\<lambda>x (ys,a'). let (elem, acc) = loopbody x a'
in (ys@[elem],acc)) (slice frm to xs) (ys,a)
in xs') = length ys + length (slice frm to xs)"
proof -
have f1: "(\<lambda>x (ys, a'). (ys @ [TypBucket.fst (loopbody x a')], TypBucket.snd (loopbody x a'))) =
(\<lambda>x prod. (TypBucket.fst prod @ [TypBucket.fst (loopbody x (TypBucket.snd prod))], TypBucket.snd (loopbody x (TypBucket.snd prod))))"
using split_beta by blast
show ?thesis
apply simp
apply (simp only: Let_def prod.case_eq_if)
using length_mapAccum_helper[unfolded fun_app_def prod.case_eq_if Let_def]
apply (force simp add: f1)
done
qed
lemma slice_length:
"length (slice frm to xs) = min (to - frm) (length xs - frm)"
by (simp add: slice_def)
lemma length_mapAccum_slice_helper':
"length (take frm xs @ fst (let (xs', acc) = fold (\<lambda>x (ys,a'). let (elem, acc) = loopbody x a'
in (ys@[elem],acc)) (slice frm to xs) (ys,a)
in (xs',acc)) @ drop (max frm to) xs) = length ys + length xs"
unfolding Let_def prod.case_eq_if
using length_mapAccum_slice_helper[unfolded prod.case_eq_if Let_def, where xs=xs and ys=ys and frm=frm and to=to and loopbody=loopbody and a=a]
by (simp add: slice_length)
lemma length_mapAccum:
"length (fst (mapAccumObs frm to fn xs a obs)) = length xs"
unfolding mapAccumObs_def
using length_mapAccum_slice_helper'[where frm=frm and to=to and xs=xs and a=a and ys="[]"]
by (auto simp: Let_def prod.case_eq_if)
lemma length_mapAccumI:
" P (length xs) \<Longrightarrow> P (length (fst (mapAccumObs frm to fn xs a obs)))"
by (simp add : length_mapAccum)
axiomatization
where
wordarray_make: "\<And>xs. \<alpha>wa (WordArrayT.make xs) = xs"
and
wordarray_make': "\<And>wa. WordArrayT.make (\<alpha>wa wa) = wa"
and
wordarray_create_ret:
"\<And>P.\<lbrakk> \<And>ex'. (ex', Option.None ()) = malloc ex \<Longrightarrow> P (Error ex');
\<And>ex' v. \<lbrakk> sz > 0 ; (ex', Option.Some v) = malloc ex; length (\<alpha>wa v) = unat sz \<rbrakk> \<Longrightarrow>
P (Success (ex', v))
\<rbrakk> \<Longrightarrow>
P (wordarray_create (ex, sz))"
and wordarray_length_ret:
"unat (wordarray_length arr) = length (\<alpha>wa arr)"
and wordarray_get_ret:
"\<lbrakk> unat index < length (\<alpha>wa arr) \<rbrakk> \<Longrightarrow>
wordarray_get (arr, index) = \<alpha>wa arr ! unat index"
and wordarray_modify_ret:
"\<And>P. \<lbrakk> unat index < List.length (\<alpha>wa varr);
let r = modifier (ElemAO.make ((\<alpha>wa varr)!unat index) vacc obs) in
P (ArrA.make (WordArrayT.make (\<alpha>wa varr[unat index:=ElemA.elem\<^sub>f r])) (ElemA.acc\<^sub>f r)) \<rbrakk> \<Longrightarrow>
P (wordarray_modify (ArrayUseValueP.make varr index modifier vacc obs))"
(* Alternative that does not use WordArray.make
and wordarray_modify_ret:
"\<And>P. \<lbrakk> unat index < List.length (\<alpha>wa varr);
ElemA.make a acc'' = modifier (ElemAO.make ((\<alpha>wa varr)!unat index) vacc obs);
\<And>arr'. \<alpha>wa arr' = (\<alpha>wa varr)[unat index:=a] \<Longrightarrow> P (ArrA.make arr' acc'') \<rbrakk> \<Longrightarrow>
P (wordarray_modify (ArrayUseValueP.make varr index modifier vacc obs))"
*)
and wordarray_map_no_break_ret:
"\<And>P. (let (aarr, vacc) = mapAccumObs (unat frm) (unat to) body (\<alpha>wa arr) acc obs
in P ((WordArrayT.make aarr), vacc))
\<Longrightarrow> P (wordarray_map_no_break (ArrayMapP.make arr frm to body acc obs))"
and wordarray_cmp_ret:
"\<And>P. P(\<alpha>wa a1 = \<alpha>wa a2) \<Longrightarrow> P (wordarray_cmp(a1, a2))"
and wordarray_set_ret:
"(offs::U32) \<le> offs + len \<Longrightarrow>
wordarray_set (wa, offs, len, (v::U8)) =
WordArrayT.make ((take (unat offs) (\<alpha>wa wa) @
replicate (unat len) v @ drop (unat (offs + len)) (\<alpha>wa wa)))"
and wordarray_copy_ret:
"\<And>P. \<lbrakk> length (\<alpha>wa dst) = length (\<alpha>wa src) \<Longrightarrow>
offs = src_offs \<Longrightarrow>
offs \<le> offs + len \<Longrightarrow>
unat (offs + len) \<le> length (\<alpha>wa src) \<Longrightarrow>
P (WordArrayT.make (take (unat offs) (\<alpha>wa dst) @ slice (unat offs) (unat offs + unat len) (\<alpha>wa src) @ drop (unat (offs+len)) (\<alpha>wa dst))) \<rbrakk>
\<Longrightarrow>
P (wordarray_copy(dst, src, offs, src_offs, len))"
lemma wordarray_\<alpha>wa_eq:
"\<And>xs ys. (xs = ys) \<longleftrightarrow> \<alpha>wa xs = \<alpha>wa ys"
apply (rule iffI)
apply (erule arg_cong[where f=\<alpha>wa])
apply (drule_tac x="\<alpha>wa xs" and y="\<alpha>wa ys" in arg_cong[where f=WordArrayT.make])
apply (simp add: wordarray_make')
done
lemma ElemA_ext_inject_plus:
"(\<lparr>ElemA.elem\<^sub>f = a, ElemA.acc\<^sub>f = b\<rparr> = v) = (ElemA.elem\<^sub>f v = a \<and> ElemA.acc\<^sub>f v = b)"
by (case_tac v, auto)
lemma wordarray_modify_length':
"\<And>index modifier vacc obs wa. unat index < length (\<alpha>wa wa) \<Longrightarrow>
(length $ \<alpha>wa $ ArrA.arr\<^sub>f $ wordarray_modify (ArrayUseValueP.make wa index modifier vacc obs)) = (length $ \<alpha>wa $ wa)"
by (fastforce intro: wordarray_modify_ret
simp: ArrA.make_def wordarray_make ElemA_ext_inject_plus
ElemA.make_def ElemAO.make_def)+
lemma wordarray_modify_length:
"\<And>index modifier vacc obs wa. unat index < length (\<alpha>wa wa) \<Longrightarrow>
P (length $ \<alpha>wa $ wa) \<Longrightarrow>
P(length (\<alpha>wa (ArrA.arr\<^sub>f ( wordarray_modify (ArrayUseValueP.make wa index modifier vacc obs)))))"
by (fastforce simp: wordarray_modify_length'[simplified])
lemma wordarray_get_ret':
"\<lbrakk> unat index < length (\<alpha>wa arr); P (\<alpha>wa arr ! unat index) \<rbrakk> \<Longrightarrow>
P (wordarray_get (arr, index))"
using wordarray_get_ret by fastforce
lemma wordarray_length_ofnat:
"unat (wordarray_length wa) = length (\<alpha>wa wa) \<Longrightarrow>
wordarray_length wa = of_nat (length (\<alpha>wa wa))"
by (drule sym, simp)
lemmas wordarray_make_rev = wordarray_make'
end