diff --git a/src/HOL/SPARK/Examples/RIPEMD-160/F.thy b/src/HOL/SPARK/Examples/RIPEMD-160/F.thy --- a/src/HOL/SPARK/Examples/RIPEMD-160/F.thy +++ b/src/HOL/SPARK/Examples/RIPEMD-160/F.thy @@ -1,66 +1,66 @@ (* Title: HOL/SPARK/Examples/RIPEMD-160/F.thy Author: Fabian Immler, TU Muenchen Verification of the RIPEMD-160 hash function *) theory F imports RMD_Specification begin spark_open \rmd/f\ spark_vc function_f_2 using assms by simp_all spark_vc function_f_3 using assms by simp_all spark_vc function_f_4 using assms by simp_all spark_vc function_f_5 using assms by simp_all spark_vc function_f_6 proof - from H8 have "nat j <= 15" by simp with assms show ?thesis - by (simp add: f_def bwsimps int_word_uint int_mod_eq') + by (simp add: f_def bwsimps int_word_uint) qed spark_vc function_f_7 proof - from H7 have "16 <= nat j" by simp moreover from H8 have "nat j <= 31" by simp ultimately show ?thesis using assms - by (simp add: f_def bwsimps int_word_uint int_mod_eq') + by (simp add: f_def bwsimps int_word_uint) qed spark_vc function_f_8 proof - from H7 have "32 <= nat j" by simp moreover from H8 have "nat j <= 47" by simp ultimately show ?thesis using assms - by (simp add: f_def bwsimps int_word_uint int_mod_eq') + by (simp add: f_def bwsimps int_word_uint) qed spark_vc function_f_9 proof - from H7 have "48 <= nat j" by simp moreover from H8 have "nat j <= 63" by simp ultimately show ?thesis using assms - by (simp add: f_def bwsimps int_word_uint int_mod_eq') + by (simp add: f_def bwsimps int_word_uint) qed spark_vc function_f_10 proof - from H2 have "nat j <= 79" by simp moreover from H12 have "64 <= nat j" by simp ultimately show ?thesis using assms - by (simp add: f_def bwsimps int_word_uint int_mod_eq') + by (simp add: f_def bwsimps int_word_uint) qed spark_end end diff --git a/src/HOL/SPARK/Examples/RIPEMD-160/Round.thy b/src/HOL/SPARK/Examples/RIPEMD-160/Round.thy --- a/src/HOL/SPARK/Examples/RIPEMD-160/Round.thy +++ b/src/HOL/SPARK/Examples/RIPEMD-160/Round.thy @@ -1,466 +1,466 @@ (* Title: HOL/SPARK/Examples/RIPEMD-160/Round.thy Author: Fabian Immler, TU Muenchen Verification of the RIPEMD-160 hash function *) theory Round imports RMD_Specification begin spark_open \rmd/round\ abbreviation from_chain :: "chain \ RMD.chain" where "from_chain c \ ( word_of_int (h0 c), word_of_int (h1 c), word_of_int (h2 c), word_of_int (h3 c), word_of_int (h4 c))" abbreviation from_chain_pair :: "chain_pair \ RMD.chain \ RMD.chain" where "from_chain_pair cc \ ( from_chain (left cc), from_chain (right cc))" abbreviation to_chain :: "RMD.chain \ chain" where "to_chain c \ (let (h0, h1, h2, h3, h4) = c in (|h0 = uint h0, h1 = uint h1, h2 = uint h2, h3 = uint h3, h4 = uint h4|))" abbreviation to_chain_pair :: "RMD.chain \ RMD.chain \ chain_pair" where "to_chain_pair c == (let (c1, c2) = c in (| left = to_chain c1, right = to_chain c2 |))" abbreviation steps' :: "chain_pair \ int \ block \ chain_pair" where "steps' cc i b == to_chain_pair (steps (\n. word_of_int (b (int n))) (from_chain_pair cc) (nat i))" abbreviation round_spec :: "chain \ block \ chain" where "round_spec c b == to_chain (round (\n. word_of_int (b (int n))) (from_chain c))" spark_proof_functions steps = steps' round_spec = round_spec lemma uint_word_of_int_id: assumes "0 <= (x::int)" assumes "x <= 4294967295" shows"uint(word_of_int x::word32) = x" unfolding int_word_uint using assms - by (simp add:int_mod_eq') + by simp lemma steps_step: "steps X cc (Suc i) = step_both X (steps X cc i) i" unfolding steps_def by (induct i) simp_all lemma from_to_id: "from_chain_pair (to_chain_pair CC) = CC" proof (cases CC) fix a::RMD.chain fix b c d e f::word32 assume "CC = (a, b, c, d, e, f)" thus ?thesis by (cases a) simp qed lemma steps_to_steps': "F A (steps X cc i) B = F A (from_chain_pair (to_chain_pair (steps X cc i))) B" unfolding from_to_id .. lemma steps'_step: assumes "0 <= i" shows "steps' cc (i + 1) X = to_chain_pair ( step_both (\n. word_of_int (X (int n))) (from_chain_pair (steps' cc i X)) (nat i))" proof - have "nat (i + 1) = Suc (nat i)" using assms by simp show ?thesis unfolding \nat (i + 1) = Suc (nat i)\ steps_step steps_to_steps' .. qed lemma step_from_hyp: assumes step_hyp: "\left = \h0 = a, h1 = b, h2 = c, h3 = d, h4 = e\, right = \h0 = a', h1 = b', h2 = c', h3 = d', h4 = e'\\ = steps' (\left = \h0 = a_0, h1 = b_0, h2 = c_0, h3 = d_0, h4 = e_0\, right = \h0 = a_0, h1 = b_0, h2 = c_0, h3 = d_0, h4 = e_0\\) j x" assumes "a <= 4294967295" (is "_ <= ?M") assumes "b <= ?M" and "c <= ?M" and "d <= ?M" and "e <= ?M" assumes "a' <= ?M" and "b' <= ?M" and "c' <= ?M" and "d' <= ?M" and "e' <= ?M" assumes "0 <= a " and "0 <= b " and "0 <= c " and "0 <= d " and "0 <= e " assumes "0 <= a'" and "0 <= b'" and "0 <= c'" and "0 <= d'" and "0 <= e'" assumes "0 <= x (r_l_spec j)" and "x (r_l_spec j) <= ?M" assumes "0 <= x (r_r_spec j)" and "x (r_r_spec j) <= ?M" assumes "0 <= j" and "j <= 79" shows "\left = \h0 = e, h1 = (rotate_left (s_l_spec j) ((((a + f_spec j b c d) mod 4294967296 + x (r_l_spec j)) mod 4294967296 + k_l_spec j) mod 4294967296) + e) mod 4294967296, h2 = b, h3 = rotate_left 10 c, h4 = d\, right = \h0 = e', h1 = (rotate_left (s_r_spec j) ((((a' + f_spec (79 - j) b' c' d') mod 4294967296 + x (r_r_spec j)) mod 4294967296 + k_r_spec j) mod 4294967296) + e') mod 4294967296, h2 = b', h3 = rotate_left 10 c', h4 = d'\\ = steps' (\left = \h0 = a_0, h1 = b_0, h2 = c_0, h3 = d_0, h4 = e_0\, right = \h0 = a_0, h1 = b_0, h2 = c_0, h3 = d_0, h4 = e_0\\) (j + 1) x" using step_hyp proof - let ?MM = 4294967296 have AL: "uint(word_of_int e::word32) = e" by (rule uint_word_of_int_id[OF \0 <= e\ \e <= ?M\]) have CL: "uint(word_of_int b::word32) = b" by (rule uint_word_of_int_id[OF \0 <= b\ \b <= ?M\]) have DL: "True" .. have EL: "uint(word_of_int d::word32) = d" by (rule uint_word_of_int_id[OF \0 <= d\ \d <= ?M\]) have AR: "uint(word_of_int e'::word32) = e'" by (rule uint_word_of_int_id[OF \0 <= e'\ \e' <= ?M\]) have CR: "uint(word_of_int b'::word32) = b'" by (rule uint_word_of_int_id[OF \0 <= b'\ \b' <= ?M\]) have DR: "True" .. have ER: "uint(word_of_int d'::word32) = d'" by (rule uint_word_of_int_id[OF \0 <= d'\ \d' <= ?M\]) have BL: "(uint (word_rotl (s (nat j)) ((word_of_int::int\word32) ((((a + f_spec j b c d) mod ?MM + x (r_l_spec j)) mod ?MM + k_l_spec j) mod ?MM))) + e) mod ?MM = uint (word_rotl (s (nat j)) (word_of_int a + f (nat j) (word_of_int b) (word_of_int c) (word_of_int d) + word_of_int (x (r_l_spec j)) + K (nat j)) + word_of_int e)" (is "(uint (word_rotl _ (_ ((((_ + ?F) mod _ + ?X) mod _ + _) mod _))) + _) mod _ = _") proof - have "a mod ?MM = a" using \0 <= a\ \a <= ?M\ - by (simp add: int_mod_eq') + by simp have "?X mod ?MM = ?X" using \0 <= ?X\ \?X <= ?M\ - by (simp add: int_mod_eq') + by simp have "e mod ?MM = e" using \0 <= e\ \e <= ?M\ - by (simp add: int_mod_eq') + by simp have "(?MM::int) = 2 ^ LENGTH(32)" by simp show ?thesis unfolding word_add_def uint_word_of_int_id[OF \0 <= a\ \a <= ?M\] uint_word_of_int_id[OF \0 <= ?X\ \?X <= ?M\] int_word_uint unfolding \?MM = 2 ^ LENGTH(32)\ unfolding word_uint.Abs_norm by (simp add: \a mod ?MM = a\ \e mod ?MM = e\ \?X mod ?MM = ?X\) qed have BR: "(uint (word_rotl (s' (nat j)) ((word_of_int::int\word32) ((((a' + f_spec (79 - j) b' c' d') mod ?MM + x (r_r_spec j)) mod ?MM + k_r_spec j) mod ?MM))) + e') mod ?MM = uint (word_rotl (s' (nat j)) (word_of_int a' + f (79 - nat j) (word_of_int b') (word_of_int c') (word_of_int d') + word_of_int (x (r_r_spec j)) + K' (nat j)) + word_of_int e')" (is "(uint (word_rotl _ (_ ((((_ + ?F) mod _ + ?X) mod _ + _) mod _))) + _) mod _ = _") proof - have "a' mod ?MM = a'" using \0 <= a'\ \a' <= ?M\ - by (simp add: int_mod_eq') + by simp have "?X mod ?MM = ?X" using \0 <= ?X\ \?X <= ?M\ - by (simp add: int_mod_eq') + by simp have "e' mod ?MM = e'" using \0 <= e'\ \e' <= ?M\ - by (simp add: int_mod_eq') + by simp have "(?MM::int) = 2 ^ LENGTH(32)" by simp have nat_transfer: "79 - nat j = nat (79 - j)" using nat_diff_distrib \0 <= j\ \j <= 79\ by simp show ?thesis unfolding word_add_def uint_word_of_int_id[OF \0 <= a'\ \a' <= ?M\] uint_word_of_int_id[OF \0 <= ?X\ \?X <= ?M\] int_word_uint nat_transfer unfolding \?MM = 2 ^ LENGTH(32)\ unfolding word_uint.Abs_norm by (simp add: \a' mod ?MM = a'\ \e' mod ?MM = e'\ \?X mod ?MM = ?X\) qed show ?thesis unfolding steps'_step[OF \0 <= j\] step_hyp[symmetric] step_both_def step_r_def step_l_def by (simp add: AL BL CL DL EL AR BR CR DR ER) qed spark_vc procedure_round_61 proof - let ?M = "4294967295::int" have step_hyp: "\left = \h0 = ca, h1 = cb, h2 = cc, h3 = cd, h4 = ce\, right = \h0 = ca, h1 = cb, h2 = cc, h3 = cd, h4 = ce\\ = steps' (\left = \h0 = ca, h1 = cb, h2 = cc, h3 = cd, h4 = ce\, right = \h0 = ca, h1 = cb, h2 = cc, h3 = cd, h4 = ce\\) 0 x" unfolding steps_def by (simp add: uint_word_of_int_id[OF \0 <= ca\ \ca <= ?M\] uint_word_of_int_id[OF \0 <= cb\ \cb <= ?M\] uint_word_of_int_id[OF \0 <= cc\ \cc <= ?M\] uint_word_of_int_id[OF \0 <= cd\ \cd <= ?M\] uint_word_of_int_id[OF \0 <= ce\ \ce <= ?M\]) let ?rotate_arg_l = "((((ca + f 0 cb cc cd) mod 4294967296 + x (r_l 0)) mod 4294967296 + k_l 0) mod 4294967296)" let ?rotate_arg_r = "((((ca + f 79 cb cc cd) mod 4294967296 + x (r_r 0)) mod 4294967296 + k_r 0) mod 4294967296)" note returns = \wordops__rotate (s_l 0) ?rotate_arg_l = rotate_left (s_l 0) ?rotate_arg_l\ \wordops__rotate (s_r 0) ?rotate_arg_r = rotate_left (s_r 0) ?rotate_arg_r\ \wordops__rotate 10 cc = rotate_left 10 cc\ \f 0 cb cc cd = f_spec 0 cb cc cd\ \f 79 cb cc cd = f_spec 79 cb cc cd\ \k_l 0 = k_l_spec 0\ \k_r 0 = k_r_spec 0\ \r_l 0 = r_l_spec 0\ \r_r 0 = r_r_spec 0\ \s_l 0 = s_l_spec 0\ \s_r 0 = s_r_spec 0\ note x_borders = \\i. 0 \ i \ i \ 15 \ 0 \ x i \ x i \ ?M\ from \0 <= r_l 0\ \r_l 0 <= 15\ x_borders have "0 \ x (r_l 0)" by blast hence x_lower: "0 <= x (r_l_spec 0)" unfolding returns . from \0 <= r_l 0\ \r_l 0 <= 15\ x_borders have "x (r_l 0) <= ?M" by blast hence x_upper: "x (r_l_spec 0) <= ?M" unfolding returns . from \0 <= r_r 0\ \r_r 0 <= 15\ x_borders have "0 \ x (r_r 0)" by blast hence x_lower': "0 <= x (r_r_spec 0)" unfolding returns . from \0 <= r_r 0\ \r_r 0 <= 15\ x_borders have "x (r_r 0) <= ?M" by blast hence x_upper': "x (r_r_spec 0) <= ?M" unfolding returns . have "0 <= (0::int)" by simp have "0 <= (79::int)" by simp note step_from_hyp [OF step_hyp H2 H4 H6 H8 H10 H2 H4 H6 H8 H10 \ \upper bounds\ H1 H3 H5 H7 H9 H1 H3 H5 H7 H9 \ \lower bounds\ ] from this[OF x_lower x_upper x_lower' x_upper' \0 <= 0\ \0 <= 79\] \0 \ ca\ \0 \ ce\ x_lower x_lower' show ?thesis unfolding returns(1) returns(2) unfolding returns by (simp del: mod_pos_pos_trivial mod_neg_neg_trivial) qed spark_vc procedure_round_62 proof - let ?M = "4294967295::int" let ?rotate_arg_l = "((((cla + f (loop__1__j + 1) clb clc cld) mod 4294967296 + x (r_l (loop__1__j + 1))) mod 4294967296 + k_l (loop__1__j + 1)) mod 4294967296)" let ?rotate_arg_r = "((((cra + f (79 - (loop__1__j + 1)) crb crc crd) mod 4294967296 + x (r_r (loop__1__j + 1))) mod 4294967296 + k_r (loop__1__j + 1)) mod 4294967296)" have s: "78 - loop__1__j = (79 - (loop__1__j + 1))" by simp note returns = \wordops__rotate (s_l (loop__1__j + 1)) ?rotate_arg_l = rotate_left (s_l (loop__1__j + 1)) ?rotate_arg_l\ \wordops__rotate (s_r (loop__1__j + 1)) ?rotate_arg_r = rotate_left (s_r (loop__1__j + 1)) ?rotate_arg_r\ \f (loop__1__j + 1) clb clc cld = f_spec (loop__1__j + 1) clb clc cld\ \f (78 - loop__1__j) crb crc crd = f_spec (78 - loop__1__j) crb crc crd\[simplified s] \wordops__rotate 10 clc = rotate_left 10 clc\ \wordops__rotate 10 crc = rotate_left 10 crc\ \k_l (loop__1__j + 1) = k_l_spec (loop__1__j + 1)\ \k_r (loop__1__j + 1) = k_r_spec (loop__1__j + 1)\ \r_l (loop__1__j + 1) = r_l_spec (loop__1__j + 1)\ \r_r (loop__1__j + 1) = r_r_spec (loop__1__j + 1)\ \s_l (loop__1__j + 1) = s_l_spec (loop__1__j + 1)\ \s_r (loop__1__j + 1) = s_r_spec (loop__1__j + 1)\ note x_borders = \\i. 0 \ i \ i \ 15 \ 0 \ x i \ x i \ ?M\ from \0 <= r_l (loop__1__j + 1)\ \r_l (loop__1__j + 1) <= 15\ x_borders have "0 \ x (r_l (loop__1__j + 1))" by blast hence x_lower: "0 <= x (r_l_spec (loop__1__j + 1))" unfolding returns . from \0 <= r_l (loop__1__j + 1)\ \r_l (loop__1__j + 1) <= 15\ x_borders have "x (r_l (loop__1__j + 1)) <= ?M" by blast hence x_upper: "x (r_l_spec (loop__1__j + 1)) <= ?M" unfolding returns . from \0 <= r_r (loop__1__j + 1)\ \r_r (loop__1__j + 1) <= 15\ x_borders have "0 \ x (r_r (loop__1__j + 1))" by blast hence x_lower': "0 <= x (r_r_spec (loop__1__j + 1))" unfolding returns . from \0 <= r_r (loop__1__j + 1)\ \r_r (loop__1__j + 1) <= 15\ x_borders have "x (r_r (loop__1__j + 1)) <= ?M" by blast hence x_upper': "x (r_r_spec (loop__1__j + 1)) <= ?M" unfolding returns . from \0 <= loop__1__j\ have "0 <= loop__1__j + 1" by simp from \loop__1__j <= 78\ have "loop__1__j + 1 <= 79" by simp have "loop__1__j + 1 + 1 = loop__1__j + 2" by simp note step_from_hyp[OF H1 \cla <= ?M\ \clb <= ?M\ \clc <= ?M\ \cld <= ?M\ \cle <= ?M\ \cra <= ?M\ \crb <= ?M\ \crc <= ?M\ \crd <= ?M\ \cre <= ?M\ \0 <= cla\ \0 <= clb\ \0 <= clc\ \0 <= cld\ \0 <= cle\ \0 <= cra\ \0 <= crb\ \0 <= crc\ \0 <= crd\ \0 <= cre\] from this[OF x_lower x_upper x_lower' x_upper' \0 <= loop__1__j + 1\ \loop__1__j + 1 <= 79\] \0 \ cla\ \0 \ cle\ \0 \ cra\ \0 \ cre\ x_lower x_lower' show ?thesis unfolding \loop__1__j + 1 + 1 = loop__1__j + 2\ unfolding returns(1) returns(2) unfolding returns by (simp del: mod_pos_pos_trivial mod_neg_neg_trivial) qed spark_vc procedure_round_76 proof - let ?M = "4294967295 :: int" let ?INIT_CHAIN = "\h0 = ca_init, h1 = cb_init, h2 = cc_init, h3 = cd_init, h4 = ce_init\" have steps_to_steps': "steps (\n::nat. word_of_int (x (int n))) (from_chain ?INIT_CHAIN, from_chain ?INIT_CHAIN) 80 = from_chain_pair ( steps' (\left = ?INIT_CHAIN, right = ?INIT_CHAIN\) 80 x)" unfolding from_to_id by simp from \0 \ ca_init\ \ca_init \ ?M\ \0 \ cb_init\ \cb_init \ ?M\ \0 \ cc_init\ \cc_init \ ?M\ \0 \ cd_init\ \cd_init \ ?M\ \0 \ ce_init\ \ce_init \ ?M\ \0 \ cla\ \cla \ ?M\ \0 \ clb\ \clb \ ?M\ \0 \ clc\ \clc \ ?M\ \0 \ cld\ \cld \ ?M\ \0 \ cle\ \cle \ ?M\ \0 \ cra\ \cra \ ?M\ \0 \ crb\ \crb \ ?M\ \0 \ crc\ \crc \ ?M\ \0 \ crd\ \crd \ ?M\ \0 \ cre\ \cre \ ?M\ show ?thesis unfolding round_def unfolding steps_to_steps' unfolding H1[symmetric] by (simp add: uint_word_ariths(1) mod_simps uint_word_of_int_id) qed spark_end end diff --git a/src/HOL/Word/Bit_Lists.thy b/src/HOL/Word/Bit_Lists.thy new file mode 100644 --- /dev/null +++ b/src/HOL/Word/Bit_Lists.thy @@ -0,0 +1,137 @@ +(* Title: HOL/Word/Bit_Lists.thy + Author: Jeremy Dawson, NICTA +*) + +section \Bit values as reversed lists of bools\ + +theory Bit_Lists + imports Bits_Int +begin + +subsection \Implicit augmentation of list prefixes\ + +primrec takefill :: "'a \ nat \ 'a list \ 'a list" +where + Z: "takefill fill 0 xs = []" + | Suc: "takefill fill (Suc n) xs = + (case xs of + [] \ fill # takefill fill n xs + | y # ys \ y # takefill fill n ys)" + +lemma nth_takefill: "m < n \ takefill fill n l ! m = (if m < length l then l ! m else fill)" + apply (induct n arbitrary: m l) + apply clarsimp + apply clarsimp + apply (case_tac m) + apply (simp split: list.split) + apply (simp split: list.split) + done + +lemma takefill_alt: "takefill fill n l = take n l @ replicate (n - length l) fill" + by (induct n arbitrary: l) (auto split: list.split) + +lemma takefill_replicate [simp]: "takefill fill n (replicate m fill) = replicate n fill" + by (simp add: takefill_alt replicate_add [symmetric]) + +lemma takefill_le': "n = m + k \ takefill x m (takefill x n l) = takefill x m l" + by (induct m arbitrary: l n) (auto split: list.split) + +lemma length_takefill [simp]: "length (takefill fill n l) = n" + by (simp add: takefill_alt) + +lemma take_takefill': "n = k + m \ take k (takefill fill n w) = takefill fill k w" + by (induct k arbitrary: w n) (auto split: list.split) + +lemma drop_takefill: "drop k (takefill fill (m + k) w) = takefill fill m (drop k w)" + by (induct k arbitrary: w) (auto split: list.split) + +lemma takefill_le [simp]: "m \ n \ takefill x m (takefill x n l) = takefill x m l" + by (auto simp: le_iff_add takefill_le') + +lemma take_takefill [simp]: "m \ n \ take m (takefill fill n w) = takefill fill m w" + by (auto simp: le_iff_add take_takefill') + +lemma takefill_append: "takefill fill (m + length xs) (xs @ w) = xs @ (takefill fill m w)" + by (induct xs) auto + +lemma takefill_same': "l = length xs \ takefill fill l xs = xs" + by (induct xs arbitrary: l) auto + +lemmas takefill_same [simp] = takefill_same' [OF refl] + +lemma tf_rev: + "n + k = m + length bl \ takefill x m (rev (takefill y n bl)) = + rev (takefill y m (rev (takefill x k (rev bl))))" + apply (rule nth_equalityI) + apply (auto simp add: nth_takefill rev_nth) + apply (rule_tac f = "\n. bl ! n" in arg_cong) + apply arith + done + +lemma takefill_minus: "0 < n \ takefill fill (Suc (n - 1)) w = takefill fill n w" + by auto + +lemmas takefill_Suc_cases = + list.cases [THEN takefill.Suc [THEN trans]] + +lemmas takefill_Suc_Nil = takefill_Suc_cases (1) +lemmas takefill_Suc_Cons = takefill_Suc_cases (2) + +lemmas takefill_minus_simps = takefill_Suc_cases [THEN [2] + takefill_minus [symmetric, THEN trans]] + +lemma takefill_numeral_Nil [simp]: + "takefill fill (numeral k) [] = fill # takefill fill (pred_numeral k) []" + by (simp add: numeral_eq_Suc) + +lemma takefill_numeral_Cons [simp]: + "takefill fill (numeral k) (x # xs) = x # takefill fill (pred_numeral k) xs" + by (simp add: numeral_eq_Suc) + + +subsection \Range projection\ + +definition bl_of_nth :: "nat \ (nat \ 'a) \ 'a list" + where "bl_of_nth n f = map f (rev [0.. rev (bl_of_nth n f) ! m = f m" + by (simp add: bl_of_nth_def rev_map) + +lemma bl_of_nth_inj: "(\k. k < n \ f k = g k) \ bl_of_nth n f = bl_of_nth n g" + by (simp add: bl_of_nth_def) + +lemma bl_of_nth_nth_le: "n \ length xs \ bl_of_nth n (nth (rev xs)) = drop (length xs - n) xs" + apply (induct n arbitrary: xs) + apply clarsimp + apply clarsimp + apply (rule trans [OF _ hd_Cons_tl]) + apply (frule Suc_le_lessD) + apply (simp add: rev_nth trans [OF drop_Suc drop_tl, symmetric]) + apply (subst hd_drop_conv_nth) + apply force + apply simp_all + apply (rule_tac f = "\n. drop n xs" in arg_cong) + apply simp + done + +lemma bl_of_nth_nth [simp]: "bl_of_nth (length xs) ((!) (rev xs)) = xs" + by (simp add: bl_of_nth_nth_le) + +lemma takefill_bintrunc: "takefill False n bl = rev (bin_to_bl n (bl_to_bin (rev bl)))" + apply (rule nth_equalityI) + apply simp + apply (clarsimp simp: nth_takefill rev_nth nth_bin_to_bl bin_nth_of_bl) + done + +lemma bl_bin_bl_rtf: "bin_to_bl n (bl_to_bin bl) = rev (takefill False n (rev bl))" + by (simp add: takefill_bintrunc) + +end diff --git a/src/HOL/Word/Bits_Int.thy b/src/HOL/Word/Bits_Int.thy --- a/src/HOL/Word/Bits_Int.thy +++ b/src/HOL/Word/Bits_Int.thy @@ -1,2343 +1,2364 @@ (* Title: HOL/Word/Bits_Int.thy Author: Jeremy Dawson and Gerwin Klein, NICTA Definitions and basic theorems for bit-wise logical operations for integers expressed using Pls, Min, BIT, and converting them to and from lists of bools. *) section \Bitwise Operations on integers\ theory Bits_Int - imports Misc_Auxiliary Bits + imports Bits begin +subsection \Generic auxiliary\ + +lemma int_mod_ge: "a < n \ 0 < n \ a \ a mod n" + for a n :: int + by (metis dual_order.trans le_cases mod_pos_pos_trivial pos_mod_conj) + + subsection \Implicit bit representation of \<^typ>\int\\ abbreviation (input) bin_last :: "int \ bool" where "bin_last \ odd" lemma bin_last_def: "bin_last w \ w mod 2 = 1" by (fact odd_iff_mod_2_eq_one) abbreviation (input) bin_rest :: "int \ int" where "bin_rest w \ w div 2" lemma bin_last_numeral_simps [simp]: "\ bin_last 0" "bin_last 1" "bin_last (- 1)" "bin_last Numeral1" "\ bin_last (numeral (Num.Bit0 w))" "bin_last (numeral (Num.Bit1 w))" "\ bin_last (- numeral (Num.Bit0 w))" "bin_last (- numeral (Num.Bit1 w))" by simp_all lemma bin_rest_numeral_simps [simp]: "bin_rest 0 = 0" "bin_rest 1 = 0" "bin_rest (- 1) = - 1" "bin_rest Numeral1 = 0" "bin_rest (numeral (Num.Bit0 w)) = numeral w" "bin_rest (numeral (Num.Bit1 w)) = numeral w" "bin_rest (- numeral (Num.Bit0 w)) = - numeral w" "bin_rest (- numeral (Num.Bit1 w)) = - numeral (w + Num.One)" by simp_all lemma bin_rl_eqI: "\bin_rest x = bin_rest y; bin_last x = bin_last y\ \ x = y" by (auto elim: oddE) lemma [simp]: shows bin_rest_lt0: "bin_rest i < 0 \ i < 0" and bin_rest_ge_0: "bin_rest i \ 0 \ i \ 0" by auto lemma bin_rest_gt_0 [simp]: "bin_rest x > 0 \ x > 1" by auto subsection \Explicit bit representation of \<^typ>\int\\ primrec bl_to_bin_aux :: "bool list \ int \ int" where Nil: "bl_to_bin_aux [] w = w" | Cons: "bl_to_bin_aux (b # bs) w = bl_to_bin_aux bs (of_bool b + 2 * w)" definition bl_to_bin :: "bool list \ int" where "bl_to_bin bs = bl_to_bin_aux bs 0" primrec bin_to_bl_aux :: "nat \ int \ bool list \ bool list" where Z: "bin_to_bl_aux 0 w bl = bl" | Suc: "bin_to_bl_aux (Suc n) w bl = bin_to_bl_aux n (bin_rest w) ((bin_last w) # bl)" definition bin_to_bl :: "nat \ int \ bool list" where "bin_to_bl n w = bin_to_bl_aux n w []" lemma bin_to_bl_aux_zero_minus_simp [simp]: "0 < n \ bin_to_bl_aux n 0 bl = bin_to_bl_aux (n - 1) 0 (False # bl)" by (cases n) auto lemma bin_to_bl_aux_minus1_minus_simp [simp]: "0 < n \ bin_to_bl_aux n (- 1) bl = bin_to_bl_aux (n - 1) (- 1) (True # bl)" by (cases n) auto lemma bin_to_bl_aux_one_minus_simp [simp]: "0 < n \ bin_to_bl_aux n 1 bl = bin_to_bl_aux (n - 1) 0 (True # bl)" by (cases n) auto lemma bin_to_bl_aux_Bit0_minus_simp [simp]: "0 < n \ bin_to_bl_aux n (numeral (Num.Bit0 w)) bl = bin_to_bl_aux (n - 1) (numeral w) (False # bl)" by (cases n) simp_all lemma bin_to_bl_aux_Bit1_minus_simp [simp]: "0 < n \ bin_to_bl_aux n (numeral (Num.Bit1 w)) bl = bin_to_bl_aux (n - 1) (numeral w) (True # bl)" by (cases n) simp_all lemma bl_to_bin_aux_append: "bl_to_bin_aux (bs @ cs) w = bl_to_bin_aux cs (bl_to_bin_aux bs w)" by (induct bs arbitrary: w) auto lemma bin_to_bl_aux_append: "bin_to_bl_aux n w bs @ cs = bin_to_bl_aux n w (bs @ cs)" by (induct n arbitrary: w bs) auto lemma bl_to_bin_append: "bl_to_bin (bs @ cs) = bl_to_bin_aux cs (bl_to_bin bs)" unfolding bl_to_bin_def by (rule bl_to_bin_aux_append) lemma bin_to_bl_aux_alt: "bin_to_bl_aux n w bs = bin_to_bl n w @ bs" by (simp add: bin_to_bl_def bin_to_bl_aux_append) lemma bin_to_bl_0 [simp]: "bin_to_bl 0 bs = []" by (auto simp: bin_to_bl_def) lemma size_bin_to_bl_aux: "length (bin_to_bl_aux n w bs) = n + length bs" by (induct n arbitrary: w bs) auto lemma size_bin_to_bl [simp]: "length (bin_to_bl n w) = n" by (simp add: bin_to_bl_def size_bin_to_bl_aux) lemma bl_bin_bl': "bin_to_bl (n + length bs) (bl_to_bin_aux bs w) = bin_to_bl_aux n w bs" apply (induct bs arbitrary: w n) apply auto apply (simp_all only: add_Suc [symmetric]) apply (auto simp add: bin_to_bl_def) done lemma bl_bin_bl [simp]: "bin_to_bl (length bs) (bl_to_bin bs) = bs" unfolding bl_to_bin_def apply (rule box_equals) apply (rule bl_bin_bl') prefer 2 apply (rule bin_to_bl_aux.Z) apply simp done lemma bl_to_bin_inj: "bl_to_bin bs = bl_to_bin cs \ length bs = length cs \ bs = cs" apply (rule_tac box_equals) defer apply (rule bl_bin_bl) apply (rule bl_bin_bl) apply simp done lemma bl_to_bin_False [simp]: "bl_to_bin (False # bl) = bl_to_bin bl" by (auto simp: bl_to_bin_def) lemma bl_to_bin_Nil [simp]: "bl_to_bin [] = 0" by (auto simp: bl_to_bin_def) lemma bin_to_bl_zero_aux: "bin_to_bl_aux n 0 bl = replicate n False @ bl" by (induct n arbitrary: bl) (auto simp: replicate_app_Cons_same) lemma bin_to_bl_zero: "bin_to_bl n 0 = replicate n False" by (simp add: bin_to_bl_def bin_to_bl_zero_aux) lemma bin_to_bl_minus1_aux: "bin_to_bl_aux n (- 1) bl = replicate n True @ bl" by (induct n arbitrary: bl) (auto simp: replicate_app_Cons_same) lemma bin_to_bl_minus1: "bin_to_bl n (- 1) = replicate n True" by (simp add: bin_to_bl_def bin_to_bl_minus1_aux) subsection \Bit projection\ abbreviation (input) bin_nth :: \int \ nat \ bool\ where \bin_nth \ bit\ lemma bin_nth_eq_iff: "bin_nth x = bin_nth y \ x = y" by (simp add: bit_eq_iff fun_eq_iff) lemma bin_eqI: "x = y" if "\n. bin_nth x n \ bin_nth y n" using that bin_nth_eq_iff [of x y] by (simp add: fun_eq_iff) lemma bin_eq_iff: "x = y \ (\n. bin_nth x n = bin_nth y n)" by (fact bit_eq_iff) lemma bin_nth_zero [simp]: "\ bin_nth 0 n" by simp lemma bin_nth_1 [simp]: "bin_nth 1 n \ n = 0" by (cases n) (simp_all add: bit_Suc) lemma bin_nth_minus1 [simp]: "bin_nth (- 1) n" by (induction n) (simp_all add: bit_Suc) lemma bin_nth_numeral: "bin_rest x = y \ bin_nth x (numeral n) = bin_nth y (pred_numeral n)" by (simp add: numeral_eq_Suc bit_Suc) lemmas bin_nth_numeral_simps [simp] = bin_nth_numeral [OF bin_rest_numeral_simps(2)] bin_nth_numeral [OF bin_rest_numeral_simps(5)] bin_nth_numeral [OF bin_rest_numeral_simps(6)] bin_nth_numeral [OF bin_rest_numeral_simps(7)] bin_nth_numeral [OF bin_rest_numeral_simps(8)] lemmas bin_nth_simps = bit_0 bit_Suc bin_nth_zero bin_nth_minus1 bin_nth_numeral_simps lemma nth_2p_bin: "bin_nth (2 ^ n) m = (m = n)" \ \for use when simplifying with \bin_nth_Bit\\ by (auto simp add: bit_exp_iff) lemma nth_rest_power_bin: "bin_nth ((bin_rest ^^ k) w) n = bin_nth w (n + k)" apply (induct k arbitrary: n) apply clarsimp apply clarsimp apply (simp only: bit_Suc [symmetric] add_Suc) done lemma bin_nth_numeral_unfold: "bin_nth (numeral (num.Bit0 x)) n \ n > 0 \ bin_nth (numeral x) (n - 1)" "bin_nth (numeral (num.Bit1 x)) n \ (n > 0 \ bin_nth (numeral x) (n - 1))" by (cases n; simp)+ subsection \Truncating\ definition bin_sign :: "int \ int" where "bin_sign k = (if k \ 0 then 0 else - 1)" lemma bin_sign_simps [simp]: "bin_sign 0 = 0" "bin_sign 1 = 0" "bin_sign (- 1) = - 1" "bin_sign (numeral k) = 0" "bin_sign (- numeral k) = -1" by (simp_all add: bin_sign_def) lemma bin_sign_rest [simp]: "bin_sign (bin_rest w) = bin_sign w" by (simp add: bin_sign_def) abbreviation (input) bintrunc :: "nat \ int \ int" where \bintrunc \ take_bit\ lemma bintrunc_mod2p: "bintrunc n w = w mod 2 ^ n" by (fact take_bit_eq_mod) primrec sbintrunc :: "nat \ int \ int" where Z : "sbintrunc 0 bin = (if odd bin then - 1 else 0)" | Suc : "sbintrunc (Suc n) bin = of_bool (odd bin) + 2 * sbintrunc n (bin div 2)" lemma sbintrunc_mod2p: "sbintrunc n w = (w + 2 ^ n) mod 2 ^ Suc n - 2 ^ n" proof (induction n arbitrary: w) case 0 then show ?case by (auto simp add: odd_iff_mod_2_eq_one) next case (Suc n) from Suc [of \w div 2\] show ?case using even_succ_mod_exp [of \(b * 2 + 2 * 2 ^ n)\ \Suc (Suc n)\ for b :: int] by (auto elim!: evenE oddE simp add: mult_mod_right ac_simps) qed +lemma sbintrunc_eq_take_bit: + \sbintrunc n k = take_bit (Suc n) (k + 2 ^ n) - 2 ^ n\ + by (simp add: sbintrunc_mod2p take_bit_eq_mod) + lemma sign_bintr: "bin_sign (bintrunc n w) = 0" by (simp add: bintrunc_mod2p bin_sign_def) lemma bintrunc_n_0 [simp]: "bintrunc n 0 = 0" by (simp add: bintrunc_mod2p) lemma sbintrunc_n_0 [simp]: "sbintrunc n 0 = 0" by (simp add: sbintrunc_mod2p) lemma sbintrunc_n_minus1 [simp]: "sbintrunc n (- 1) = -1" by (induct n) auto lemma bintrunc_Suc_numeral: "bintrunc (Suc n) 1 = 1" "bintrunc (Suc n) (- 1) = 1 + 2 * bintrunc n (- 1)" "bintrunc (Suc n) (numeral (Num.Bit0 w)) = 2 * bintrunc n (numeral w)" "bintrunc (Suc n) (numeral (Num.Bit1 w)) = 1 + 2 * bintrunc n (numeral w)" "bintrunc (Suc n) (- numeral (Num.Bit0 w)) = 2 * bintrunc n (- numeral w)" "bintrunc (Suc n) (- numeral (Num.Bit1 w)) = 1 + 2 * bintrunc n (- numeral (w + Num.One))" by (simp_all add: take_bit_Suc) lemma sbintrunc_0_numeral [simp]: "sbintrunc 0 1 = -1" "sbintrunc 0 (numeral (Num.Bit0 w)) = 0" "sbintrunc 0 (numeral (Num.Bit1 w)) = -1" "sbintrunc 0 (- numeral (Num.Bit0 w)) = 0" "sbintrunc 0 (- numeral (Num.Bit1 w)) = -1" by simp_all lemma sbintrunc_Suc_numeral: "sbintrunc (Suc n) 1 = 1" "sbintrunc (Suc n) (numeral (Num.Bit0 w)) = 2 * sbintrunc n (numeral w)" "sbintrunc (Suc n) (numeral (Num.Bit1 w)) = 1 + 2 * sbintrunc n (numeral w)" "sbintrunc (Suc n) (- numeral (Num.Bit0 w)) = 2 * sbintrunc n (- numeral w)" "sbintrunc (Suc n) (- numeral (Num.Bit1 w)) = 1 + 2 * sbintrunc n (- numeral (w + Num.One))" by simp_all lemma bin_sign_lem: "(bin_sign (sbintrunc n bin) = -1) = bin_nth bin n" apply (rule sym) apply (induct n arbitrary: bin) apply (simp_all add: bit_Suc bin_sign_def) done lemma nth_bintr: "bin_nth (bintrunc m w) n \ n < m \ bin_nth w n" by (fact bit_take_bit_iff) lemma nth_sbintr: "bin_nth (sbintrunc m w) n = (if n < m then bin_nth w n else bin_nth w m)" apply (induct n arbitrary: w m) apply (case_tac m) apply simp_all apply (case_tac m) apply (simp_all add: bit_Suc) done lemma bin_nth_Bit0: "bin_nth (numeral (Num.Bit0 w)) n \ (\m. n = Suc m \ bin_nth (numeral w) m)" using bit_double_iff [of \numeral w :: int\ n] by (auto intro: exI [of _ \n - 1\]) lemma bin_nth_Bit1: "bin_nth (numeral (Num.Bit1 w)) n \ n = 0 \ (\m. n = Suc m \ bin_nth (numeral w) m)" using even_bit_succ_iff [of \2 * numeral w :: int\ n] bit_double_iff [of \numeral w :: int\ n] by auto lemma bintrunc_bintrunc_l: "n \ m \ bintrunc m (bintrunc n w) = bintrunc n w" by (simp add: min.absorb2) lemma sbintrunc_sbintrunc_l: "n \ m \ sbintrunc m (sbintrunc n w) = sbintrunc n w" by (rule bin_eqI) (auto simp: nth_sbintr) lemma bintrunc_bintrunc_ge: "n \ m \ bintrunc n (bintrunc m w) = bintrunc n w" by (rule bin_eqI) (auto simp: nth_bintr) lemma bintrunc_bintrunc_min [simp]: "bintrunc m (bintrunc n w) = bintrunc (min m n) w" by (rule bin_eqI) (auto simp: nth_bintr) lemma sbintrunc_sbintrunc_min [simp]: "sbintrunc m (sbintrunc n w) = sbintrunc (min m n) w" by (rule bin_eqI) (auto simp: nth_sbintr min.absorb1 min.absorb2) lemmas sbintrunc_Suc_Pls = sbintrunc.Suc [where bin="0", simplified bin_last_numeral_simps bin_rest_numeral_simps] lemmas sbintrunc_Suc_Min = sbintrunc.Suc [where bin="-1", simplified bin_last_numeral_simps bin_rest_numeral_simps] lemmas sbintrunc_Sucs = sbintrunc_Suc_Pls sbintrunc_Suc_Min sbintrunc_Suc_numeral lemmas sbintrunc_Pls = sbintrunc.Z [where bin="0", simplified bin_last_numeral_simps bin_rest_numeral_simps] lemmas sbintrunc_Min = sbintrunc.Z [where bin="-1", simplified bin_last_numeral_simps bin_rest_numeral_simps] lemmas sbintrunc_0_simps = sbintrunc_Pls sbintrunc_Min lemmas sbintrunc_simps = sbintrunc_0_simps sbintrunc_Sucs lemma bintrunc_minus: "0 < n \ bintrunc (Suc (n - 1)) w = bintrunc n w" by auto lemma sbintrunc_minus: "0 < n \ sbintrunc (Suc (n - 1)) w = sbintrunc n w" by auto lemmas sbintrunc_minus_simps = sbintrunc_Sucs [THEN [2] sbintrunc_minus [symmetric, THEN trans]] lemma sbintrunc_BIT_I: \0 < n \ sbintrunc (n - 1) 0 = y \ sbintrunc n 0 = 2 * y\ by simp lemma sbintrunc_Suc_Is: \sbintrunc n (- 1) = y \ sbintrunc (Suc n) (- 1) = 1 + 2 * y\ by auto lemma sbintrunc_Suc_lem: "sbintrunc (Suc n) x = y \ m = Suc n \ sbintrunc m x = y" by auto lemmas sbintrunc_Suc_Ialts = sbintrunc_Suc_Is [THEN sbintrunc_Suc_lem] lemma sbintrunc_bintrunc_lt: "m > n \ sbintrunc n (bintrunc m w) = sbintrunc n w" by (rule bin_eqI) (auto simp: nth_sbintr nth_bintr) lemma bintrunc_sbintrunc_le: "m \ Suc n \ bintrunc m (sbintrunc n w) = bintrunc m w" apply (rule bin_eqI) using le_Suc_eq less_Suc_eq_le apply (auto simp: nth_sbintr nth_bintr) done lemmas bintrunc_sbintrunc [simp] = order_refl [THEN bintrunc_sbintrunc_le] lemmas sbintrunc_bintrunc [simp] = lessI [THEN sbintrunc_bintrunc_lt] lemmas bintrunc_bintrunc [simp] = order_refl [THEN bintrunc_bintrunc_l] lemmas sbintrunc_sbintrunc [simp] = order_refl [THEN sbintrunc_sbintrunc_l] lemma bintrunc_sbintrunc' [simp]: "0 < n \ bintrunc n (sbintrunc (n - 1) w) = bintrunc n w" by (cases n) simp_all lemma sbintrunc_bintrunc' [simp]: "0 < n \ sbintrunc (n - 1) (bintrunc n w) = sbintrunc (n - 1) w" by (cases n) simp_all lemma bin_sbin_eq_iff: "bintrunc (Suc n) x = bintrunc (Suc n) y \ sbintrunc n x = sbintrunc n y" apply (rule iffI) apply (rule box_equals [OF _ sbintrunc_bintrunc sbintrunc_bintrunc]) apply simp apply (rule box_equals [OF _ bintrunc_sbintrunc bintrunc_sbintrunc]) apply simp done lemma bin_sbin_eq_iff': "0 < n \ bintrunc n x = bintrunc n y \ sbintrunc (n - 1) x = sbintrunc (n - 1) y" by (cases n) (simp_all add: bin_sbin_eq_iff) lemmas bintrunc_sbintruncS0 [simp] = bintrunc_sbintrunc' [unfolded One_nat_def] lemmas sbintrunc_bintruncS0 [simp] = sbintrunc_bintrunc' [unfolded One_nat_def] lemmas bintrunc_bintrunc_l' = le_add1 [THEN bintrunc_bintrunc_l] lemmas sbintrunc_sbintrunc_l' = le_add1 [THEN sbintrunc_sbintrunc_l] (* although bintrunc_minus_simps, if added to default simpset, tends to get applied where it's not wanted in developing the theories, we get a version for when the word length is given literally *) lemmas nat_non0_gr = trans [OF iszero_def [THEN Not_eq_iff [THEN iffD2]] refl] lemma bintrunc_numeral: "bintrunc (numeral k) x = of_bool (odd x) + 2 * bintrunc (pred_numeral k) (x div 2)" by (simp add: numeral_eq_Suc take_bit_Suc mod_2_eq_odd) lemma sbintrunc_numeral: "sbintrunc (numeral k) x = of_bool (odd x) + 2 * sbintrunc (pred_numeral k) (x div 2)" by (simp add: numeral_eq_Suc) lemma bintrunc_numeral_simps [simp]: "bintrunc (numeral k) (numeral (Num.Bit0 w)) = 2 * bintrunc (pred_numeral k) (numeral w)" "bintrunc (numeral k) (numeral (Num.Bit1 w)) = 1 + 2 * bintrunc (pred_numeral k) (numeral w)" "bintrunc (numeral k) (- numeral (Num.Bit0 w)) = 2 * bintrunc (pred_numeral k) (- numeral w)" "bintrunc (numeral k) (- numeral (Num.Bit1 w)) = 1 + 2 * bintrunc (pred_numeral k) (- numeral (w + Num.One))" "bintrunc (numeral k) 1 = 1" by (simp_all add: bintrunc_numeral) lemma sbintrunc_numeral_simps [simp]: "sbintrunc (numeral k) (numeral (Num.Bit0 w)) = 2 * sbintrunc (pred_numeral k) (numeral w)" "sbintrunc (numeral k) (numeral (Num.Bit1 w)) = 1 + 2 * sbintrunc (pred_numeral k) (numeral w)" "sbintrunc (numeral k) (- numeral (Num.Bit0 w)) = 2 * sbintrunc (pred_numeral k) (- numeral w)" "sbintrunc (numeral k) (- numeral (Num.Bit1 w)) = 1 + 2 * sbintrunc (pred_numeral k) (- numeral (w + Num.One))" "sbintrunc (numeral k) 1 = 1" by (simp_all add: sbintrunc_numeral) lemma no_bintr_alt1: "bintrunc n = (\w. w mod 2 ^ n :: int)" by (rule ext) (rule bintrunc_mod2p) lemma range_bintrunc: "range (bintrunc n) = {i. 0 \ i \ i < 2 ^ n}" - apply (unfold no_bintr_alt1) - apply (auto simp add: image_iff) - apply (rule exI) - apply (rule sym) - using int_mod_lem [symmetric, of "2 ^ n"] - apply auto - done + by (auto simp add: take_bit_eq_mod image_iff) (metis mod_pos_pos_trivial) lemma no_sbintr_alt2: "sbintrunc n = (\w. (w + 2 ^ n) mod 2 ^ Suc n - 2 ^ n :: int)" by (rule ext) (simp add : sbintrunc_mod2p) lemma range_sbintrunc: "range (sbintrunc n) = {i. - (2 ^ n) \ i \ i < 2 ^ n}" - apply (unfold no_sbintr_alt2) - apply (auto simp add: image_iff eq_diff_eq) - - apply (rule exI) - apply (auto intro: int_mod_lem [THEN iffD1, symmetric]) - done - -lemma sb_inc_lem: "a + 2^k < 0 \ a + 2^k + 2^(Suc k) \ (a + 2^k) mod 2^(Suc k)" - for a :: int - using int_mod_ge' [where n = "2 ^ (Suc k)" and b = "a + 2 ^ k"] - by simp - -lemma sb_inc_lem': "a < - (2^k) \ a + 2^k + 2^(Suc k) \ (a + 2^k) mod 2^(Suc k)" - for a :: int - by (rule sb_inc_lem) simp - -lemma sbintrunc_inc: "x < - (2^n) \ x + 2^(Suc n) \ sbintrunc n x" - unfolding no_sbintr_alt2 by (drule sb_inc_lem') simp - -lemma sb_dec_lem: "0 \ - (2 ^ k) + a \ (a + 2 ^ k) mod (2 * 2 ^ k) \ - (2 ^ k) + a" - for a :: int - using int_mod_le'[where n = "2 ^ (Suc k)" and b = "a + 2 ^ k"] by simp - -lemma sb_dec_lem': "2 ^ k \ a \ (a + 2 ^ k) mod (2 * 2 ^ k) \ - (2 ^ k) + a" - for a :: int - by (rule sb_dec_lem) simp - -lemma sbintrunc_dec: "x \ (2 ^ n) \ x - 2 ^ (Suc n) >= sbintrunc n x" - unfolding no_sbintr_alt2 by (drule sb_dec_lem') simp +proof - + have \surj (\k::int. k + 2 ^ n)\ + by (rule surjI [of _ \(\k. k - 2 ^ n)\]) simp + moreover have \sbintrunc n = ((\k. k - 2 ^ n) \ take_bit (Suc n) \ (\k. k + 2 ^ n))\ + by (simp add: sbintrunc_eq_take_bit fun_eq_iff) + ultimately show ?thesis + apply (simp only: fun.set_map range_bintrunc) + apply (auto simp add: image_iff) + apply presburger + done +qed + +lemma take_bit_greater_eq: + \k + 2 ^ n \ take_bit n k\ if \k < 0\ for k :: int +proof - + have \k + 2 ^ n \ take_bit n (k + 2 ^ n)\ + proof (cases \k > - (2 ^ n)\) + case False + then have \k + 2 ^ n \ 0\ + by simp + also note take_bit_nonnegative + finally show ?thesis . + next + case True + with that have \0 \ k + 2 ^ n\ and \k + 2 ^ n < 2 ^ n\ + by simp_all + then show ?thesis + by (simp only: take_bit_eq_mod mod_pos_pos_trivial) + qed + then show ?thesis + by (simp add: take_bit_eq_mod) +qed + +lemma take_bit_less_eq: + \take_bit n k \ k - 2 ^ n\ if \2 ^ n \ k\ and \n > 0\ for k :: int + using that zmod_le_nonneg_dividend [of \k - 2 ^ n\ \2 ^ n\] + by (simp add: take_bit_eq_mod) + +lemma sbintrunc_inc: + \k + 2 ^ Suc n \ sbintrunc n k\ if \k < - (2 ^ n)\ + using that take_bit_greater_eq [of \k + 2 ^ n\ \Suc n\] + by (simp add: sbintrunc_eq_take_bit) + +lemma sbintrunc_dec: + \sbintrunc n k \ k - 2 ^ (Suc n)\ if \k \ 2 ^ n\ + using that take_bit_less_eq [of \Suc n\ \k + 2 ^ n\] + by (simp add: sbintrunc_eq_take_bit) lemma bintr_ge0: "0 \ bintrunc n w" by (simp add: bintrunc_mod2p) lemma bintr_lt2p: "bintrunc n w < 2 ^ n" by (simp add: bintrunc_mod2p) lemma bintr_Min: "bintrunc n (- 1) = 2 ^ n - 1" - by (simp add: bintrunc_mod2p m1mod2k) - + by (simp add: stable_imp_take_bit_eq) + lemma sbintr_ge: "- (2 ^ n) \ sbintrunc n w" by (simp add: sbintrunc_mod2p) lemma sbintr_lt: "sbintrunc n w < 2 ^ n" by (simp add: sbintrunc_mod2p) lemma sign_Pls_ge_0: "bin_sign bin = 0 \ bin \ 0" for bin :: int by (simp add: bin_sign_def) lemma sign_Min_lt_0: "bin_sign bin = -1 \ bin < 0" for bin :: int by (simp add: bin_sign_def) lemma bin_rest_trunc: "bin_rest (bintrunc n bin) = bintrunc (n - 1) (bin_rest bin)" by (simp add: take_bit_rec [of n bin]) lemma bin_rest_power_trunc: "(bin_rest ^^ k) (bintrunc n bin) = bintrunc (n - k) ((bin_rest ^^ k) bin)" by (induct k) (auto simp: bin_rest_trunc) lemma bin_rest_trunc_i: "bintrunc n (bin_rest bin) = bin_rest (bintrunc (Suc n) bin)" by (auto simp add: take_bit_Suc) lemma bin_rest_strunc: "bin_rest (sbintrunc (Suc n) bin) = sbintrunc n (bin_rest bin)" - by (induct n arbitrary: bin) auto + by simp lemma bintrunc_rest [simp]: "bintrunc n (bin_rest (bintrunc n bin)) = bin_rest (bintrunc n bin)" by (induct n arbitrary: bin) (simp_all add: take_bit_Suc) lemma sbintrunc_rest [simp]: "sbintrunc n (bin_rest (sbintrunc n bin)) = bin_rest (sbintrunc n bin)" by (induct n arbitrary: bin) simp_all lemma bintrunc_rest': "bintrunc n \ bin_rest \ bintrunc n = bin_rest \ bintrunc n" by (rule ext) auto lemma sbintrunc_rest': "sbintrunc n \ bin_rest \ sbintrunc n = bin_rest \ sbintrunc n" by (rule ext) auto lemma rco_lem: "f \ g \ f = g \ f \ f \ (g \ f) ^^ n = g ^^ n \ f" apply (rule ext) apply (induct_tac n) apply (simp_all (no_asm)) apply (drule fun_cong) apply (unfold o_def) apply (erule trans) apply simp done lemmas rco_bintr = bintrunc_rest' [THEN rco_lem [THEN fun_cong], unfolded o_def] lemmas rco_sbintr = sbintrunc_rest' [THEN rco_lem [THEN fun_cong], unfolded o_def] lemma sbintrunc_code [code]: "sbintrunc n k = (let l = take_bit (Suc n) k in if bit l n then l - push_bit n 2 else l)" proof (induction n arbitrary: k) case 0 then show ?case by (simp add: mod_2_eq_odd and_one_eq) next case (Suc n) from Suc [of \k div 2\] show ?case by (auto simp add: Let_def push_bit_eq_mult algebra_simps take_bit_Suc [of \Suc n\] bit_Suc elim!: evenE oddE) qed subsection \Splitting and concatenation\ definition bin_split :: \nat \ int \ int \ int\ where [simp]: \bin_split n k = (drop_bit n k, take_bit n k)\ lemma [code]: "bin_split (Suc n) w = (let (w1, w2) = bin_split n (w div 2) in (w1, of_bool (odd w) + 2 * w2))" "bin_split 0 w = (w, 0)" by (simp_all add: drop_bit_Suc take_bit_Suc mod_2_eq_odd) primrec bin_cat :: "int \ nat \ int \ int" where Z: "bin_cat w 0 v = w" | Suc: "bin_cat w (Suc n) v = of_bool (odd v) + 2 * bin_cat w n (v div 2)" lemma bin_cat_eq_push_bit_add_take_bit: \bin_cat k n l = push_bit n k + take_bit n l\ by (induction n arbitrary: k l) (simp_all add: take_bit_Suc push_bit_double mod_2_eq_odd) lemma bin_sign_cat: "bin_sign (bin_cat x n y) = bin_sign x" proof - have \0 \ x\ if \0 \ x * 2 ^ n + y mod 2 ^ n\ proof - - from that have \x \ - 1\ - using int_mod_le' [of \y mod 2 ^ n\ \2 ^ n\] by auto + have \y mod 2 ^ n < 2 ^ n\ + using pos_mod_bound [of \2 ^ n\ y] by simp + then have \\ y mod 2 ^ n \ 2 ^ n\ + by (simp add: less_le) + with that have \x \ - 1\ + by auto have *: \- 1 \ (- (y mod 2 ^ n)) div 2 ^ n\ by (simp add: zdiv_zminus1_eq_if) from that have \- (y mod 2 ^ n) \ x * 2 ^ n\ by simp then have \(- (y mod 2 ^ n)) div 2 ^ n \ (x * 2 ^ n) div 2 ^ n\ using zdiv_mono1 zero_less_numeral zero_less_power by blast with * have \- 1 \ x * 2 ^ n div 2 ^ n\ by simp with \x \ - 1\ show ?thesis by simp qed then show ?thesis by (simp add: bin_sign_def not_le not_less bin_cat_eq_push_bit_add_take_bit push_bit_eq_mult take_bit_eq_mod) qed lemma bin_cat_assoc: "bin_cat (bin_cat x m y) n z = bin_cat x (m + n) (bin_cat y n z)" by (induct n arbitrary: z) auto lemma bin_cat_assoc_sym: "bin_cat x m (bin_cat y n z) = bin_cat (bin_cat x (m - n) y) (min m n) z" apply (induct n arbitrary: z m) apply clarsimp apply (case_tac m, auto) done definition bin_rcat :: "nat \ int list \ int" where "bin_rcat n = foldl (\u v. bin_cat u n v) 0" fun bin_rsplit_aux :: "nat \ nat \ int \ int list \ int list" where "bin_rsplit_aux n m c bs = (if m = 0 \ n = 0 then bs else let (a, b) = bin_split n c in bin_rsplit_aux n (m - n) a (b # bs))" definition bin_rsplit :: "nat \ nat \ int \ int list" where "bin_rsplit n w = bin_rsplit_aux n (fst w) (snd w) []" fun bin_rsplitl_aux :: "nat \ nat \ int \ int list \ int list" where "bin_rsplitl_aux n m c bs = (if m = 0 \ n = 0 then bs else let (a, b) = bin_split (min m n) c in bin_rsplitl_aux n (m - n) a (b # bs))" definition bin_rsplitl :: "nat \ nat \ int \ int list" where "bin_rsplitl n w = bin_rsplitl_aux n (fst w) (snd w) []" declare bin_rsplit_aux.simps [simp del] declare bin_rsplitl_aux.simps [simp del] lemma bin_nth_cat: "bin_nth (bin_cat x k y) n = (if n < k then bin_nth y n else bin_nth x (n - k))" apply (induct k arbitrary: n y) apply simp apply (case_tac n) apply (simp_all add: bit_Suc) done lemma bin_nth_drop_bit_iff: \bin_nth (drop_bit n c) k \ bin_nth c (n + k)\ by (simp add: bit_drop_bit_eq) lemma bin_nth_take_bit_iff: \bin_nth (take_bit n c) k \ k < n \ bin_nth c k\ by (fact bit_take_bit_iff) lemma bin_nth_split: "bin_split n c = (a, b) \ (\k. bin_nth a k = bin_nth c (n + k)) \ (\k. bin_nth b k = (k < n \ bin_nth c k))" by (auto simp add: bin_nth_drop_bit_iff bin_nth_take_bit_iff) lemma bin_cat_zero [simp]: "bin_cat 0 n w = bintrunc n w" by (simp add: bin_cat_eq_push_bit_add_take_bit) lemma bintr_cat1: "bintrunc (k + n) (bin_cat a n b) = bin_cat (bintrunc k a) n b" by (metis bin_cat_assoc bin_cat_zero) lemma bintr_cat: "bintrunc m (bin_cat a n b) = bin_cat (bintrunc (m - n) a) n (bintrunc (min m n) b)" by (rule bin_eqI) (auto simp: bin_nth_cat nth_bintr) lemma bintr_cat_same [simp]: "bintrunc n (bin_cat a n b) = bintrunc n b" by (auto simp add : bintr_cat) lemma cat_bintr [simp]: "bin_cat a n (bintrunc n b) = bin_cat a n b" by (simp add: bin_cat_eq_push_bit_add_take_bit) lemma split_bintrunc: "bin_split n c = (a, b) \ b = bintrunc n c" by simp lemma bin_cat_split: "bin_split n w = (u, v) \ w = bin_cat u n v" by (auto simp add: bin_cat_eq_push_bit_add_take_bit bits_ident) lemma drop_bit_bin_cat_eq: \drop_bit n (bin_cat v n w) = v\ by (induct n arbitrary: w) (simp_all add: drop_bit_Suc) lemma take_bit_bin_cat_eq: \take_bit n (bin_cat v n w) = take_bit n w\ by (induct n arbitrary: w) (simp_all add: take_bit_Suc mod_2_eq_odd) lemma bin_split_cat: "bin_split n (bin_cat v n w) = (v, bintrunc n w)" by (simp add: drop_bit_bin_cat_eq take_bit_bin_cat_eq) lemma bin_split_zero [simp]: "bin_split n 0 = (0, 0)" by simp lemma bin_split_minus1 [simp]: "bin_split n (- 1) = (- 1, bintrunc n (- 1))" by simp lemma bin_split_trunc: "bin_split (min m n) c = (a, b) \ bin_split n (bintrunc m c) = (bintrunc (m - n) a, b)" apply (induct n arbitrary: m b c, clarsimp) apply (simp add: bin_rest_trunc Let_def split: prod.split_asm) apply (case_tac m) apply (auto simp: Let_def drop_bit_Suc take_bit_Suc mod_2_eq_odd split: prod.split_asm) done lemma bin_split_trunc1: "bin_split n c = (a, b) \ bin_split n (bintrunc m c) = (bintrunc (m - n) a, bintrunc m b)" apply (induct n arbitrary: m b c, clarsimp) apply (simp add: bin_rest_trunc Let_def split: prod.split_asm) apply (case_tac m) apply (auto simp: Let_def drop_bit_Suc take_bit_Suc mod_2_eq_odd split: prod.split_asm) done lemma bin_cat_num: "bin_cat a n b = a * 2 ^ n + bintrunc n b" by (simp add: bin_cat_eq_push_bit_add_take_bit push_bit_eq_mult) lemma bin_split_num: "bin_split n b = (b div 2 ^ n, b mod 2 ^ n)" by (simp add: drop_bit_eq_div take_bit_eq_mod) lemmas bin_rsplit_aux_simps = bin_rsplit_aux.simps bin_rsplitl_aux.simps lemmas rsplit_aux_simps = bin_rsplit_aux_simps lemmas th_if_simp1 = if_split [where P = "(=) l", THEN iffD1, THEN conjunct1, THEN mp] for l lemmas th_if_simp2 = if_split [where P = "(=) l", THEN iffD1, THEN conjunct2, THEN mp] for l lemmas rsplit_aux_simp1s = rsplit_aux_simps [THEN th_if_simp1] lemmas rsplit_aux_simp2ls = rsplit_aux_simps [THEN th_if_simp2] \ \these safe to \[simp add]\ as require calculating \m - n\\ lemmas bin_rsplit_aux_simp2s [simp] = rsplit_aux_simp2ls [unfolded Let_def] lemmas rbscl = bin_rsplit_aux_simp2s (2) lemmas rsplit_aux_0_simps [simp] = rsplit_aux_simp1s [OF disjI1] rsplit_aux_simp1s [OF disjI2] lemma bin_rsplit_aux_append: "bin_rsplit_aux n m c (bs @ cs) = bin_rsplit_aux n m c bs @ cs" apply (induct n m c bs rule: bin_rsplit_aux.induct) apply (subst bin_rsplit_aux.simps) apply (subst bin_rsplit_aux.simps) apply (clarsimp split: prod.split) done lemma bin_rsplitl_aux_append: "bin_rsplitl_aux n m c (bs @ cs) = bin_rsplitl_aux n m c bs @ cs" apply (induct n m c bs rule: bin_rsplitl_aux.induct) apply (subst bin_rsplitl_aux.simps) apply (subst bin_rsplitl_aux.simps) apply (clarsimp split: prod.split) done lemmas rsplit_aux_apps [where bs = "[]"] = bin_rsplit_aux_append bin_rsplitl_aux_append lemmas rsplit_def_auxs = bin_rsplit_def bin_rsplitl_def lemmas rsplit_aux_alts = rsplit_aux_apps [unfolded append_Nil rsplit_def_auxs [symmetric]] lemma bin_split_minus: "0 < n \ bin_split (Suc (n - 1)) w = bin_split n w" by auto lemma bin_split_pred_simp [simp]: "(0::nat) < numeral bin \ bin_split (numeral bin) w = (let (w1, w2) = bin_split (numeral bin - 1) (bin_rest w) in (w1, of_bool (odd w) + 2 * w2))" by (simp add: take_bit_rec drop_bit_rec mod_2_eq_odd) lemma bin_rsplit_aux_simp_alt: "bin_rsplit_aux n m c bs = (if m = 0 \ n = 0 then bs else let (a, b) = bin_split n c in bin_rsplit n (m - n, a) @ b # bs)" apply (simp add: bin_rsplit_aux.simps [of n m c bs]) apply (subst rsplit_aux_alts) apply (simp add: bin_rsplit_def) done lemmas bin_rsplit_simp_alt = trans [OF bin_rsplit_def bin_rsplit_aux_simp_alt] lemmas bthrs = bin_rsplit_simp_alt [THEN [2] trans] lemma bin_rsplit_size_sign' [rule_format]: "n > 0 \ rev sw = bin_rsplit n (nw, w) \ \v\set sw. bintrunc n v = v" apply (induct sw arbitrary: nw w) apply clarsimp apply clarsimp apply (drule bthrs) apply (simp (no_asm_use) add: Let_def split: prod.split_asm if_split_asm) apply clarify apply simp done lemmas bin_rsplit_size_sign = bin_rsplit_size_sign' [OF asm_rl rev_rev_ident [THEN trans] set_rev [THEN equalityD2 [THEN subsetD]]] lemma bin_nth_rsplit [rule_format] : "n > 0 \ m < n \ \w k nw. rev sw = bin_rsplit n (nw, w) \ k < size sw \ bin_nth (sw ! k) m = bin_nth w (k * n + m)" apply (induct sw) apply clarsimp apply clarsimp apply (drule bthrs) apply (simp (no_asm_use) add: Let_def split: prod.split_asm if_split_asm) apply (erule allE, erule impE, erule exI) apply (case_tac k) apply clarsimp prefer 2 apply clarsimp apply (erule allE) apply (erule (1) impE) apply (simp add: bit_drop_bit_eq ac_simps) apply (simp add: bit_take_bit_iff ac_simps) done lemma bin_rsplit_all: "0 < nw \ nw \ n \ bin_rsplit n (nw, w) = [bintrunc n w]" by (auto simp: bin_rsplit_def rsplit_aux_simp2ls split: prod.split dest!: split_bintrunc) lemma bin_rsplit_l [rule_format]: "\bin. bin_rsplitl n (m, bin) = bin_rsplit n (m, bintrunc m bin)" apply (rule_tac a = "m" in wf_less_than [THEN wf_induct]) apply (simp (no_asm) add: bin_rsplitl_def bin_rsplit_def) apply (rule allI) apply (subst bin_rsplitl_aux.simps) apply (subst bin_rsplit_aux.simps) apply (clarsimp simp: Let_def split: prod.split) apply (simp add: ac_simps) apply (subst rsplit_aux_alts(1)) apply (subst rsplit_aux_alts(2)) apply clarsimp unfolding bin_rsplit_def bin_rsplitl_def apply (simp add: drop_bit_take_bit) apply (case_tac \x < n\) apply (simp_all add: not_less min_def) done lemma bin_rsplit_rcat [rule_format]: "n > 0 \ bin_rsplit n (n * size ws, bin_rcat n ws) = map (bintrunc n) ws" apply (unfold bin_rsplit_def bin_rcat_def) apply (rule_tac xs = ws in rev_induct) apply clarsimp apply clarsimp apply (subst rsplit_aux_alts) apply (simp add: drop_bit_bin_cat_eq take_bit_bin_cat_eq) done lemma bin_rsplit_aux_len_le [rule_format] : "\ws m. n \ 0 \ ws = bin_rsplit_aux n nw w bs \ length ws \ m \ nw + length bs * n \ m * n" proof - have *: R if d: "i \ j \ m < j'" and R1: "i * k \ j * k \ R" and R2: "Suc m * k' \ j' * k' \ R" for i j j' k k' m :: nat and R using d apply safe apply (rule R1, erule mult_le_mono1) apply (rule R2, erule Suc_le_eq [THEN iffD2 [THEN mult_le_mono1]]) done have **: "0 < sc \ sc - n + (n + lb * n) \ m * n \ sc + lb * n \ m * n" for sc m n lb :: nat apply safe apply arith apply (case_tac "sc \ n") apply arith apply (insert linorder_le_less_linear [of m lb]) apply (erule_tac k=n and k'=n in *) apply arith apply simp done show ?thesis apply (induct n nw w bs rule: bin_rsplit_aux.induct) apply (subst bin_rsplit_aux.simps) apply (simp add: ** Let_def split: prod.split) done qed lemma bin_rsplit_len_le: "n \ 0 \ ws = bin_rsplit n (nw, w) \ length ws \ m \ nw \ m * n" by (auto simp: bin_rsplit_def bin_rsplit_aux_len_le) lemma bin_rsplit_aux_len: "n \ 0 \ length (bin_rsplit_aux n nw w cs) = (nw + n - 1) div n + length cs" apply (induct n nw w cs rule: bin_rsplit_aux.induct) apply (subst bin_rsplit_aux.simps) apply (clarsimp simp: Let_def split: prod.split) apply (erule thin_rl) apply (case_tac m) apply simp apply (case_tac "m \ n") apply (auto simp add: div_add_self2) done lemma bin_rsplit_len: "n \ 0 \ length (bin_rsplit n (nw, w)) = (nw + n - 1) div n" by (auto simp: bin_rsplit_def bin_rsplit_aux_len) lemma bin_rsplit_aux_len_indep: "n \ 0 \ length bs = length cs \ length (bin_rsplit_aux n nw v bs) = length (bin_rsplit_aux n nw w cs)" proof (induct n nw w cs arbitrary: v bs rule: bin_rsplit_aux.induct) case (1 n m w cs v bs) show ?case proof (cases "m = 0") case True with \length bs = length cs\ show ?thesis by simp next case False from "1.hyps" [of \bin_split n w\ \drop_bit n w\ \take_bit n w\] \m \ 0\ \n \ 0\ have hyp: "\v bs. length bs = Suc (length cs) \ length (bin_rsplit_aux n (m - n) v bs) = length (bin_rsplit_aux n (m - n) (drop_bit n w) (take_bit n w # cs))" using bin_rsplit_aux_len by fastforce from \length bs = length cs\ \n \ 0\ show ?thesis by (auto simp add: bin_rsplit_aux_simp_alt Let_def bin_rsplit_len split: prod.split) qed qed lemma bin_rsplit_len_indep: "n \ 0 \ length (bin_rsplit n (nw, v)) = length (bin_rsplit n (nw, w))" apply (unfold bin_rsplit_def) apply (simp (no_asm)) apply (erule bin_rsplit_aux_len_indep) apply (rule refl) done subsection \Logical operations\ primrec bin_sc :: "nat \ bool \ int \ int" where Z: "bin_sc 0 b w = of_bool b + 2 * bin_rest w" | Suc: "bin_sc (Suc n) b w = of_bool (odd w) + 2 * bin_sc n b (w div 2)" lemma bin_nth_sc [simp]: "bit (bin_sc n b w) n \ b" by (induction n arbitrary: w) (simp_all add: bit_Suc) lemma bin_sc_sc_same [simp]: "bin_sc n c (bin_sc n b w) = bin_sc n c w" by (induction n arbitrary: w) (simp_all add: bit_Suc) lemma bin_sc_sc_diff: "m \ n \ bin_sc m c (bin_sc n b w) = bin_sc n b (bin_sc m c w)" apply (induct n arbitrary: w m) apply (case_tac [!] m) apply auto done lemma bin_nth_sc_gen: "bin_nth (bin_sc n b w) m = (if m = n then b else bin_nth w m)" apply (induct n arbitrary: w m) apply (case_tac m; simp add: bit_Suc) apply (case_tac m; simp add: bit_Suc) done lemma bin_sc_eq: \bin_sc n False = unset_bit n\ \bin_sc n True = Bit_Operations.set_bit n\ by (simp_all add: fun_eq_iff bit_eq_iff) (simp_all add: bin_nth_sc_gen bit_set_bit_iff bit_unset_bit_iff) lemma bin_sc_nth [simp]: "bin_sc n (bin_nth w n) w = w" by (rule bit_eqI) (simp add: bin_nth_sc_gen) lemma bin_sign_sc [simp]: "bin_sign (bin_sc n b w) = bin_sign w" proof (induction n arbitrary: w) case 0 then show ?case by (auto simp add: bin_sign_def) (use bin_rest_ge_0 in fastforce) next case (Suc n) from Suc [of \w div 2\] show ?case by (auto simp add: bin_sign_def split: if_splits) qed lemma bin_sc_bintr [simp]: "bintrunc m (bin_sc n x (bintrunc m w)) = bintrunc m (bin_sc n x w)" apply (cases x) apply (simp_all add: bin_sc_eq bit_eq_iff) apply (auto simp add: bit_take_bit_iff bit_set_bit_iff bit_unset_bit_iff) done lemma bin_clr_le: "bin_sc n False w \ w" by (simp add: bin_sc_eq unset_bit_less_eq) lemma bin_set_ge: "bin_sc n True w \ w" by (simp add: bin_sc_eq set_bit_greater_eq) lemma bintr_bin_clr_le: "bintrunc n (bin_sc m False w) \ bintrunc n w" by (simp add: bin_sc_eq take_bit_unset_bit_eq unset_bit_less_eq) lemma bintr_bin_set_ge: "bintrunc n (bin_sc m True w) \ bintrunc n w" by (simp add: bin_sc_eq take_bit_set_bit_eq set_bit_greater_eq) lemma bin_sc_FP [simp]: "bin_sc n False 0 = 0" by (induct n) auto lemma bin_sc_TM [simp]: "bin_sc n True (- 1) = - 1" by (induct n) auto lemmas bin_sc_simps = bin_sc.Z bin_sc.Suc bin_sc_TM bin_sc_FP lemma bin_sc_minus: "0 < n \ bin_sc (Suc (n - 1)) b w = bin_sc n b w" by auto lemmas bin_sc_Suc_minus = trans [OF bin_sc_minus [symmetric] bin_sc.Suc] lemma bin_sc_numeral [simp]: "bin_sc (numeral k) b w = of_bool (odd w) + 2 * bin_sc (pred_numeral k) b (w div 2)" by (simp add: numeral_eq_Suc) instantiation int :: bit_operations begin definition [iff]: "i !! n \ bin_nth i n" definition "lsb i = i !! 0" for i :: int definition "set_bit i n b = bin_sc n b i" definition "shiftl x n = x * 2 ^ n" for x :: int definition "shiftr x n = x div 2 ^ n" for x :: int definition "msb x \ x < 0" for x :: int instance .. end lemma shiftl_eq_push_bit: \k << n = push_bit n k\ for k :: int by (simp add: shiftl_int_def push_bit_eq_mult) lemma shiftr_eq_drop_bit: \k >> n = drop_bit n k\ for k :: int by (simp add: shiftr_int_def drop_bit_eq_div) subsubsection \Basic simplification rules\ lemmas int_not_def = not_int_def lemma int_not_simps [simp]: "NOT (0::int) = -1" "NOT (1::int) = -2" "NOT (- 1::int) = 0" "NOT (numeral w::int) = - numeral (w + Num.One)" "NOT (- numeral (Num.Bit0 w)::int) = numeral (Num.BitM w)" "NOT (- numeral (Num.Bit1 w)::int) = numeral (Num.Bit0 w)" by (simp_all add: not_int_def) lemma int_not_not: "NOT (NOT x) = x" for x :: int by (fact bit.double_compl) lemma int_and_0 [simp]: "0 AND x = 0" for x :: int by (fact bit.conj_zero_left) lemma int_and_m1 [simp]: "-1 AND x = x" for x :: int by (fact bit.conj_one_left) lemma int_or_zero [simp]: "0 OR x = x" for x :: int by (fact bit.disj_zero_left) lemma int_or_minus1 [simp]: "-1 OR x = -1" for x :: int by (fact bit.disj_one_left) lemma int_xor_zero [simp]: "0 XOR x = x" for x :: int by (fact bit.xor_zero_left) subsubsection \Binary destructors\ lemma bin_rest_NOT [simp]: "bin_rest (NOT x) = NOT (bin_rest x)" by (fact not_int_div_2) lemma bin_last_NOT [simp]: "bin_last (NOT x) \ \ bin_last x" by simp lemma bin_rest_AND [simp]: "bin_rest (x AND y) = bin_rest x AND bin_rest y" by (subst and_int_rec) auto lemma bin_last_AND [simp]: "bin_last (x AND y) \ bin_last x \ bin_last y" by (subst and_int_rec) auto lemma bin_rest_OR [simp]: "bin_rest (x OR y) = bin_rest x OR bin_rest y" by (subst or_int_rec) auto lemma bin_last_OR [simp]: "bin_last (x OR y) \ bin_last x \ bin_last y" by (subst or_int_rec) auto lemma bin_rest_XOR [simp]: "bin_rest (x XOR y) = bin_rest x XOR bin_rest y" by (subst xor_int_rec) auto lemma bin_last_XOR [simp]: "bin_last (x XOR y) \ (bin_last x \ bin_last y) \ \ (bin_last x \ bin_last y)" by (subst xor_int_rec) auto lemma bin_nth_ops: "\x y. bin_nth (x AND y) n \ bin_nth x n \ bin_nth y n" "\x y. bin_nth (x OR y) n \ bin_nth x n \ bin_nth y n" "\x y. bin_nth (x XOR y) n \ bin_nth x n \ bin_nth y n" "\x. bin_nth (NOT x) n \ \ bin_nth x n" by (simp_all add: bit_and_iff bit_or_iff bit_xor_iff bit_not_iff) subsubsection \Derived properties\ lemma int_xor_minus1 [simp]: "-1 XOR x = NOT x" for x :: int by (fact bit.xor_one_left) lemma int_xor_extra_simps [simp]: "w XOR 0 = w" "w XOR -1 = NOT w" for w :: int by simp_all lemma int_or_extra_simps [simp]: "w OR 0 = w" "w OR -1 = -1" for w :: int by simp_all lemma int_and_extra_simps [simp]: "w AND 0 = 0" "w AND -1 = w" for w :: int by simp_all text \Commutativity of the above.\ lemma bin_ops_comm: fixes x y :: int shows int_and_comm: "x AND y = y AND x" and int_or_comm: "x OR y = y OR x" and int_xor_comm: "x XOR y = y XOR x" by (simp_all add: ac_simps) lemma bin_ops_same [simp]: "x AND x = x" "x OR x = x" "x XOR x = 0" for x :: int by simp_all lemmas bin_log_esimps = int_and_extra_simps int_or_extra_simps int_xor_extra_simps int_and_0 int_and_m1 int_or_zero int_or_minus1 int_xor_zero int_xor_minus1 subsubsection \Basic properties of logical (bit-wise) operations\ lemma bbw_ao_absorb: "x AND (y OR x) = x \ x OR (y AND x) = x" for x y :: int by (auto simp add: bin_eq_iff bin_nth_ops) lemma bbw_ao_absorbs_other: "x AND (x OR y) = x \ (y AND x) OR x = x" "(y OR x) AND x = x \ x OR (x AND y) = x" "(x OR y) AND x = x \ (x AND y) OR x = x" for x y :: int by (auto simp add: bin_eq_iff bin_nth_ops) lemmas bbw_ao_absorbs [simp] = bbw_ao_absorb bbw_ao_absorbs_other lemma int_xor_not: "(NOT x) XOR y = NOT (x XOR y) \ x XOR (NOT y) = NOT (x XOR y)" for x y :: int by (auto simp add: bin_eq_iff bin_nth_ops) lemma int_and_assoc: "(x AND y) AND z = x AND (y AND z)" for x y z :: int by (auto simp add: bin_eq_iff bin_nth_ops) lemma int_or_assoc: "(x OR y) OR z = x OR (y OR z)" for x y z :: int by (auto simp add: bin_eq_iff bin_nth_ops) lemma int_xor_assoc: "(x XOR y) XOR z = x XOR (y XOR z)" for x y z :: int by (auto simp add: bin_eq_iff bin_nth_ops) lemmas bbw_assocs = int_and_assoc int_or_assoc int_xor_assoc (* BH: Why are these declared as simp rules??? *) lemma bbw_lcs [simp]: "y AND (x AND z) = x AND (y AND z)" "y OR (x OR z) = x OR (y OR z)" "y XOR (x XOR z) = x XOR (y XOR z)" for x y :: int by (auto simp add: bin_eq_iff bin_nth_ops) lemma bbw_not_dist: "NOT (x OR y) = (NOT x) AND (NOT y)" "NOT (x AND y) = (NOT x) OR (NOT y)" for x y :: int by (auto simp add: bin_eq_iff bin_nth_ops) lemma bbw_oa_dist: "(x AND y) OR z = (x OR z) AND (y OR z)" for x y z :: int by (auto simp add: bin_eq_iff bin_nth_ops) lemma bbw_ao_dist: "(x OR y) AND z = (x AND z) OR (y AND z)" for x y z :: int by (auto simp add: bin_eq_iff bin_nth_ops) (* Why were these declared simp??? declare bin_ops_comm [simp] bbw_assocs [simp] *) subsubsection \Simplification with numerals\ text \Cases for \0\ and \-1\ are already covered by other simp rules.\ lemma bin_rest_neg_numeral_BitM [simp]: "bin_rest (- numeral (Num.BitM w)) = - numeral w" by simp lemma bin_last_neg_numeral_BitM [simp]: "bin_last (- numeral (Num.BitM w))" by simp (* FIXME: The rule sets below are very large (24 rules for each operator). Is there a simpler way to do this? *) lemma int_and_numerals [simp]: "numeral (Num.Bit0 x) AND numeral (Num.Bit0 y) = (2 :: int) * (numeral x AND numeral y)" "numeral (Num.Bit0 x) AND numeral (Num.Bit1 y) = (2 :: int) * (numeral x AND numeral y)" "numeral (Num.Bit1 x) AND numeral (Num.Bit0 y) = (2 :: int) * (numeral x AND numeral y)" "numeral (Num.Bit1 x) AND numeral (Num.Bit1 y) = 1 + (2 :: int) * (numeral x AND numeral y)" "numeral (Num.Bit0 x) AND - numeral (Num.Bit0 y) = (2 :: int) * (numeral x AND - numeral y)" "numeral (Num.Bit0 x) AND - numeral (Num.Bit1 y) = (2 :: int) * (numeral x AND - numeral (y + Num.One))" "numeral (Num.Bit1 x) AND - numeral (Num.Bit0 y) = (2 :: int) * (numeral x AND - numeral y)" "numeral (Num.Bit1 x) AND - numeral (Num.Bit1 y) = 1 + (2 :: int) * (numeral x AND - numeral (y + Num.One))" "- numeral (Num.Bit0 x) AND numeral (Num.Bit0 y) = (2 :: int) * (- numeral x AND numeral y)" "- numeral (Num.Bit0 x) AND numeral (Num.Bit1 y) = (2 :: int) * (- numeral x AND numeral y)" "- numeral (Num.Bit1 x) AND numeral (Num.Bit0 y) = (2 :: int) * (- numeral (x + Num.One) AND numeral y)" "- numeral (Num.Bit1 x) AND numeral (Num.Bit1 y) = 1 + (2 :: int) * (- numeral (x + Num.One) AND numeral y)" "- numeral (Num.Bit0 x) AND - numeral (Num.Bit0 y) = (2 :: int) * (- numeral x AND - numeral y)" "- numeral (Num.Bit0 x) AND - numeral (Num.Bit1 y) = (2 :: int) * (- numeral x AND - numeral (y + Num.One))" "- numeral (Num.Bit1 x) AND - numeral (Num.Bit0 y) = (2 :: int) * (- numeral (x + Num.One) AND - numeral y)" "- numeral (Num.Bit1 x) AND - numeral (Num.Bit1 y) = 1 + (2 :: int) * (- numeral (x + Num.One) AND - numeral (y + Num.One))" "(1::int) AND numeral (Num.Bit0 y) = 0" "(1::int) AND numeral (Num.Bit1 y) = 1" "(1::int) AND - numeral (Num.Bit0 y) = 0" "(1::int) AND - numeral (Num.Bit1 y) = 1" "numeral (Num.Bit0 x) AND (1::int) = 0" "numeral (Num.Bit1 x) AND (1::int) = 1" "- numeral (Num.Bit0 x) AND (1::int) = 0" "- numeral (Num.Bit1 x) AND (1::int) = 1" by (rule bin_rl_eqI; simp)+ lemma int_or_numerals [simp]: "numeral (Num.Bit0 x) OR numeral (Num.Bit0 y) = (2 :: int) * (numeral x OR numeral y)" "numeral (Num.Bit0 x) OR numeral (Num.Bit1 y) = 1 + (2 :: int) * (numeral x OR numeral y)" "numeral (Num.Bit1 x) OR numeral (Num.Bit0 y) = 1 + (2 :: int) * (numeral x OR numeral y)" "numeral (Num.Bit1 x) OR numeral (Num.Bit1 y) = 1 + (2 :: int) * (numeral x OR numeral y)" "numeral (Num.Bit0 x) OR - numeral (Num.Bit0 y) = (2 :: int) * (numeral x OR - numeral y)" "numeral (Num.Bit0 x) OR - numeral (Num.Bit1 y) = 1 + (2 :: int) * (numeral x OR - numeral (y + Num.One))" "numeral (Num.Bit1 x) OR - numeral (Num.Bit0 y) = 1 + (2 :: int) * (numeral x OR - numeral y)" "numeral (Num.Bit1 x) OR - numeral (Num.Bit1 y) = 1 + (2 :: int) * (numeral x OR - numeral (y + Num.One))" "- numeral (Num.Bit0 x) OR numeral (Num.Bit0 y) = (2 :: int) * (- numeral x OR numeral y)" "- numeral (Num.Bit0 x) OR numeral (Num.Bit1 y) = 1 + (2 :: int) * (- numeral x OR numeral y)" "- numeral (Num.Bit1 x) OR numeral (Num.Bit0 y) = 1 + (2 :: int) * (- numeral (x + Num.One) OR numeral y)" "- numeral (Num.Bit1 x) OR numeral (Num.Bit1 y) = 1 + (2 :: int) * (- numeral (x + Num.One) OR numeral y)" "- numeral (Num.Bit0 x) OR - numeral (Num.Bit0 y) = (2 :: int) * (- numeral x OR - numeral y)" "- numeral (Num.Bit0 x) OR - numeral (Num.Bit1 y) = 1 + (2 :: int) * (- numeral x OR - numeral (y + Num.One))" "- numeral (Num.Bit1 x) OR - numeral (Num.Bit0 y) = 1 + (2 :: int) * (- numeral (x + Num.One) OR - numeral y)" "- numeral (Num.Bit1 x) OR - numeral (Num.Bit1 y) = 1 + (2 :: int) * (- numeral (x + Num.One) OR - numeral (y + Num.One))" "(1::int) OR numeral (Num.Bit0 y) = numeral (Num.Bit1 y)" "(1::int) OR numeral (Num.Bit1 y) = numeral (Num.Bit1 y)" "(1::int) OR - numeral (Num.Bit0 y) = - numeral (Num.BitM y)" "(1::int) OR - numeral (Num.Bit1 y) = - numeral (Num.Bit1 y)" "numeral (Num.Bit0 x) OR (1::int) = numeral (Num.Bit1 x)" "numeral (Num.Bit1 x) OR (1::int) = numeral (Num.Bit1 x)" "- numeral (Num.Bit0 x) OR (1::int) = - numeral (Num.BitM x)" "- numeral (Num.Bit1 x) OR (1::int) = - numeral (Num.Bit1 x)" by (rule bin_rl_eqI; simp)+ lemma int_xor_numerals [simp]: "numeral (Num.Bit0 x) XOR numeral (Num.Bit0 y) = (2 :: int) * (numeral x XOR numeral y)" "numeral (Num.Bit0 x) XOR numeral (Num.Bit1 y) = 1 + (2 :: int) * (numeral x XOR numeral y)" "numeral (Num.Bit1 x) XOR numeral (Num.Bit0 y) = 1 + (2 :: int) * (numeral x XOR numeral y)" "numeral (Num.Bit1 x) XOR numeral (Num.Bit1 y) = (2 :: int) * (numeral x XOR numeral y)" "numeral (Num.Bit0 x) XOR - numeral (Num.Bit0 y) = (2 :: int) * (numeral x XOR - numeral y)" "numeral (Num.Bit0 x) XOR - numeral (Num.Bit1 y) = 1 + (2 :: int) * (numeral x XOR - numeral (y + Num.One))" "numeral (Num.Bit1 x) XOR - numeral (Num.Bit0 y) = 1 + (2 :: int) * (numeral x XOR - numeral y)" "numeral (Num.Bit1 x) XOR - numeral (Num.Bit1 y) = (2 :: int) * (numeral x XOR - numeral (y + Num.One))" "- numeral (Num.Bit0 x) XOR numeral (Num.Bit0 y) = (2 :: int) * (- numeral x XOR numeral y)" "- numeral (Num.Bit0 x) XOR numeral (Num.Bit1 y) = 1 + (2 :: int) * (- numeral x XOR numeral y)" "- numeral (Num.Bit1 x) XOR numeral (Num.Bit0 y) = 1 + (2 :: int) * (- numeral (x + Num.One) XOR numeral y)" "- numeral (Num.Bit1 x) XOR numeral (Num.Bit1 y) = (2 :: int) * (- numeral (x + Num.One) XOR numeral y)" "- numeral (Num.Bit0 x) XOR - numeral (Num.Bit0 y) = (2 :: int) * (- numeral x XOR - numeral y)" "- numeral (Num.Bit0 x) XOR - numeral (Num.Bit1 y) = 1 + (2 :: int) * (- numeral x XOR - numeral (y + Num.One))" "- numeral (Num.Bit1 x) XOR - numeral (Num.Bit0 y) = 1 + (2 :: int) * (- numeral (x + Num.One) XOR - numeral y)" "- numeral (Num.Bit1 x) XOR - numeral (Num.Bit1 y) = (2 :: int) * (- numeral (x + Num.One) XOR - numeral (y + Num.One))" "(1::int) XOR numeral (Num.Bit0 y) = numeral (Num.Bit1 y)" "(1::int) XOR numeral (Num.Bit1 y) = numeral (Num.Bit0 y)" "(1::int) XOR - numeral (Num.Bit0 y) = - numeral (Num.BitM y)" "(1::int) XOR - numeral (Num.Bit1 y) = - numeral (Num.Bit0 (y + Num.One))" "numeral (Num.Bit0 x) XOR (1::int) = numeral (Num.Bit1 x)" "numeral (Num.Bit1 x) XOR (1::int) = numeral (Num.Bit0 x)" "- numeral (Num.Bit0 x) XOR (1::int) = - numeral (Num.BitM x)" "- numeral (Num.Bit1 x) XOR (1::int) = - numeral (Num.Bit0 (x + Num.One))" by (rule bin_rl_eqI; simp)+ subsubsection \Interactions with arithmetic\ lemma plus_and_or: "(x AND y) + (x OR y) = x + y" for x y :: int proof (induction x arbitrary: y rule: int_bit_induct) case zero then show ?case by simp next case minus then show ?case by simp next case (even x) from even.IH [of \y div 2\] show ?case by (auto simp add: and_int_rec [of _ y] or_int_rec [of _ y] elim: oddE) next case (odd x) from odd.IH [of \y div 2\] show ?case by (auto simp add: and_int_rec [of _ y] or_int_rec [of _ y] elim: oddE) qed lemma le_int_or: "bin_sign y = 0 \ x \ x OR y" for x y :: int by (simp add: bin_sign_def or_greater_eq split: if_splits) lemmas int_and_le = xtrans(3) [OF bbw_ao_absorbs (2) [THEN conjunct2, symmetric] le_int_or] text \Interaction between bit-wise and arithmetic: good example of \bin_induction\.\ lemma bin_add_not: "x + NOT x = (-1::int)" by (simp add: not_int_def) lemma AND_mod: "x AND (2 ^ n - 1) = x mod 2 ^ n" for x :: int by (simp flip: take_bit_eq_mod add: take_bit_eq_mask mask_eq_exp_minus_1) subsubsection \Comparison\ lemma AND_lower [simp]: \<^marker>\contributor \Stefan Berghofer\\ fixes x y :: int assumes "0 \ x" shows "0 \ x AND y" using assms by simp lemma OR_lower [simp]: \<^marker>\contributor \Stefan Berghofer\\ fixes x y :: int assumes "0 \ x" "0 \ y" shows "0 \ x OR y" using assms by simp lemma XOR_lower [simp]: \<^marker>\contributor \Stefan Berghofer\\ fixes x y :: int assumes "0 \ x" "0 \ y" shows "0 \ x XOR y" using assms by simp lemma AND_upper1 [simp]: \<^marker>\contributor \Stefan Berghofer\\ fixes x y :: int assumes "0 \ x" shows "x AND y \ x" using assms by (induction x arbitrary: y rule: int_bit_induct) (simp_all add: and_int_rec [of \_ * 2\] and_int_rec [of \1 + _ * 2\] add_increasing) lemmas AND_upper1' [simp] = order_trans [OF AND_upper1] \<^marker>\contributor \Stefan Berghofer\\ lemmas AND_upper1'' [simp] = order_le_less_trans [OF AND_upper1] \<^marker>\contributor \Stefan Berghofer\\ lemma AND_upper2 [simp]: \<^marker>\contributor \Stefan Berghofer\\ fixes x y :: int assumes "0 \ y" shows "x AND y \ y" using assms AND_upper1 [of y x] by (simp add: ac_simps) lemmas AND_upper2' [simp] = order_trans [OF AND_upper2] \<^marker>\contributor \Stefan Berghofer\\ lemmas AND_upper2'' [simp] = order_le_less_trans [OF AND_upper2] \<^marker>\contributor \Stefan Berghofer\\ lemma OR_upper: \<^marker>\contributor \Stefan Berghofer\\ fixes x y :: int assumes "0 \ x" "x < 2 ^ n" "y < 2 ^ n" shows "x OR y < 2 ^ n" using assms proof (induction x arbitrary: y n rule: int_bit_induct) case zero then show ?case by simp next case minus then show ?case by simp next case (even x) from even.IH [of \n - 1\ \y div 2\] even.prems even.hyps show ?case by (cases n) (auto simp add: or_int_rec [of \_ * 2\] elim: oddE) next case (odd x) from odd.IH [of \n - 1\ \y div 2\] odd.prems odd.hyps show ?case by (cases n) (auto simp add: or_int_rec [of \1 + _ * 2\], linarith) qed lemma XOR_upper: \<^marker>\contributor \Stefan Berghofer\\ fixes x y :: int assumes "0 \ x" "x < 2 ^ n" "y < 2 ^ n" shows "x XOR y < 2 ^ n" using assms proof (induction x arbitrary: y n rule: int_bit_induct) case zero then show ?case by simp next case minus then show ?case by simp next case (even x) from even.IH [of \n - 1\ \y div 2\] even.prems even.hyps show ?case by (cases n) (auto simp add: xor_int_rec [of \_ * 2\] elim: oddE) next case (odd x) from odd.IH [of \n - 1\ \y div 2\] odd.prems odd.hyps show ?case by (cases n) (auto simp add: xor_int_rec [of \1 + _ * 2\]) qed subsubsection \Truncating results of bit-wise operations\ lemma bin_trunc_ao: "bintrunc n x AND bintrunc n y = bintrunc n (x AND y)" "bintrunc n x OR bintrunc n y = bintrunc n (x OR y)" by (auto simp add: bin_eq_iff bin_nth_ops nth_bintr) lemma bin_trunc_xor: "bintrunc n (bintrunc n x XOR bintrunc n y) = bintrunc n (x XOR y)" by (auto simp add: bin_eq_iff bin_nth_ops nth_bintr) lemma bin_trunc_not: "bintrunc n (NOT (bintrunc n x)) = bintrunc n (NOT x)" by (auto simp add: bin_eq_iff bin_nth_ops nth_bintr) text \Want theorems of the form of \bin_trunc_xor\.\ lemma bintr_bintr_i: "x = bintrunc n y \ bintrunc n x = bintrunc n y" by auto lemmas bin_trunc_and = bin_trunc_ao(1) [THEN bintr_bintr_i] lemmas bin_trunc_or = bin_trunc_ao(2) [THEN bintr_bintr_i] subsubsection \More lemmas\ lemma not_int_cmp_0 [simp]: fixes i :: int shows "0 < NOT i \ i < -1" "0 \ NOT i \ i < 0" "NOT i < 0 \ i \ 0" "NOT i \ 0 \ i \ -1" by(simp_all add: int_not_def) arith+ lemma bbw_ao_dist2: "(x :: int) AND (y OR z) = x AND y OR x AND z" by (fact bit.conj_disj_distrib) lemmas int_and_ac = bbw_lcs(1) int_and_comm int_and_assoc lemma int_nand_same [simp]: fixes x :: int shows "x AND NOT x = 0" by simp lemma int_nand_same_middle: fixes x :: int shows "x AND y AND NOT x = 0" by (simp add: bit_eq_iff bit_and_iff bit_not_iff) lemma and_xor_dist: fixes x :: int shows "x AND (y XOR z) = (x AND y) XOR (x AND z)" by (fact bit.conj_xor_distrib) lemma int_and_lt0 [simp]: \x AND y < 0 \ x < 0 \ y < 0\ for x y :: int by (fact and_negative_int_iff) lemma int_and_ge0 [simp]: \x AND y \ 0 \ x \ 0 \ y \ 0\ for x y :: int by (fact and_nonnegative_int_iff) lemma int_and_1: fixes x :: int shows "x AND 1 = x mod 2" by (fact and_one_eq) lemma int_1_and: fixes x :: int shows "1 AND x = x mod 2" by (fact one_and_eq) lemma int_or_lt0 [simp]: \x OR y < 0 \ x < 0 \ y < 0\ for x y :: int by (fact or_negative_int_iff) lemma int_or_ge0 [simp]: \x OR y \ 0 \ x \ 0 \ y \ 0\ for x y :: int by (fact or_nonnegative_int_iff) lemma int_xor_lt0 [simp]: \x XOR y < 0 \ (x < 0) \ (y < 0)\ for x y :: int by (fact xor_negative_int_iff) lemma int_xor_ge0 [simp]: \x XOR y \ 0 \ (x \ 0 \ y \ 0)\ for x y :: int by (fact xor_nonnegative_int_iff) lemma even_conv_AND: \even i \ i AND 1 = 0\ for i :: int by (simp add: and_one_eq mod2_eq_if) lemma bin_last_conv_AND: "bin_last i \ i AND 1 \ 0" by (simp add: and_one_eq mod2_eq_if) lemma bitval_bin_last: "of_bool (bin_last i) = i AND 1" by (simp add: and_one_eq mod2_eq_if) lemma bin_sign_and: "bin_sign (i AND j) = - (bin_sign i * bin_sign j)" by(simp add: bin_sign_def) lemma int_not_neg_numeral: "NOT (- numeral n) = (Num.sub n num.One :: int)" by(simp add: int_not_def) lemma int_neg_numeral_pOne_conv_not: "- numeral (n + num.One) = (NOT (numeral n) :: int)" by(simp add: int_not_def) subsection \Setting and clearing bits\ lemma bin_last_conv_lsb: "bin_last = lsb" by(clarsimp simp add: lsb_int_def fun_eq_iff) lemma int_lsb_numeral [simp]: "lsb (0 :: int) = False" "lsb (1 :: int) = True" "lsb (Numeral1 :: int) = True" "lsb (- 1 :: int) = True" "lsb (- Numeral1 :: int) = True" "lsb (numeral (num.Bit0 w) :: int) = False" "lsb (numeral (num.Bit1 w) :: int) = True" "lsb (- numeral (num.Bit0 w) :: int) = False" "lsb (- numeral (num.Bit1 w) :: int) = True" by (simp_all add: lsb_int_def) lemma int_set_bit_0 [simp]: fixes x :: int shows "set_bit x 0 b = of_bool b + 2 * (x div 2)" by (auto simp add: set_bit_int_def intro: bin_rl_eqI) lemma int_set_bit_Suc: fixes x :: int shows "set_bit x (Suc n) b = of_bool (odd x) + 2 * set_bit (x div 2) n b" by (auto simp add: set_bit_int_def intro: bin_rl_eqI) lemma bin_last_set_bit: "bin_last (set_bit x n b) = (if n > 0 then bin_last x else b)" by (cases n) (simp_all add: int_set_bit_Suc) lemma bin_rest_set_bit: "bin_rest (set_bit x n b) = (if n > 0 then set_bit (x div 2) (n - 1) b else x div 2)" by (cases n) (simp_all add: int_set_bit_Suc) lemma int_set_bit_numeral: fixes x :: int shows "set_bit x (numeral w) b = of_bool (odd x) + 2 * set_bit (x div 2) (pred_numeral w) b" by (simp add: set_bit_int_def) lemmas int_set_bit_numerals [simp] = int_set_bit_numeral[where x="numeral w'"] int_set_bit_numeral[where x="- numeral w'"] int_set_bit_numeral[where x="Numeral1"] int_set_bit_numeral[where x="1"] int_set_bit_numeral[where x="0"] int_set_bit_Suc[where x="numeral w'"] int_set_bit_Suc[where x="- numeral w'"] int_set_bit_Suc[where x="Numeral1"] int_set_bit_Suc[where x="1"] int_set_bit_Suc[where x="0"] for w' lemma int_shiftl_BIT: fixes x :: int shows int_shiftl0 [simp]: "x << 0 = x" and int_shiftl_Suc [simp]: "x << Suc n = 2 * (x << n)" by (auto simp add: shiftl_int_def) lemma int_0_shiftl [simp]: "0 << n = (0 :: int)" by(induct n) simp_all lemma bin_last_shiftl: "bin_last (x << n) \ n = 0 \ bin_last x" by(cases n)(simp_all) lemma bin_rest_shiftl: "bin_rest (x << n) = (if n > 0 then x << (n - 1) else bin_rest x)" by(cases n)(simp_all) lemma bin_nth_shiftl [simp]: "bin_nth (x << n) m \ n \ m \ bin_nth x (m - n)" by (simp add: bit_push_bit_iff_int shiftl_eq_push_bit) lemma bin_last_shiftr: "odd (x >> n) \ x !! n" for x :: int by (simp add: shiftr_eq_drop_bit bit_iff_odd_drop_bit) lemma bin_rest_shiftr [simp]: "bin_rest (x >> n) = x >> Suc n" by (simp add: bit_eq_iff shiftr_eq_drop_bit drop_bit_Suc bit_drop_bit_eq drop_bit_half) lemma bin_nth_shiftr [simp]: "bin_nth (x >> n) m = bin_nth x (n + m)" by (simp add: shiftr_eq_drop_bit bit_drop_bit_eq) lemma bin_nth_conv_AND: fixes x :: int shows "bin_nth x n \ x AND (1 << n) \ 0" by (simp add: bit_eq_iff) (auto simp add: shiftl_eq_push_bit bit_and_iff bit_push_bit_iff bit_exp_iff) lemma int_shiftl_numeral [simp]: "(numeral w :: int) << numeral w' = numeral (num.Bit0 w) << pred_numeral w'" "(- numeral w :: int) << numeral w' = - numeral (num.Bit0 w) << pred_numeral w'" by(simp_all add: numeral_eq_Suc shiftl_int_def) (metis add_One mult_inc semiring_norm(11) semiring_norm(13) semiring_norm(2) semiring_norm(6) semiring_norm(87))+ lemma int_shiftl_One_numeral [simp]: "(1 :: int) << numeral w = 2 << pred_numeral w" using int_shiftl_numeral [of Num.One w] by simp lemma shiftl_ge_0 [simp]: fixes i :: int shows "i << n \ 0 \ i \ 0" by(induct n) simp_all lemma shiftl_lt_0 [simp]: fixes i :: int shows "i << n < 0 \ i < 0" by (metis not_le shiftl_ge_0) lemma int_shiftl_test_bit: "(n << i :: int) !! m \ m \ i \ n !! (m - i)" by simp lemma int_0shiftr [simp]: "(0 :: int) >> x = 0" by(simp add: shiftr_int_def) lemma int_minus1_shiftr [simp]: "(-1 :: int) >> x = -1" by(simp add: shiftr_int_def div_eq_minus1) lemma int_shiftr_ge_0 [simp]: fixes i :: int shows "i >> n \ 0 \ i \ 0" by (simp add: shiftr_eq_drop_bit) lemma int_shiftr_lt_0 [simp]: fixes i :: int shows "i >> n < 0 \ i < 0" by (metis int_shiftr_ge_0 not_less) lemma int_shiftr_numeral [simp]: "(1 :: int) >> numeral w' = 0" "(numeral num.One :: int) >> numeral w' = 0" "(numeral (num.Bit0 w) :: int) >> numeral w' = numeral w >> pred_numeral w'" "(numeral (num.Bit1 w) :: int) >> numeral w' = numeral w >> pred_numeral w'" "(- numeral (num.Bit0 w) :: int) >> numeral w' = - numeral w >> pred_numeral w'" "(- numeral (num.Bit1 w) :: int) >> numeral w' = - numeral (Num.inc w) >> pred_numeral w'" by (simp_all add: shiftr_eq_drop_bit numeral_eq_Suc add_One drop_bit_Suc) lemma int_shiftr_numeral_Suc0 [simp]: "(1 :: int) >> Suc 0 = 0" "(numeral num.One :: int) >> Suc 0 = 0" "(numeral (num.Bit0 w) :: int) >> Suc 0 = numeral w" "(numeral (num.Bit1 w) :: int) >> Suc 0 = numeral w" "(- numeral (num.Bit0 w) :: int) >> Suc 0 = - numeral w" "(- numeral (num.Bit1 w) :: int) >> Suc 0 = - numeral (Num.inc w)" by (simp_all add: shiftr_eq_drop_bit drop_bit_Suc add_One) lemma bin_nth_minus_p2: assumes sign: "bin_sign x = 0" and y: "y = 1 << n" and m: "m < n" and x: "x < y" shows "bin_nth (x - y) m = bin_nth x m" proof - from sign y x have \x \ 0\ and \y = 2 ^ n\ and \x < 2 ^ n\ by (simp_all add: bin_sign_def shiftl_eq_push_bit push_bit_eq_mult split: if_splits) from \0 \ x\ \x < 2 ^ n\ \m < n\ have \bit x m \ bit (x - 2 ^ n) m\ proof (induction m arbitrary: x n) case 0 then show ?case by simp next case (Suc m) moreover define q where \q = n - 1\ ultimately have n: \n = Suc q\ by simp have \(x - 2 ^ Suc q) div 2 = x div 2 - 2 ^ q\ by simp moreover from Suc.IH [of \x div 2\ q] Suc.prems have \bit (x div 2) m \ bit (x div 2 - 2 ^ q) m\ by (simp add: n) ultimately show ?case by (simp add: bit_Suc n) qed with \y = 2 ^ n\ show ?thesis by simp qed lemma bin_clr_conv_NAND: "bin_sc n False i = i AND NOT (1 << n)" by (induct n arbitrary: i) (rule bin_rl_eqI; simp)+ lemma bin_set_conv_OR: "bin_sc n True i = i OR (1 << n)" by (induct n arbitrary: i) (rule bin_rl_eqI; simp)+ lemma msb_conv_bin_sign: "msb x \ bin_sign x = -1" by(simp add: bin_sign_def not_le msb_int_def) lemma msb_bin_rest [simp]: "msb (bin_rest x) = msb x" by(simp add: msb_int_def) lemma int_msb_and [simp]: "msb ((x :: int) AND y) \ msb x \ msb y" by(simp add: msb_int_def) lemma int_msb_or [simp]: "msb ((x :: int) OR y) \ msb x \ msb y" by(simp add: msb_int_def) lemma int_msb_xor [simp]: "msb ((x :: int) XOR y) \ msb x \ msb y" by(simp add: msb_int_def) lemma int_msb_not [simp]: "msb (NOT (x :: int)) \ \ msb x" by(simp add: msb_int_def not_less) lemma msb_shiftl [simp]: "msb ((x :: int) << n) \ msb x" by(simp add: msb_int_def) lemma msb_shiftr [simp]: "msb ((x :: int) >> r) \ msb x" by(simp add: msb_int_def) lemma msb_bin_sc [simp]: "msb (bin_sc n b x) \ msb x" by(simp add: msb_conv_bin_sign) lemma msb_set_bit [simp]: "msb (set_bit (x :: int) n b) \ msb x" by(simp add: msb_conv_bin_sign set_bit_int_def) lemma msb_0 [simp]: "msb (0 :: int) = False" by(simp add: msb_int_def) lemma msb_1 [simp]: "msb (1 :: int) = False" by(simp add: msb_int_def) lemma msb_numeral [simp]: "msb (numeral n :: int) = False" "msb (- numeral n :: int) = True" by(simp_all add: msb_int_def) subsection \Semantic interpretation of \<^typ>\bool list\ as \<^typ>\int\\ lemma bin_bl_bin': "bl_to_bin (bin_to_bl_aux n w bs) = bl_to_bin_aux bs (bintrunc n w)" by (induct n arbitrary: w bs) (auto simp: bl_to_bin_def take_bit_Suc ac_simps mod_2_eq_odd) lemma bin_bl_bin [simp]: "bl_to_bin (bin_to_bl n w) = bintrunc n w" by (auto simp: bin_to_bl_def bin_bl_bin') lemma bl_to_bin_rep_F: "bl_to_bin (replicate n False @ bl) = bl_to_bin bl" by (simp add: bin_to_bl_zero_aux [symmetric] bin_bl_bin') (simp add: bl_to_bin_def) lemma bin_to_bl_trunc [simp]: "n \ m \ bin_to_bl n (bintrunc m w) = bin_to_bl n w" by (auto intro: bl_to_bin_inj) lemma bin_to_bl_aux_bintr: "bin_to_bl_aux n (bintrunc m bin) bl = replicate (n - m) False @ bin_to_bl_aux (min n m) bin bl" apply (induct n arbitrary: m bin bl) apply clarsimp apply clarsimp apply (case_tac "m") apply (clarsimp simp: bin_to_bl_zero_aux) apply (erule thin_rl) apply (induct_tac n) apply (auto simp add: take_bit_Suc) done lemma bin_to_bl_bintr: "bin_to_bl n (bintrunc m bin) = replicate (n - m) False @ bin_to_bl (min n m) bin" unfolding bin_to_bl_def by (rule bin_to_bl_aux_bintr) lemma bl_to_bin_rep_False: "bl_to_bin (replicate n False) = 0" by (induct n) auto lemma len_bin_to_bl_aux: "length (bin_to_bl_aux n w bs) = n + length bs" by (fact size_bin_to_bl_aux) lemma len_bin_to_bl: "length (bin_to_bl n w) = n" by (fact size_bin_to_bl) (* FIXME: duplicate *) lemma sign_bl_bin': "bin_sign (bl_to_bin_aux bs w) = bin_sign w" by (induction bs arbitrary: w) (simp_all add: bin_sign_def) lemma sign_bl_bin: "bin_sign (bl_to_bin bs) = 0" by (simp add: bl_to_bin_def sign_bl_bin') lemma bl_sbin_sign_aux: "hd (bin_to_bl_aux (Suc n) w bs) = (bin_sign (sbintrunc n w) = -1)" by (induction n arbitrary: w bs) (simp_all add: bin_sign_def) lemma bl_sbin_sign: "hd (bin_to_bl (Suc n) w) = (bin_sign (sbintrunc n w) = -1)" unfolding bin_to_bl_def by (rule bl_sbin_sign_aux) lemma bin_nth_of_bl_aux: "bin_nth (bl_to_bin_aux bl w) n = (n < size bl \ rev bl ! n \ n \ length bl \ bin_nth w (n - size bl))" apply (induction bl arbitrary: w) apply simp_all apply safe apply (simp_all add: not_le nth_append bit_double_iff even_bit_succ_iff split: if_splits) done lemma bin_nth_of_bl: "bin_nth (bl_to_bin bl) n = (n < length bl \ rev bl ! n)" by (simp add: bl_to_bin_def bin_nth_of_bl_aux) lemma bin_nth_bl: "n < m \ bin_nth w n = nth (rev (bin_to_bl m w)) n" apply (induct n arbitrary: m w) apply clarsimp apply (case_tac m, clarsimp) apply (clarsimp simp: bin_to_bl_def) apply (simp add: bin_to_bl_aux_alt) apply (case_tac m, clarsimp) apply (clarsimp simp: bin_to_bl_def) apply (simp add: bin_to_bl_aux_alt bit_Suc) done lemma nth_bin_to_bl_aux: "n < m + length bl \ (bin_to_bl_aux m w bl) ! n = - (if n < m then bin_nth w (m - 1 - n) else bl ! (n - m))" + (if n < m then bit w (m - 1 - n) else bl ! (n - m))" apply (induction bl arbitrary: w) apply simp_all - apply (metis add.right_neutral bin_nth_bl bin_to_bl_def diff_Suc_less less_Suc_eq_0_disj less_imp_Suc_add list.size(3) nth_rev_alt size_bin_to_bl_aux) - apply (metis One_nat_def Suc_pred add_diff_cancel_left' add_diff_cancel_right' bin_to_bl_aux_alt bin_to_bl_def cancel_comm_monoid_add_class.diff_cancel diff_Suc_Suc diff_is_0_eq diff_zero le_add_diff_inverse le_eq_less_or_eq less_Suc_eq_0_disj less_antisym less_imp_Suc_add list.size(3) nat_less_le nth_append order_refl size_bin_to_bl_aux) + apply (simp add: bin_nth_bl [of \m - Suc n\ m] rev_nth flip: bin_to_bl_def) + apply (metis One_nat_def Suc_pred add_diff_cancel_left' + add_diff_cancel_right' bin_to_bl_aux_alt bin_to_bl_def + diff_Suc_Suc diff_is_0_eq diff_zero less_Suc_eq_0_disj + less_antisym less_imp_Suc_add list.size(3) nat_less_le nth_append size_bin_to_bl_aux) done lemma nth_bin_to_bl: "n < m \ (bin_to_bl m w) ! n = bin_nth w (m - Suc n)" by (simp add: bin_to_bl_def nth_bin_to_bl_aux) lemma bl_to_bin_lt2p_aux: "bl_to_bin_aux bs w < (w + 1) * (2 ^ length bs)" proof (induction bs arbitrary: w) case Nil then show ?case by simp next case (Cons b bs) from Cons.IH [of \1 + 2 * w\] Cons.IH [of \2 * w\] show ?case apply (auto simp add: algebra_simps) apply (subst mult_2 [of \2 ^ length bs\]) apply (simp only: add.assoc) apply (rule pos_add_strict) apply simp_all done qed lemma bl_to_bin_lt2p_drop: "bl_to_bin bs < 2 ^ length (dropWhile Not bs)" proof (induct bs) case Nil then show ?case by simp next case (Cons b bs) with bl_to_bin_lt2p_aux[where w=1] show ?case by (simp add: bl_to_bin_def) qed lemma bl_to_bin_lt2p: "bl_to_bin bs < 2 ^ length bs" by (metis bin_bl_bin bintr_lt2p bl_bin_bl) lemma bl_to_bin_ge2p_aux: "bl_to_bin_aux bs w \ w * (2 ^ length bs)" proof (induction bs arbitrary: w) case Nil then show ?case by simp next case (Cons b bs) from Cons.IH [of \1 + 2 * w\] Cons.IH [of \2 * w\] show ?case apply (auto simp add: algebra_simps) apply (rule add_le_imp_le_left [of \2 ^ length bs\]) apply (rule add_increasing) apply simp_all done qed lemma bl_to_bin_ge0: "bl_to_bin bs \ 0" apply (unfold bl_to_bin_def) apply (rule xtrans(4)) apply (rule bl_to_bin_ge2p_aux) apply simp done lemma butlast_rest_bin: "butlast (bin_to_bl n w) = bin_to_bl (n - 1) (bin_rest w)" apply (unfold bin_to_bl_def) apply (cases n, clarsimp) apply clarsimp apply (auto simp add: bin_to_bl_aux_alt) done lemma butlast_bin_rest: "butlast bl = bin_to_bl (length bl - Suc 0) (bin_rest (bl_to_bin bl))" using butlast_rest_bin [where w="bl_to_bin bl" and n="length bl"] by simp lemma butlast_rest_bl2bin_aux: "bl \ [] \ bl_to_bin_aux (butlast bl) w = bin_rest (bl_to_bin_aux bl w)" by (induct bl arbitrary: w) auto lemma butlast_rest_bl2bin: "bl_to_bin (butlast bl) = bin_rest (bl_to_bin bl)" by (cases bl) (auto simp: bl_to_bin_def butlast_rest_bl2bin_aux) lemma trunc_bl2bin_aux: "bintrunc m (bl_to_bin_aux bl w) = bl_to_bin_aux (drop (length bl - m) bl) (bintrunc (m - length bl) w)" proof (induct bl arbitrary: w) case Nil show ?case by simp next case (Cons b bl) show ?case proof (cases "m - length bl") case 0 then have "Suc (length bl) - m = Suc (length bl - m)" by simp with Cons show ?thesis by simp next case (Suc n) then have "m - Suc (length bl) = n" by simp with Cons Suc show ?thesis by (simp add: take_bit_Suc ac_simps) qed qed lemma trunc_bl2bin: "bintrunc m (bl_to_bin bl) = bl_to_bin (drop (length bl - m) bl)" by (simp add: bl_to_bin_def trunc_bl2bin_aux) lemma trunc_bl2bin_len [simp]: "bintrunc (length bl) (bl_to_bin bl) = bl_to_bin bl" by (simp add: trunc_bl2bin) lemma bl2bin_drop: "bl_to_bin (drop k bl) = bintrunc (length bl - k) (bl_to_bin bl)" apply (rule trans) prefer 2 apply (rule trunc_bl2bin [symmetric]) apply (cases "k \ length bl") apply auto done lemma take_rest_power_bin: "m \ n \ take m (bin_to_bl n w) = bin_to_bl m ((bin_rest ^^ (n - m)) w)" apply (rule nth_equalityI) apply simp apply (clarsimp simp add: nth_bin_to_bl nth_rest_power_bin) done lemma last_bin_last': "size xs > 0 \ last xs \ bin_last (bl_to_bin_aux xs w)" by (induct xs arbitrary: w) auto lemma last_bin_last: "size xs > 0 \ last xs \ bin_last (bl_to_bin xs)" unfolding bl_to_bin_def by (erule last_bin_last') lemma bin_last_last: "bin_last w \ last (bin_to_bl (Suc n) w)" by (simp add: bin_to_bl_def) (auto simp: bin_to_bl_aux_alt) lemma drop_bin2bl_aux: "drop m (bin_to_bl_aux n bin bs) = bin_to_bl_aux (n - m) bin (drop (m - n) bs)" apply (induction n arbitrary: m bin bs) apply auto apply (case_tac "m \ n") apply (auto simp add: not_le Suc_diff_le) apply (case_tac "m - n") apply auto apply (use Suc_diff_Suc in fastforce) done lemma drop_bin2bl: "drop m (bin_to_bl n bin) = bin_to_bl (n - m) bin" by (simp add: bin_to_bl_def drop_bin2bl_aux) lemma take_bin2bl_lem1: "take m (bin_to_bl_aux m w bs) = bin_to_bl m w" apply (induct m arbitrary: w bs) apply clarsimp apply clarsimp apply (simp add: bin_to_bl_aux_alt) apply (simp add: bin_to_bl_def) apply (simp add: bin_to_bl_aux_alt) done lemma take_bin2bl_lem: "take m (bin_to_bl_aux (m + n) w bs) = take m (bin_to_bl (m + n) w)" by (induct n arbitrary: w bs) (simp_all (no_asm) add: bin_to_bl_def take_bin2bl_lem1, simp) lemma bin_split_take: "bin_split n c = (a, b) \ bin_to_bl m a = take m (bin_to_bl (m + n) c)" apply (induct n arbitrary: b c) apply clarsimp apply (clarsimp simp: Let_def split: prod.split_asm) apply (simp add: bin_to_bl_def) apply (simp add: take_bin2bl_lem drop_bit_Suc) done lemma bin_to_bl_drop_bit: "k = m + n \ bin_to_bl m (drop_bit n c) = take m (bin_to_bl k c)" using bin_split_take by simp lemma bin_split_take1: "k = m + n \ bin_split n c = (a, b) \ bin_to_bl m a = take m (bin_to_bl k c)" using bin_split_take by simp -lemma takefill_bintrunc: "takefill False n bl = rev (bin_to_bl n (bl_to_bin (rev bl)))" - apply (rule nth_equalityI) - apply simp - apply (clarsimp simp: nth_takefill nth_rev nth_bin_to_bl bin_nth_of_bl) - done - -lemma bl_bin_bl_rtf: "bin_to_bl n (bl_to_bin bl) = rev (takefill False n (rev bl))" - by (simp add: takefill_bintrunc) - lemma bl_bin_bl_rep_drop: "bin_to_bl n (bl_to_bin bl) = replicate (n - length bl) False @ drop (length bl - n) bl" - by (simp add: bl_bin_bl_rtf takefill_alt rev_take) + by (simp add: bl_to_bin_inj bl_to_bin_rep_F trunc_bl2bin) lemma bl_to_bin_aux_cat: "bl_to_bin_aux bs (bin_cat w nv v) = bin_cat w (nv + length bs) (bl_to_bin_aux bs v)" by (rule bit_eqI) (auto simp add: bin_nth_of_bl_aux bin_nth_cat algebra_simps) lemma bin_to_bl_aux_cat: "\w bs. bin_to_bl_aux (nv + nw) (bin_cat v nw w) bs = bin_to_bl_aux nv v (bin_to_bl_aux nw w bs)" by (induct nw) auto lemma bl_to_bin_aux_alt: "bl_to_bin_aux bs w = bin_cat w (length bs) (bl_to_bin bs)" using bl_to_bin_aux_cat [where nv = "0" and v = "0"] by (simp add: bl_to_bin_def [symmetric]) lemma bin_to_bl_cat: "bin_to_bl (nv + nw) (bin_cat v nw w) = bin_to_bl_aux nv v (bin_to_bl nw w)" by (simp add: bin_to_bl_def bin_to_bl_aux_cat) lemmas bl_to_bin_aux_app_cat = trans [OF bl_to_bin_aux_append bl_to_bin_aux_alt] lemmas bin_to_bl_aux_cat_app = trans [OF bin_to_bl_aux_cat bin_to_bl_aux_alt] lemma bl_to_bin_app_cat: "bl_to_bin (bsa @ bs) = bin_cat (bl_to_bin bsa) (length bs) (bl_to_bin bs)" by (simp only: bl_to_bin_aux_app_cat bl_to_bin_def) lemma bin_to_bl_cat_app: "bin_to_bl (n + nw) (bin_cat w nw wa) = bin_to_bl n w @ bin_to_bl nw wa" by (simp only: bin_to_bl_def bin_to_bl_aux_cat_app) text \\bl_to_bin_app_cat_alt\ and \bl_to_bin_app_cat\ are easily interderivable.\ lemma bl_to_bin_app_cat_alt: "bin_cat (bl_to_bin cs) n w = bl_to_bin (cs @ bin_to_bl n w)" by (simp add: bl_to_bin_app_cat) lemma mask_lem: "(bl_to_bin (True # replicate n False)) = bl_to_bin (replicate n True) + 1" apply (unfold bl_to_bin_def) apply (induct n) apply simp apply (simp only: Suc_eq_plus1 replicate_add append_Cons [symmetric] bl_to_bin_aux_append) apply simp done lemma bin_exhaust: "(\x b. bin = of_bool b + 2 * x \ Q) \ Q" for bin :: int apply (cases \even bin\) apply (auto elim!: evenE oddE) apply fastforce apply fastforce done primrec rbl_succ :: "bool list \ bool list" where Nil: "rbl_succ Nil = Nil" | Cons: "rbl_succ (x # xs) = (if x then False # rbl_succ xs else True # xs)" primrec rbl_pred :: "bool list \ bool list" where Nil: "rbl_pred Nil = Nil" | Cons: "rbl_pred (x # xs) = (if x then False # xs else True # rbl_pred xs)" primrec rbl_add :: "bool list \ bool list \ bool list" where \ \result is length of first arg, second arg may be longer\ Nil: "rbl_add Nil x = Nil" | Cons: "rbl_add (y # ys) x = (let ws = rbl_add ys (tl x) in (y \ hd x) # (if hd x \ y then rbl_succ ws else ws))" primrec rbl_mult :: "bool list \ bool list \ bool list" where \ \result is length of first arg, second arg may be longer\ Nil: "rbl_mult Nil x = Nil" | Cons: "rbl_mult (y # ys) x = (let ws = False # rbl_mult ys x in if y then rbl_add ws x else ws)" lemma size_rbl_pred: "length (rbl_pred bl) = length bl" by (induct bl) auto lemma size_rbl_succ: "length (rbl_succ bl) = length bl" by (induct bl) auto lemma size_rbl_add: "length (rbl_add bl cl) = length bl" by (induct bl arbitrary: cl) (auto simp: Let_def size_rbl_succ) lemma size_rbl_mult: "length (rbl_mult bl cl) = length bl" by (induct bl arbitrary: cl) (auto simp add: Let_def size_rbl_add) lemmas rbl_sizes [simp] = size_rbl_pred size_rbl_succ size_rbl_add size_rbl_mult lemmas rbl_Nils = rbl_pred.Nil rbl_succ.Nil rbl_add.Nil rbl_mult.Nil lemma rbl_add_app2: "length blb \ length bla \ rbl_add bla (blb @ blc) = rbl_add bla blb" apply (induct bla arbitrary: blb) apply simp apply clarsimp apply (case_tac blb, clarsimp) apply (clarsimp simp: Let_def) done lemma rbl_add_take2: "length blb \ length bla \ rbl_add bla (take (length bla) blb) = rbl_add bla blb" apply (induct bla arbitrary: blb) apply simp apply clarsimp apply (case_tac blb, clarsimp) apply (clarsimp simp: Let_def) done lemma rbl_mult_app2: "length blb \ length bla \ rbl_mult bla (blb @ blc) = rbl_mult bla blb" apply (induct bla arbitrary: blb) apply simp apply clarsimp apply (case_tac blb, clarsimp) apply (clarsimp simp: Let_def rbl_add_app2) done lemma rbl_mult_take2: "length blb \ length bla \ rbl_mult bla (take (length bla) blb) = rbl_mult bla blb" apply (rule trans) apply (rule rbl_mult_app2 [symmetric]) apply simp apply (rule_tac f = "rbl_mult bla" in arg_cong) apply (rule append_take_drop_id) done lemma rbl_add_split: "P (rbl_add (y # ys) (x # xs)) = (\ws. length ws = length ys \ ws = rbl_add ys xs \ (y \ ((x \ P (False # rbl_succ ws)) \ (\ x \ P (True # ws)))) \ (\ y \ P (x # ws)))" by (cases y) (auto simp: Let_def) lemma rbl_mult_split: "P (rbl_mult (y # ys) xs) = (\ws. length ws = Suc (length ys) \ ws = False # rbl_mult ys xs \ (y \ P (rbl_add ws xs)) \ (\ y \ P ws))" by (auto simp: Let_def) lemma rbl_pred: "rbl_pred (rev (bin_to_bl n bin)) = rev (bin_to_bl n (bin - 1))" proof (unfold bin_to_bl_def, induction n arbitrary: bin) case 0 then show ?case by simp next case (Suc n) obtain b k where \bin = of_bool b + 2 * k\ using bin_exhaust by blast moreover have \(2 * k - 1) div 2 = k - 1\ using even_succ_div_2 [of \2 * (k - 1)\] by simp ultimately show ?case using Suc [of \bin div 2\] by simp (simp add: bin_to_bl_aux_alt) qed lemma rbl_succ: "rbl_succ (rev (bin_to_bl n bin)) = rev (bin_to_bl n (bin + 1))" apply (unfold bin_to_bl_def) apply (induction n arbitrary: bin) apply simp_all apply (case_tac bin rule: bin_exhaust) apply simp apply (simp add: bin_to_bl_aux_alt ac_simps) done lemma rbl_add: "\bina binb. rbl_add (rev (bin_to_bl n bina)) (rev (bin_to_bl n binb)) = rev (bin_to_bl n (bina + binb))" apply (unfold bin_to_bl_def) apply (induct n) apply simp apply clarsimp apply (case_tac bina rule: bin_exhaust) apply (case_tac binb rule: bin_exhaust) apply (case_tac b) apply (case_tac [!] "ba") apply (auto simp: rbl_succ bin_to_bl_aux_alt Let_def ac_simps) done lemma rbl_add_long: "m \ n \ rbl_add (rev (bin_to_bl n bina)) (rev (bin_to_bl m binb)) = rev (bin_to_bl n (bina + binb))" apply (rule box_equals [OF _ rbl_add_take2 rbl_add]) apply (rule_tac f = "rbl_add (rev (bin_to_bl n bina))" in arg_cong) apply (rule rev_swap [THEN iffD1]) apply (simp add: rev_take drop_bin2bl) apply simp done lemma rbl_mult_gt1: "m \ length bl \ rbl_mult bl (rev (bin_to_bl m binb)) = rbl_mult bl (rev (bin_to_bl (length bl) binb))" apply (rule trans) apply (rule rbl_mult_take2 [symmetric]) apply simp_all apply (rule_tac f = "rbl_mult bl" in arg_cong) apply (rule rev_swap [THEN iffD1]) apply (simp add: rev_take drop_bin2bl) done lemma rbl_mult_gt: "m > n \ rbl_mult (rev (bin_to_bl n bina)) (rev (bin_to_bl m binb)) = rbl_mult (rev (bin_to_bl n bina)) (rev (bin_to_bl n binb))" by (auto intro: trans [OF rbl_mult_gt1]) lemmas rbl_mult_Suc = lessI [THEN rbl_mult_gt] lemma rbbl_Cons: "b # rev (bin_to_bl n x) = rev (bin_to_bl (Suc n) (of_bool b + 2 * x))" by (simp add: bin_to_bl_def) (simp add: bin_to_bl_aux_alt) lemma rbl_mult: "rbl_mult (rev (bin_to_bl n bina)) (rev (bin_to_bl n binb)) = rev (bin_to_bl n (bina * binb))" apply (induct n arbitrary: bina binb) apply simp_all apply (unfold bin_to_bl_def) apply clarsimp apply (case_tac bina rule: bin_exhaust) apply (case_tac binb rule: bin_exhaust) apply simp apply (simp add: bin_to_bl_aux_alt) apply (simp add: rbbl_Cons rbl_mult_Suc rbl_add algebra_simps) done lemma sclem: "size (concat (map (bin_to_bl n) xs)) = length xs * n" by (induct xs) auto lemma bin_cat_foldl_lem: "foldl (\u. bin_cat u n) x xs = bin_cat x (size xs * n) (foldl (\u. bin_cat u n) y xs)" apply (induct xs arbitrary: x) apply simp apply (simp (no_asm)) apply (frule asm_rl) apply (drule meta_spec) apply (erule trans) apply (drule_tac x = "bin_cat y n a" in meta_spec) apply (simp add: bin_cat_assoc_sym min.absorb2) done lemma bin_rcat_bl: "bin_rcat n wl = bl_to_bin (concat (map (bin_to_bl n) wl))" apply (unfold bin_rcat_def) apply (rule sym) apply (induct wl) apply (auto simp add: bl_to_bin_append) apply (simp add: bl_to_bin_aux_alt sclem) apply (simp add: bin_cat_foldl_lem [symmetric]) done lemma bin_last_bl_to_bin: "bin_last (bl_to_bin bs) \ bs \ [] \ last bs" by(cases "bs = []")(auto simp add: bl_to_bin_def last_bin_last'[where w=0]) lemma bin_rest_bl_to_bin: "bin_rest (bl_to_bin bs) = bl_to_bin (butlast bs)" by(cases "bs = []")(simp_all add: bl_to_bin_def butlast_rest_bl2bin_aux) lemma bl_xor_aux_bin: "map2 (\x y. x \ y) (bin_to_bl_aux n v bs) (bin_to_bl_aux n w cs) = bin_to_bl_aux n (v XOR w) (map2 (\x y. x \ y) bs cs)" apply (induction n arbitrary: v w bs cs) apply auto apply (case_tac v rule: bin_exhaust) apply (case_tac w rule: bin_exhaust) apply clarsimp done lemma bl_or_aux_bin: "map2 (\) (bin_to_bl_aux n v bs) (bin_to_bl_aux n w cs) = bin_to_bl_aux n (v OR w) (map2 (\) bs cs)" by (induct n arbitrary: v w bs cs) simp_all lemma bl_and_aux_bin: "map2 (\) (bin_to_bl_aux n v bs) (bin_to_bl_aux n w cs) = bin_to_bl_aux n (v AND w) (map2 (\) bs cs)" by (induction n arbitrary: v w bs cs) simp_all lemma bl_not_aux_bin: "map Not (bin_to_bl_aux n w cs) = bin_to_bl_aux n (NOT w) (map Not cs)" by (induct n arbitrary: w cs) auto lemma bl_not_bin: "map Not (bin_to_bl n w) = bin_to_bl n (NOT w)" by (simp add: bin_to_bl_def bl_not_aux_bin) lemma bl_and_bin: "map2 (\) (bin_to_bl n v) (bin_to_bl n w) = bin_to_bl n (v AND w)" by (simp add: bin_to_bl_def bl_and_aux_bin) lemma bl_or_bin: "map2 (\) (bin_to_bl n v) (bin_to_bl n w) = bin_to_bl n (v OR w)" by (simp add: bin_to_bl_def bl_or_aux_bin) lemma bl_xor_bin: "map2 (\) (bin_to_bl n v) (bin_to_bl n w) = bin_to_bl n (v XOR w)" using bl_xor_aux_bin by (simp add: bin_to_bl_def) end diff --git a/src/HOL/Word/Misc_Arithmetic.thy b/src/HOL/Word/Misc_Arithmetic.thy --- a/src/HOL/Word/Misc_Arithmetic.thy +++ b/src/HOL/Word/Misc_Arithmetic.thy @@ -1,422 +1,462 @@ (* Title: HOL/Word/Misc_Arithmetic.thy *) section \Miscellaneous lemmas, mostly for arithmetic\ theory Misc_Arithmetic - imports Misc_Auxiliary + imports Main Bits_Int begin +lemma int_mod_lem: "0 < n \ 0 \ b \ b < n \ b mod n = b" + for b n :: int + apply safe + apply (erule (1) mod_pos_pos_trivial) + apply (erule_tac [!] subst) + apply auto + done + +lemma int_mod_ge': "b < 0 \ 0 < n \ b + n \ b mod n" + for b n :: int + by (metis add_less_same_cancel2 int_mod_ge mod_add_self2) + +lemma int_mod_le': "0 \ b - n \ b mod n \ b - n" + for b n :: int + by (metis minus_mod_self2 zmod_le_nonneg_dividend) + +lemma emep1: "even n \ even d \ 0 \ d \ (n + 1) mod d = (n mod d) + 1" + for n d :: int + by (auto simp add: pos_zmod_mult_2 add.commute dvd_def) + +lemma m1mod2k: "- 1 mod 2 ^ n = (2 ^ n - 1 :: int)" + by (rule zmod_minus1) simp + +lemma sb_inc_lem: "a + 2^k < 0 \ a + 2^k + 2^(Suc k) \ (a + 2^k) mod 2^(Suc k)" + for a :: int + using int_mod_ge' [where n = "2 ^ (Suc k)" and b = "a + 2 ^ k"] + by simp + +lemma sb_inc_lem': "a < - (2^k) \ a + 2^k + 2^(Suc k) \ (a + 2^k) mod 2^(Suc k)" + for a :: int + by (rule sb_inc_lem) simp + +lemma sb_dec_lem: "0 \ - (2 ^ k) + a \ (a + 2 ^ k) mod (2 * 2 ^ k) \ - (2 ^ k) + a" + for a :: int + using int_mod_le'[where n = "2 ^ (Suc k)" and b = "a + 2 ^ k"] by simp + +lemma sb_dec_lem': "2 ^ k \ a \ (a + 2 ^ k) mod (2 * 2 ^ k) \ - (2 ^ k) + a" + for a :: int + by (rule sb_dec_lem) simp + lemma one_mod_exp_eq_one [simp]: "1 mod (2 * 2 ^ n) = (1::int)" using power_gt1 [of 2 n] by (auto intro: mod_pos_pos_trivial) lemma mod_2_neq_1_eq_eq_0: "k mod 2 \ 1 \ k mod 2 = 0" for k :: int by (fact not_mod_2_eq_1_eq_0) lemma z1pmod2: "(2 * b + 1) mod 2 = (1::int)" for b :: int by arith lemma diff_le_eq': "a - b \ c \ a \ b + c" for a b c :: int by arith lemma zless2: "0 < (2 :: int)" by (fact zero_less_numeral) lemma zless2p: "0 < (2 ^ n :: int)" by arith lemma zle2p: "0 \ (2 ^ n :: int)" by arith lemma p1mod22k': "(1 + 2 * b) mod (2 * 2 ^ n) = 1 + 2 * (b mod 2 ^ n)" for b :: int using zle2p by (rule pos_zmod_mult_2) lemma p1mod22k: "(2 * b + 1) mod (2 * 2 ^ n) = 2 * (b mod 2 ^ n) + 1" for b :: int by (simp add: p1mod22k' add.commute) lemma ex_eq_or: "(\m. n = Suc m \ (m = k \ P m)) \ n = Suc k \ (\m. n = Suc m \ P m)" by auto lemma power_minus_simp: "0 < n \ a ^ n = a * a ^ (n - 1)" by (auto dest: gr0_implies_Suc) lemma funpow_minus_simp: "0 < n \ f ^^ n = f \ f ^^ (n - 1)" by (auto dest: gr0_implies_Suc) lemma power_numeral: "a ^ numeral k = a * a ^ (pred_numeral k)" by (simp add: numeral_eq_Suc) lemma funpow_numeral [simp]: "f ^^ numeral k = f \ f ^^ (pred_numeral k)" by (simp add: numeral_eq_Suc) lemma replicate_numeral [simp]: "replicate (numeral k) x = x # replicate (pred_numeral k) x" by (simp add: numeral_eq_Suc) lemma rco_alt: "(f \ g) ^^ n \ f = f \ (g \ f) ^^ n" apply (rule ext) apply (induct n) apply (simp_all add: o_def) done lemma list_exhaust_size_gt0: assumes "\a list. y = a # list \ P" shows "0 < length y \ P" apply (cases y) apply simp apply (rule assms) apply fastforce done lemma list_exhaust_size_eq0: assumes "y = [] \ P" shows "length y = 0 \ P" apply (cases y) apply (rule assms) apply simp apply simp done lemma size_Cons_lem_eq: "y = xa # list \ size y = Suc k \ size list = k" by auto lemmas ls_splits = prod.split prod.split_asm if_split_asm \ \simplifications for specific word lengths\ lemmas n2s_ths [THEN eq_reflection] = add_2_eq_Suc add_2_eq_Suc' lemmas s2n_ths = n2s_ths [symmetric] lemma and_len: "xs = ys \ xs = ys \ length xs = length ys" by auto lemma size_if: "size (if p then xs else ys) = (if p then size xs else size ys)" by auto lemma tl_if: "tl (if p then xs else ys) = (if p then tl xs else tl ys)" by auto lemma hd_if: "hd (if p then xs else ys) = (if p then hd xs else hd ys)" by auto lemma if_Not_x: "(if p then \ x else x) = (p = (\ x))" by auto lemma if_x_Not: "(if p then x else \ x) = (p = x)" by auto lemma if_same_and: "(If p x y \ If p u v) = (if p then x \ u else y \ v)" by auto lemma if_same_eq: "(If p x y = (If p u v)) = (if p then x = u else y = v)" by auto lemma if_same_eq_not: "(If p x y = (\ If p u v)) = (if p then x = (\ u) else y = (\ v))" by auto \ \note -- \if_Cons\ can cause blowup in the size, if \p\ is complex, so make a simproc\ lemma if_Cons: "(if p then x # xs else y # ys) = If p x y # If p xs ys" by auto lemma if_single: "(if xc then [xab] else [an]) = [if xc then xab else an]" by auto lemma if_bool_simps: "If p True y = (p \ y) \ If p False y = (\ p \ y) \ If p y True = (p \ y) \ If p y False = (p \ y)" by auto lemmas if_simps = if_x_Not if_Not_x if_cancel if_True if_False if_bool_simps lemmas seqr = eq_reflection [where x = "size w"] for w (* FIXME: delete *) lemma the_elemI: "y = {x} \ the_elem y = x" by simp lemma nonemptyE: "S \ {} \ (\x. x \ S \ R) \ R" by auto lemma gt_or_eq_0: "0 < y \ 0 = y" for y :: nat by arith lemmas xtr1 = xtrans(1) lemmas xtr2 = xtrans(2) lemmas xtr3 = xtrans(3) lemmas xtr4 = xtrans(4) lemmas xtr5 = xtrans(5) lemmas xtr6 = xtrans(6) lemmas xtr7 = xtrans(7) lemmas xtr8 = xtrans(8) lemmas nat_simps = diff_add_inverse2 diff_add_inverse lemmas nat_iffs = le_add1 le_add2 lemma sum_imp_diff: "j = k + i \ j - i = k" for k :: nat by arith lemmas pos_mod_sign2 = zless2 [THEN pos_mod_sign [where b = "2::int"]] lemmas pos_mod_bound2 = zless2 [THEN pos_mod_bound [where b = "2::int"]] lemma nmod2: "n mod 2 = 0 \ n mod 2 = 1" for n :: int by arith lemma eme1p: "even n \ even d \ 0 \ d \ (1 + n) mod d = 1 + n mod d" for n d :: int using emep1 [of n d] by (simp add: ac_simps) lemma le_diff_eq': "a \ c - b \ b + a \ c" for a b c :: int by arith lemma less_diff_eq': "a < c - b \ b + a < c" for a b c :: int by arith lemma diff_less_eq': "a - b < c \ a < b + c" for a b c :: int by arith lemmas m1mod22k = mult_pos_pos [OF zless2 zless2p, THEN zmod_minus1] lemma z1pdiv2: "(2 * b + 1) div 2 = b" for b :: int by arith lemmas zdiv_le_dividend = xtr3 [OF div_by_1 [symmetric] zdiv_mono2, simplified int_one_le_iff_zero_less, simplified] lemma axxbyy: "a + m + m = b + n + n \ a = 0 \ a = 1 \ b = 0 \ b = 1 \ a = b \ m = n" for a b m n :: int by arith lemma axxmod2: "(1 + x + x) mod 2 = 1 \ (0 + x + x) mod 2 = 0" for x :: int by arith lemma axxdiv2: "(1 + x + x) div 2 = x \ (0 + x + x) div 2 = x" for x :: int by arith lemmas iszero_minus = trans [THEN trans, OF iszero_def neg_equal_0_iff_equal iszero_def [symmetric]] lemmas zadd_diff_inverse = trans [OF diff_add_cancel [symmetric] add.commute] lemmas add_diff_cancel2 = add.commute [THEN diff_eq_eq [THEN iffD2]] lemmas rdmods [symmetric] = mod_minus_eq mod_diff_left_eq mod_diff_right_eq mod_add_left_eq mod_add_right_eq mod_mult_right_eq mod_mult_left_eq lemma mod_plus_right: "(a + x) mod m = (b + x) mod m \ a mod m = b mod m" for a b m x :: nat by (induct x) (simp_all add: mod_Suc, arith) lemma nat_minus_mod: "(n - n mod m) mod m = 0" for m n :: nat by (induct n) (simp_all add: mod_Suc) lemmas nat_minus_mod_plus_right = trans [OF nat_minus_mod mod_0 [symmetric], THEN mod_plus_right [THEN iffD2], simplified] lemmas push_mods' = mod_add_eq mod_mult_eq mod_diff_eq mod_minus_eq lemmas push_mods = push_mods' [THEN eq_reflection] lemmas pull_mods = push_mods [symmetric] rdmods [THEN eq_reflection] lemma nat_mod_eq: "b < n \ a mod n = b mod n \ a mod n = b" for a b n :: nat by (induct a) auto lemmas nat_mod_eq' = refl [THEN [2] nat_mod_eq] lemma nat_mod_lem: "0 < n \ b < n \ b mod n = b" for b n :: nat apply safe apply (erule nat_mod_eq') apply (erule subst) apply (erule mod_less_divisor) done lemma mod_nat_add: "x < z \ y < z \ (x + y) mod z = (if x + y < z then x + y else x + y - z)" for x y z :: nat apply (rule nat_mod_eq) apply auto apply (rule trans) apply (rule le_mod_geq) apply simp apply (rule nat_mod_eq') apply arith done lemma mod_nat_sub: "x < z \ (x - y) mod z = x - y" for x y :: nat by (rule nat_mod_eq') arith lemma int_mod_eq: "0 \ b \ b < n \ a mod n = b mod n \ a mod n = b" for a b n :: int by (metis mod_pos_pos_trivial) lemmas int_mod_eq' = mod_pos_pos_trivial (* FIXME delete *) lemmas int_mod_le = zmod_le_nonneg_dividend (* FIXME: delete *) lemma mod_add_if_z: "x < z \ y < z \ 0 \ y \ 0 \ x \ 0 \ z \ (x + y) mod z = (if x + y < z then x + y else x + y - z)" for x y z :: int by (auto intro: int_mod_eq) lemma mod_sub_if_z: "x < z \ y < z \ 0 \ y \ 0 \ x \ 0 \ z \ (x - y) mod z = (if y \ x then x - y else x - y + z)" for x y z :: int by (auto intro: int_mod_eq) lemmas zmde = mult_div_mod_eq [symmetric, THEN diff_eq_eq [THEN iffD2], symmetric] lemmas mcl = mult_cancel_left [THEN iffD1, THEN make_pos_rule] (* already have this for naturals, div_mult_self1/2, but not for ints *) lemma zdiv_mult_self: "m \ 0 \ (a + m * n) div m = a div m + n" for a m n :: int apply (rule mcl) prefer 2 apply (erule asm_rl) apply (simp add: zmde ring_distribs) done lemma mod_power_lem: "a > 1 \ a ^ n mod a ^ m = (if m \ n then 0 else a ^ n)" for a :: int by (simp add: mod_eq_0_iff_dvd le_imp_power_dvd) lemma pl_pl_rels: "a + b = c + d \ a \ c \ b \ d \ a \ c \ b \ d" for a b c d :: nat by arith lemmas pl_pl_rels' = add.commute [THEN [2] trans, THEN pl_pl_rels] lemma minus_eq: "m - k = m \ k = 0 \ m = 0" for k m :: nat by arith lemma pl_pl_mm: "a + b = c + d \ a - c = d - b" for a b c d :: nat by arith lemmas pl_pl_mm' = add.commute [THEN [2] trans, THEN pl_pl_mm] lemmas dme = div_mult_mod_eq lemmas dtle = div_times_less_eq_dividend lemmas th2 = order_trans [OF order_refl [THEN [2] mult_le_mono] div_times_less_eq_dividend] lemma td_gal: "0 < c \ a \ b * c \ a div c \ b" for a b c :: nat apply safe apply (erule (1) xtr4 [OF div_le_mono div_mult_self_is_m]) apply (erule th2) done lemmas td_gal_lt = td_gal [simplified not_less [symmetric], simplified] lemmas div_mult_le = div_times_less_eq_dividend lemmas sdl = div_nat_eqI lemma given_quot: "f > 0 \ (f * l + (f - 1)) div f = l" for f l :: nat by (rule div_nat_eqI) (simp_all) lemma given_quot_alt: "f > 0 \ (l * f + f - Suc 0) div f = l" for f l :: nat apply (frule given_quot) apply (rule trans) prefer 2 apply (erule asm_rl) apply (rule_tac f="\n. n div f" in arg_cong) apply (simp add : ac_simps) done lemma diff_mod_le: "a < d \ b dvd d \ a - a mod b \ d - b" for a b d :: nat apply (unfold dvd_def) apply clarify apply (case_tac k) apply clarsimp apply clarify apply (cases "b > 0") apply (drule mult.commute [THEN xtr1]) apply (frule (1) td_gal_lt [THEN iffD1]) apply (clarsimp simp: le_simps) apply (rule minus_mod_eq_mult_div [symmetric, THEN [2] xtr4]) apply (rule mult_mono) apply auto done lemma less_le_mult': "w * c < b * c \ 0 \ c \ (w + 1) * c \ b * c" for b c w :: int apply (rule mult_right_mono) apply (rule zless_imp_add1_zle) apply (erule (1) mult_right_less_imp_less) apply assumption done lemma less_le_mult: "w * c < b * c \ 0 \ c \ w * c + c \ b * c" for b c w :: int using less_le_mult' [of w c b] by (simp add: algebra_simps) lemmas less_le_mult_minus = iffD2 [OF le_diff_eq less_le_mult, simplified left_diff_distrib] lemma gen_minus: "0 < n \ f n = f (Suc (n - 1))" by auto lemma mpl_lem: "j \ i \ k < j \ i - j + k < i" for i j k :: nat by arith lemma nonneg_mod_div: "0 \ a \ 0 \ b \ 0 \ (a mod b) \ 0 \ a div b" for a b :: int by (cases "b = 0") (auto intro: pos_imp_zdiv_nonneg_iff [THEN iffD2]) declare iszero_0 [intro] lemma min_pm [simp]: "min a b + (a - b) = a" for a b :: nat by arith lemma min_pm1 [simp]: "a - b + min a b = a" for a b :: nat by arith lemma rev_min_pm [simp]: "min b a + (a - b) = a" for a b :: nat by arith lemma rev_min_pm1 [simp]: "a - b + min b a = a" for a b :: nat by arith lemma min_minus [simp]: "min m (m - k) = m - k" for m k :: nat by arith lemma min_minus' [simp]: "min (m - k) m = m - k" for m k :: nat by arith lemmas m2pths = pos_mod_sign pos_mod_bound [OF zless2p] end diff --git a/src/HOL/Word/Misc_Auxiliary.thy b/src/HOL/Word/Misc_Auxiliary.thy --- a/src/HOL/Word/Misc_Auxiliary.thy +++ b/src/HOL/Word/Misc_Auxiliary.thy @@ -1,179 +1,25 @@ (* Title: HOL/Word/Misc_Auxiliary.thy Author: Jeremy Dawson, NICTA *) section \Generic auxiliary\ theory Misc_Auxiliary imports Main begin -subsection \Arithmetic lemmas\ - -lemma int_mod_lem: "0 < n \ 0 \ b \ b < n \ b mod n = b" - for b n :: int - apply safe - apply (erule (1) mod_pos_pos_trivial) - apply (erule_tac [!] subst) - apply auto - done - -lemma int_mod_ge: "a < n \ 0 < n \ a \ a mod n" - for a n :: int - by (metis dual_order.trans le_cases mod_pos_pos_trivial pos_mod_conj) - -lemma int_mod_ge': "b < 0 \ 0 < n \ b + n \ b mod n" - for b n :: int - by (metis add_less_same_cancel2 int_mod_ge mod_add_self2) - -lemma int_mod_le': "0 \ b - n \ b mod n \ b - n" - for b n :: int - by (metis minus_mod_self2 zmod_le_nonneg_dividend) - -lemma emep1: "even n \ even d \ 0 \ d \ (n + 1) mod d = (n mod d) + 1" - for n d :: int - by (auto simp add: pos_zmod_mult_2 add.commute dvd_def) - -lemma m1mod2k: "- 1 mod 2 ^ n = (2 ^ n - 1 :: int)" - by (rule zmod_minus1) simp - -lemma sub_inc_One: "Num.sub (Num.inc n) num.One = numeral n" - by (metis add_diff_cancel add_neg_numeral_special(3) add_uminus_conv_diff numeral_inc) - -lemma inc_BitM: "Num.inc (Num.BitM n) = num.Bit0 n" - by (simp add: BitM_plus_one[symmetric] add_One) - - subsection \Lemmas on list operations\ lemma butlast_power: "(butlast ^^ n) bl = take (length bl - n) bl" by (induct n) (auto simp: butlast_take) lemma nth_rev: "n < length xs \ rev xs ! n = xs ! (length xs - 1 - n)" using rev_nth by simp lemma nth_rev_alt: "n < length ys \ ys ! n = rev ys ! (length ys - Suc n)" by (simp add: nth_rev) lemma hd_butlast: "length xs > 1 \ hd (butlast xs) = hd xs" by (cases xs) auto - -subsection \Implicit augmentation of list prefixes\ - -primrec takefill :: "'a \ nat \ 'a list \ 'a list" -where - Z: "takefill fill 0 xs = []" - | Suc: "takefill fill (Suc n) xs = - (case xs of - [] \ fill # takefill fill n xs - | y # ys \ y # takefill fill n ys)" - -lemma nth_takefill: "m < n \ takefill fill n l ! m = (if m < length l then l ! m else fill)" - apply (induct n arbitrary: m l) - apply clarsimp - apply clarsimp - apply (case_tac m) - apply (simp split: list.split) - apply (simp split: list.split) - done - -lemma takefill_alt: "takefill fill n l = take n l @ replicate (n - length l) fill" - by (induct n arbitrary: l) (auto split: list.split) - -lemma takefill_replicate [simp]: "takefill fill n (replicate m fill) = replicate n fill" - by (simp add: takefill_alt replicate_add [symmetric]) - -lemma takefill_le': "n = m + k \ takefill x m (takefill x n l) = takefill x m l" - by (induct m arbitrary: l n) (auto split: list.split) - -lemma length_takefill [simp]: "length (takefill fill n l) = n" - by (simp add: takefill_alt) - -lemma take_takefill': "n = k + m \ take k (takefill fill n w) = takefill fill k w" - by (induct k arbitrary: w n) (auto split: list.split) - -lemma drop_takefill: "drop k (takefill fill (m + k) w) = takefill fill m (drop k w)" - by (induct k arbitrary: w) (auto split: list.split) - -lemma takefill_le [simp]: "m \ n \ takefill x m (takefill x n l) = takefill x m l" - by (auto simp: le_iff_add takefill_le') - -lemma take_takefill [simp]: "m \ n \ take m (takefill fill n w) = takefill fill m w" - by (auto simp: le_iff_add take_takefill') - -lemma takefill_append: "takefill fill (m + length xs) (xs @ w) = xs @ (takefill fill m w)" - by (induct xs) auto - -lemma takefill_same': "l = length xs \ takefill fill l xs = xs" - by (induct xs arbitrary: l) auto - -lemmas takefill_same [simp] = takefill_same' [OF refl] - -lemma tf_rev: - "n + k = m + length bl \ takefill x m (rev (takefill y n bl)) = - rev (takefill y m (rev (takefill x k (rev bl))))" - apply (rule nth_equalityI) - apply (auto simp add: nth_takefill nth_rev) - apply (rule_tac f = "\n. bl ! n" in arg_cong) - apply arith - done - -lemma takefill_minus: "0 < n \ takefill fill (Suc (n - 1)) w = takefill fill n w" - by auto - -lemmas takefill_Suc_cases = - list.cases [THEN takefill.Suc [THEN trans]] - -lemmas takefill_Suc_Nil = takefill_Suc_cases (1) -lemmas takefill_Suc_Cons = takefill_Suc_cases (2) - -lemmas takefill_minus_simps = takefill_Suc_cases [THEN [2] - takefill_minus [symmetric, THEN trans]] - -lemma takefill_numeral_Nil [simp]: - "takefill fill (numeral k) [] = fill # takefill fill (pred_numeral k) []" - by (simp add: numeral_eq_Suc) - -lemma takefill_numeral_Cons [simp]: - "takefill fill (numeral k) (x # xs) = x # takefill fill (pred_numeral k) xs" - by (simp add: numeral_eq_Suc) - - -subsection \Auxiliary: Range projection\ - -definition bl_of_nth :: "nat \ (nat \ 'a) \ 'a list" - where "bl_of_nth n f = map f (rev [0.. rev (bl_of_nth n f) ! m = f m" - by (simp add: bl_of_nth_def rev_map) - -lemma bl_of_nth_inj: "(\k. k < n \ f k = g k) \ bl_of_nth n f = bl_of_nth n g" - by (simp add: bl_of_nth_def) - -lemma bl_of_nth_nth_le: "n \ length xs \ bl_of_nth n (nth (rev xs)) = drop (length xs - n) xs" - apply (induct n arbitrary: xs) - apply clarsimp - apply clarsimp - apply (rule trans [OF _ hd_Cons_tl]) - apply (frule Suc_le_lessD) - apply (simp add: nth_rev trans [OF drop_Suc drop_tl, symmetric]) - apply (subst hd_drop_conv_nth) - apply force - apply simp_all - apply (rule_tac f = "\n. drop n xs" in arg_cong) - apply simp - done - -lemma bl_of_nth_nth [simp]: "bl_of_nth (length xs) ((!) (rev xs)) = xs" - by (simp add: bl_of_nth_nth_le) - end diff --git a/src/HOL/Word/More_Word.thy b/src/HOL/Word/More_Word.thy --- a/src/HOL/Word/More_Word.thy +++ b/src/HOL/Word/More_Word.thy @@ -1,12 +1,14 @@ (* Title: HOL/Word/More_Word.thy *) section \Ancient comprehensive Word Library\ theory More_Word imports Word Ancient_Numeral + Misc_Auxiliary + Misc_Arithmetic begin end diff --git a/src/HOL/Word/Word.thy b/src/HOL/Word/Word.thy --- a/src/HOL/Word/Word.thy +++ b/src/HOL/Word/Word.thy @@ -1,5496 +1,5484 @@ (* Title: HOL/Word/Word.thy Author: Jeremy Dawson and Gerwin Klein, NICTA *) section \A type of finite bit strings\ theory Word imports "HOL-Library.Type_Length" "HOL-Library.Boolean_Algebra" "HOL-Library.Bit_Operations" Bits_Int Bit_Comprehension + Bit_Lists Misc_Typedef - Misc_Arithmetic begin subsection \Type definition\ quotient_type (overloaded) 'a word = int / \\k l. take_bit LENGTH('a) k = take_bit LENGTH('a::len) l\ morphisms rep_word word_of_int by (auto intro!: equivpI reflpI sympI transpI) lift_definition uint :: \'a::len word \ int\ is \take_bit LENGTH('a)\ . lemma uint_nonnegative: "0 \ uint w" by transfer simp lemma uint_bounded: "uint w < 2 ^ LENGTH('a)" for w :: "'a::len word" by transfer (simp add: take_bit_eq_mod) lemma uint_idem: "uint w mod 2 ^ LENGTH('a) = uint w" for w :: "'a::len word" using uint_nonnegative uint_bounded by (rule mod_pos_pos_trivial) lemma word_uint_eqI: "uint a = uint b \ a = b" by transfer simp lemma word_uint_eq_iff: "a = b \ uint a = uint b" using word_uint_eqI by auto lemma uint_word_of_int: "uint (word_of_int k :: 'a::len word) = k mod 2 ^ LENGTH('a)" by transfer (simp add: take_bit_eq_mod) lemma word_of_int_uint: "word_of_int (uint w) = w" by transfer simp lemma split_word_all: "(\x::'a::len word. PROP P x) \ (\x. PROP P (word_of_int x))" proof fix x :: "'a word" assume "\x. PROP P (word_of_int x)" then have "PROP P (word_of_int (uint x))" . then show "PROP P x" by (simp add: word_of_int_uint) qed subsection \Type conversions and casting\ definition sint :: "'a::len word \ int" \ \treats the most-significant-bit as a sign bit\ where sint_uint: "sint w = sbintrunc (LENGTH('a) - 1) (uint w)" definition unat :: "'a::len word \ nat" where "unat w = nat (uint w)" definition uints :: "nat \ int set" \ \the sets of integers representing the words\ where "uints n = range (bintrunc n)" definition sints :: "nat \ int set" where "sints n = range (sbintrunc (n - 1))" lemma uints_num: "uints n = {i. 0 \ i \ i < 2 ^ n}" by (simp add: uints_def range_bintrunc) lemma sints_num: "sints n = {i. - (2 ^ (n - 1)) \ i \ i < 2 ^ (n - 1)}" by (simp add: sints_def range_sbintrunc) definition unats :: "nat \ nat set" where "unats n = {i. i < 2 ^ n}" definition norm_sint :: "nat \ int \ int" where "norm_sint n w = (w + 2 ^ (n - 1)) mod 2 ^ n - 2 ^ (n - 1)" definition scast :: "'a::len word \ 'b::len word" \ \cast a word to a different length\ where "scast w = word_of_int (sint w)" definition ucast :: "'a::len word \ 'b::len word" where "ucast w = word_of_int (uint w)" instantiation word :: (len) size begin definition word_size: "size (w :: 'a word) = LENGTH('a)" instance .. end lemma word_size_gt_0 [iff]: "0 < size w" for w :: "'a::len word" by (simp add: word_size) lemmas lens_gt_0 = word_size_gt_0 len_gt_0 lemma lens_not_0 [iff]: \size w \ 0\ for w :: \'a::len word\ by auto definition source_size :: "('a::len word \ 'b) \ nat" \ \whether a cast (or other) function is to a longer or shorter length\ where [code del]: "source_size c = (let arb = undefined; x = c arb in size arb)" definition target_size :: "('a \ 'b::len word) \ nat" where [code del]: "target_size c = size (c undefined)" definition is_up :: "('a::len word \ 'b::len word) \ bool" where "is_up c \ source_size c \ target_size c" definition is_down :: "('a::len word \ 'b::len word) \ bool" where "is_down c \ target_size c \ source_size c" definition of_bl :: "bool list \ 'a::len word" where "of_bl bl = word_of_int (bl_to_bin bl)" definition to_bl :: "'a::len word \ bool list" where "to_bl w = bin_to_bl (LENGTH('a)) (uint w)" definition word_reverse :: "'a::len word \ 'a word" where "word_reverse w = of_bl (rev (to_bl w))" definition word_int_case :: "(int \ 'b) \ 'a::len word \ 'b" where "word_int_case f w = f (uint w)" translations "case x of XCONST of_int y \ b" \ "CONST word_int_case (\y. b) x" "case x of (XCONST of_int :: 'a) y \ b" \ "CONST word_int_case (\y. b) x" subsection \Basic code generation setup\ definition Word :: "int \ 'a::len word" where [code_post]: "Word = word_of_int" lemma [code abstype]: "Word (uint w) = w" by (simp add: Word_def word_of_int_uint) declare uint_word_of_int [code abstract] instantiation word :: (len) equal begin definition equal_word :: "'a word \ 'a word \ bool" where "equal_word k l \ HOL.equal (uint k) (uint l)" instance by standard (simp add: equal equal_word_def word_uint_eq_iff) end notation fcomp (infixl "\>" 60) notation scomp (infixl "\\" 60) instantiation word :: ("{len, typerep}") random begin definition "random_word i = Random.range i \\ (\k. Pair ( let j = word_of_int (int_of_integer (integer_of_natural k)) :: 'a word in (j, \_::unit. Code_Evaluation.term_of j)))" instance .. end no_notation fcomp (infixl "\>" 60) no_notation scomp (infixl "\\" 60) subsection \Type-definition locale instantiations\ lemmas uint_0 = uint_nonnegative (* FIXME duplicate *) lemmas uint_lt = uint_bounded (* FIXME duplicate *) lemmas uint_mod_same = uint_idem (* FIXME duplicate *) lemma td_ext_uint: "td_ext (uint :: 'a word \ int) word_of_int (uints (LENGTH('a::len))) (\w::int. w mod 2 ^ LENGTH('a))" apply (unfold td_ext_def') apply transfer apply (simp add: uints_num take_bit_eq_mod) done interpretation word_uint: td_ext "uint::'a::len word \ int" word_of_int "uints (LENGTH('a::len))" "\w. w mod 2 ^ LENGTH('a::len)" by (fact td_ext_uint) lemmas td_uint = word_uint.td_thm lemmas int_word_uint = word_uint.eq_norm lemma td_ext_ubin: "td_ext (uint :: 'a word \ int) word_of_int (uints (LENGTH('a::len))) (bintrunc (LENGTH('a)))" by (unfold no_bintr_alt1) (fact td_ext_uint) interpretation word_ubin: td_ext "uint::'a::len word \ int" word_of_int "uints (LENGTH('a::len))" "bintrunc (LENGTH('a::len))" by (fact td_ext_ubin) subsection \Arithmetic operations\ lift_definition word_succ :: "'a::len word \ 'a word" is "\x. x + 1" by (auto simp add: bintrunc_mod2p intro: mod_add_cong) lift_definition word_pred :: "'a::len word \ 'a word" is "\x. x - 1" by (auto simp add: bintrunc_mod2p intro: mod_diff_cong) instantiation word :: (len) "{neg_numeral, modulo, comm_monoid_mult, comm_ring}" begin lift_definition zero_word :: "'a word" is "0" . lift_definition one_word :: "'a word" is "1" . lift_definition plus_word :: "'a word \ 'a word \ 'a word" is "(+)" by (auto simp add: bintrunc_mod2p intro: mod_add_cong) lift_definition minus_word :: "'a word \ 'a word \ 'a word" is "(-)" by (auto simp add: bintrunc_mod2p intro: mod_diff_cong) lift_definition uminus_word :: "'a word \ 'a word" is uminus by (auto simp add: bintrunc_mod2p intro: mod_minus_cong) lift_definition times_word :: "'a word \ 'a word \ 'a word" is "(*)" by (auto simp add: bintrunc_mod2p intro: mod_mult_cong) lift_definition divide_word :: "'a word \ 'a word \ 'a word" is "\a b. take_bit LENGTH('a) a div take_bit LENGTH('a) b" by simp lift_definition modulo_word :: "'a word \ 'a word \ 'a word" is "\a b. take_bit LENGTH('a) a mod take_bit LENGTH('a) b" by simp instance by standard (transfer, simp add: algebra_simps)+ end lemma word_div_def [code]: "a div b = word_of_int (uint a div uint b)" by transfer rule lemma word_mod_def [code]: "a mod b = word_of_int (uint a mod uint b)" by transfer rule quickcheck_generator word constructors: "zero_class.zero :: ('a::len) word", "numeral :: num \ ('a::len) word", "uminus :: ('a::len) word \ ('a::len) word" context includes lifting_syntax notes power_transfer [transfer_rule] begin lemma power_transfer_word [transfer_rule]: \(pcr_word ===> (=) ===> pcr_word) (^) (^)\ by transfer_prover end text \Legacy theorems:\ lemma word_arith_wis [code]: shows word_add_def: "a + b = word_of_int (uint a + uint b)" and word_sub_wi: "a - b = word_of_int (uint a - uint b)" and word_mult_def: "a * b = word_of_int (uint a * uint b)" and word_minus_def: "- a = word_of_int (- uint a)" and word_succ_alt: "word_succ a = word_of_int (uint a + 1)" and word_pred_alt: "word_pred a = word_of_int (uint a - 1)" and word_0_wi: "0 = word_of_int 0" and word_1_wi: "1 = word_of_int 1" apply (simp_all flip: plus_word.abs_eq minus_word.abs_eq times_word.abs_eq uminus_word.abs_eq zero_word.abs_eq one_word.abs_eq) apply transfer apply simp apply transfer apply simp done lemma wi_homs: shows wi_hom_add: "word_of_int a + word_of_int b = word_of_int (a + b)" and wi_hom_sub: "word_of_int a - word_of_int b = word_of_int (a - b)" and wi_hom_mult: "word_of_int a * word_of_int b = word_of_int (a * b)" and wi_hom_neg: "- word_of_int a = word_of_int (- a)" and wi_hom_succ: "word_succ (word_of_int a) = word_of_int (a + 1)" and wi_hom_pred: "word_pred (word_of_int a) = word_of_int (a - 1)" by (transfer, simp)+ lemmas wi_hom_syms = wi_homs [symmetric] lemmas word_of_int_homs = wi_homs word_0_wi word_1_wi lemmas word_of_int_hom_syms = word_of_int_homs [symmetric] instance word :: (len) comm_monoid_add .. instance word :: (len) semiring_numeral .. instance word :: (len) comm_ring_1 proof have *: "0 < LENGTH('a)" by (rule len_gt_0) show "(0::'a word) \ 1" by transfer (use * in \auto simp add: gr0_conv_Suc\) qed lemma word_of_nat: "of_nat n = word_of_int (int n)" by (induct n) (auto simp add : word_of_int_hom_syms) lemma word_of_int: "of_int = word_of_int" apply (rule ext) apply (case_tac x rule: int_diff_cases) apply (simp add: word_of_nat wi_hom_sub) done context includes lifting_syntax notes transfer_rule_of_bool [transfer_rule] transfer_rule_numeral [transfer_rule] transfer_rule_of_nat [transfer_rule] transfer_rule_of_int [transfer_rule] begin lemma [transfer_rule]: "((=) ===> (pcr_word :: int \ 'a::len word \ bool)) of_bool of_bool" by transfer_prover lemma [transfer_rule]: "((=) ===> (pcr_word :: int \ 'a::len word \ bool)) numeral numeral" by transfer_prover lemma [transfer_rule]: "((=) ===> pcr_word) int of_nat" by transfer_prover lemma [transfer_rule]: "((=) ===> pcr_word) (\k. k) of_int" proof - have "((=) ===> pcr_word) of_int of_int" by transfer_prover then show ?thesis by (simp add: id_def) qed end lemma word_of_int_eq: "word_of_int = of_int" by (rule ext) (transfer, rule) definition udvd :: "'a::len word \ 'a::len word \ bool" (infixl "udvd" 50) where "a udvd b = (\n\0. uint b = n * uint a)" context includes lifting_syntax begin lemma [transfer_rule]: \(pcr_word ===> (\)) even ((dvd) 2 :: 'a::len word \ bool)\ proof - have even_word_unfold: "even k \ (\l. take_bit LENGTH('a) k = take_bit LENGTH('a) (2 * l))" (is "?P \ ?Q") for k :: int proof assume ?P then show ?Q by auto next assume ?Q then obtain l where "take_bit LENGTH('a) k = take_bit LENGTH('a) (2 * l)" .. then have "even (take_bit LENGTH('a) k)" by simp then show ?P by simp qed show ?thesis by (simp only: even_word_unfold [abs_def] dvd_def [where ?'a = "'a word", abs_def]) transfer_prover qed end instance word :: (len) semiring_modulo proof show "a div b * b + a mod b = a" for a b :: "'a word" proof transfer fix k l :: int define r :: int where "r = 2 ^ LENGTH('a)" then have r: "take_bit LENGTH('a) k = k mod r" for k by (simp add: take_bit_eq_mod) have "k mod r = ((k mod r) div (l mod r) * (l mod r) + (k mod r) mod (l mod r)) mod r" by (simp add: div_mult_mod_eq) also have "... = (((k mod r) div (l mod r) * (l mod r)) mod r + (k mod r) mod (l mod r)) mod r" by (simp add: mod_add_left_eq) also have "... = (((k mod r) div (l mod r) * l) mod r + (k mod r) mod (l mod r)) mod r" by (simp add: mod_mult_right_eq) finally have "k mod r = ((k mod r) div (l mod r) * l + (k mod r) mod (l mod r)) mod r" by (simp add: mod_simps) with r show "take_bit LENGTH('a) (take_bit LENGTH('a) k div take_bit LENGTH('a) l * l + take_bit LENGTH('a) k mod take_bit LENGTH('a) l) = take_bit LENGTH('a) k" by simp qed qed instance word :: (len) semiring_parity proof show "\ 2 dvd (1::'a word)" by transfer simp show even_iff_mod_2_eq_0: "2 dvd a \ a mod 2 = 0" for a :: "'a word" by transfer (simp_all add: mod_2_eq_odd take_bit_Suc) show "\ 2 dvd a \ a mod 2 = 1" for a :: "'a word" by transfer (simp_all add: mod_2_eq_odd take_bit_Suc) qed lemma exp_eq_zero_iff: \2 ^ n = (0 :: 'a::len word) \ n \ LENGTH('a)\ by transfer simp lemma double_eq_zero_iff: \2 * a = 0 \ a = 0 \ a = 2 ^ (LENGTH('a) - Suc 0)\ for a :: \'a::len word\ proof - define n where \n = LENGTH('a) - Suc 0\ then have *: \LENGTH('a) = Suc n\ by simp have \a = 0\ if \2 * a = 0\ and \a \ 2 ^ (LENGTH('a) - Suc 0)\ using that by transfer (auto simp add: take_bit_eq_0_iff take_bit_eq_mod *) moreover have \2 ^ LENGTH('a) = (0 :: 'a word)\ by transfer simp then have \2 * 2 ^ (LENGTH('a) - Suc 0) = (0 :: 'a word)\ by (simp add: *) ultimately show ?thesis by auto qed subsection \Ordering\ instantiation word :: (len) linorder begin lift_definition less_eq_word :: "'a word \ 'a word \ bool" is "\a b. take_bit LENGTH('a) a \ take_bit LENGTH('a) b" by simp lift_definition less_word :: "'a word \ 'a word \ bool" is "\a b. take_bit LENGTH('a) a < take_bit LENGTH('a) b" by simp instance by (standard; transfer) auto end interpretation word_order: ordering_top \(\)\ \(<)\ \- 1 :: 'a::len word\ by (standard; transfer) (simp add: take_bit_eq_mod zmod_minus1) interpretation word_coorder: ordering_top \(\)\ \(>)\ \0 :: 'a::len word\ by (standard; transfer) simp lemma word_le_def [code]: "a \ b \ uint a \ uint b" by transfer rule lemma word_less_def [code]: "a < b \ uint a < uint b" by transfer rule lemma word_greater_zero_iff: \a > 0 \ a \ 0\ for a :: \'a::len word\ by transfer (simp add: less_le) lemma of_nat_word_eq_iff: \of_nat m = (of_nat n :: 'a::len word) \ take_bit LENGTH('a) m = take_bit LENGTH('a) n\ by transfer (simp add: take_bit_of_nat) lemma of_nat_word_less_eq_iff: \of_nat m \ (of_nat n :: 'a::len word) \ take_bit LENGTH('a) m \ take_bit LENGTH('a) n\ by transfer (simp add: take_bit_of_nat) lemma of_nat_word_less_iff: \of_nat m < (of_nat n :: 'a::len word) \ take_bit LENGTH('a) m < take_bit LENGTH('a) n\ by transfer (simp add: take_bit_of_nat) lemma of_nat_word_eq_0_iff: \of_nat n = (0 :: 'a::len word) \ 2 ^ LENGTH('a) dvd n\ using of_nat_word_eq_iff [where ?'a = 'a, of n 0] by (simp add: take_bit_eq_0_iff) lemma of_int_word_eq_iff: \of_int k = (of_int l :: 'a::len word) \ take_bit LENGTH('a) k = take_bit LENGTH('a) l\ by transfer rule lemma of_int_word_less_eq_iff: \of_int k \ (of_int l :: 'a::len word) \ take_bit LENGTH('a) k \ take_bit LENGTH('a) l\ by transfer rule lemma of_int_word_less_iff: \of_int k < (of_int l :: 'a::len word) \ take_bit LENGTH('a) k < take_bit LENGTH('a) l\ by transfer rule lemma of_int_word_eq_0_iff: \of_int k = (0 :: 'a::len word) \ 2 ^ LENGTH('a) dvd k\ using of_int_word_eq_iff [where ?'a = 'a, of k 0] by (simp add: take_bit_eq_0_iff) definition word_sle :: "'a::len word \ 'a word \ bool" ("(_/ <=s _)" [50, 51] 50) where "a <=s b \ sint a \ sint b" definition word_sless :: "'a::len word \ 'a word \ bool" ("(_/ x <=s y \ x \ y" subsection \Bit-wise operations\ lemma word_bit_induct [case_names zero even odd]: \P a\ if word_zero: \P 0\ and word_even: \\a. P a \ 0 < a \ a < 2 ^ (LENGTH('a) - 1) \ P (2 * a)\ and word_odd: \\a. P a \ a < 2 ^ (LENGTH('a) - 1) \ P (1 + 2 * a)\ for P and a :: \'a::len word\ proof - define m :: nat where \m = LENGTH('a) - 1\ then have l: \LENGTH('a) = Suc m\ by simp define n :: nat where \n = unat a\ then have \n < 2 ^ LENGTH('a)\ by (unfold unat_def) (transfer, simp add: take_bit_eq_mod) then have \n < 2 * 2 ^ m\ by (simp add: l) then have \P (of_nat n)\ proof (induction n rule: nat_bit_induct) case zero show ?case by simp (rule word_zero) next case (even n) then have \n < 2 ^ m\ by simp with even.IH have \P (of_nat n)\ by simp moreover from \n < 2 ^ m\ even.hyps have \0 < (of_nat n :: 'a word)\ by (auto simp add: word_greater_zero_iff of_nat_word_eq_0_iff l) moreover from \n < 2 ^ m\ have \(of_nat n :: 'a word) < 2 ^ (LENGTH('a) - 1)\ using of_nat_word_less_iff [where ?'a = 'a, of n \2 ^ m\] by (cases \m = 0\) (simp_all add: not_less take_bit_eq_self ac_simps l) ultimately have \P (2 * of_nat n)\ by (rule word_even) then show ?case by simp next case (odd n) then have \Suc n \ 2 ^ m\ by simp with odd.IH have \P (of_nat n)\ by simp moreover from \Suc n \ 2 ^ m\ have \(of_nat n :: 'a word) < 2 ^ (LENGTH('a) - 1)\ using of_nat_word_less_iff [where ?'a = 'a, of n \2 ^ m\] by (cases \m = 0\) (simp_all add: not_less take_bit_eq_self ac_simps l) ultimately have \P (1 + 2 * of_nat n)\ by (rule word_odd) then show ?case by simp qed moreover have \of_nat (nat (uint a)) = a\ by transfer simp ultimately show ?thesis by (simp add: n_def unat_def) qed lemma bit_word_half_eq: \(of_bool b + a * 2) div 2 = a\ if \a < 2 ^ (LENGTH('a) - Suc 0)\ for a :: \'a::len word\ proof (cases \2 \ LENGTH('a::len)\) case False have \of_bool (odd k) < (1 :: int) \ even k\ for k :: int by auto with False that show ?thesis by transfer (simp add: eq_iff) next case True obtain n where length: \LENGTH('a) = Suc n\ by (cases \LENGTH('a)\) simp_all show ?thesis proof (cases b) case False moreover have \a * 2 div 2 = a\ using that proof transfer fix k :: int from length have \k * 2 mod 2 ^ LENGTH('a) = (k mod 2 ^ n) * 2\ by simp moreover assume \take_bit LENGTH('a) k < take_bit LENGTH('a) (2 ^ (LENGTH('a) - Suc 0))\ with \LENGTH('a) = Suc n\ have \k mod 2 ^ LENGTH('a) = k mod 2 ^ n\ by (simp add: take_bit_eq_mod divmod_digit_0) ultimately have \take_bit LENGTH('a) (k * 2) = take_bit LENGTH('a) k * 2\ by (simp add: take_bit_eq_mod) with True show \take_bit LENGTH('a) (take_bit LENGTH('a) (k * 2) div take_bit LENGTH('a) 2) = take_bit LENGTH('a) k\ by simp qed ultimately show ?thesis by simp next case True moreover have \(1 + a * 2) div 2 = a\ using that proof transfer fix k :: int from length have \(1 + k * 2) mod 2 ^ LENGTH('a) = 1 + (k mod 2 ^ n) * 2\ using pos_zmod_mult_2 [of \2 ^ n\ k] by (simp add: ac_simps) moreover assume \take_bit LENGTH('a) k < take_bit LENGTH('a) (2 ^ (LENGTH('a) - Suc 0))\ with \LENGTH('a) = Suc n\ have \k mod 2 ^ LENGTH('a) = k mod 2 ^ n\ by (simp add: take_bit_eq_mod divmod_digit_0) ultimately have \take_bit LENGTH('a) (1 + k * 2) = 1 + take_bit LENGTH('a) k * 2\ by (simp add: take_bit_eq_mod) with True show \take_bit LENGTH('a) (take_bit LENGTH('a) (1 + k * 2) div take_bit LENGTH('a) 2) = take_bit LENGTH('a) k\ by (auto simp add: take_bit_Suc) qed ultimately show ?thesis by simp qed qed lemma even_mult_exp_div_word_iff: \even (a * 2 ^ m div 2 ^ n) \ \ ( m \ n \ n < LENGTH('a) \ odd (a div 2 ^ (n - m)))\ for a :: \'a::len word\ by transfer (auto simp flip: drop_bit_eq_div simp add: even_drop_bit_iff_not_bit bit_take_bit_iff, simp_all flip: push_bit_eq_mult add: bit_push_bit_iff_int) instantiation word :: (len) semiring_bits begin lift_definition bit_word :: \'a word \ nat \ bool\ is \\k n. n < LENGTH('a) \ bit k n\ proof fix k l :: int and n :: nat assume *: \take_bit LENGTH('a) k = take_bit LENGTH('a) l\ show \n < LENGTH('a) \ bit k n \ n < LENGTH('a) \ bit l n\ proof (cases \n < LENGTH('a)\) case True from * have \bit (take_bit LENGTH('a) k) n \ bit (take_bit LENGTH('a) l) n\ by simp then show ?thesis by (simp add: bit_take_bit_iff) next case False then show ?thesis by simp qed qed instance proof show \P a\ if stable: \\a. a div 2 = a \ P a\ and rec: \\a b. P a \ (of_bool b + 2 * a) div 2 = a \ P (of_bool b + 2 * a)\ for P and a :: \'a word\ proof (induction a rule: word_bit_induct) case zero have \0 div 2 = (0::'a word)\ by transfer simp with stable [of 0] show ?case by simp next case (even a) with rec [of a False] show ?case using bit_word_half_eq [of a False] by (simp add: ac_simps) next case (odd a) with rec [of a True] show ?case using bit_word_half_eq [of a True] by (simp add: ac_simps) qed show \bit a n \ odd (a div 2 ^ n)\ for a :: \'a word\ and n by transfer (simp flip: drop_bit_eq_div add: drop_bit_take_bit bit_iff_odd_drop_bit) show \0 div a = 0\ for a :: \'a word\ by transfer simp show \a div 1 = a\ for a :: \'a word\ by transfer simp show \a mod b div b = 0\ for a b :: \'a word\ apply transfer apply (simp add: take_bit_eq_mod) apply (subst (3) mod_pos_pos_trivial [of _ \2 ^ LENGTH('a)\]) apply simp_all apply (metis le_less mod_by_0 pos_mod_conj zero_less_numeral zero_less_power) using pos_mod_bound [of \2 ^ LENGTH('a)\] apply simp proof - fix aa :: int and ba :: int have f1: "\i n. (i::int) mod 2 ^ n = 0 \ 0 < i mod 2 ^ n" by (metis le_less take_bit_eq_mod take_bit_nonnegative) have "(0::int) < 2 ^ len_of (TYPE('a)::'a itself) \ ba mod 2 ^ len_of (TYPE('a)::'a itself) \ 0 \ aa mod 2 ^ len_of (TYPE('a)::'a itself) mod (ba mod 2 ^ len_of (TYPE('a)::'a itself)) < 2 ^ len_of (TYPE('a)::'a itself)" by (metis (no_types) mod_by_0 unique_euclidean_semiring_numeral_class.pos_mod_bound zero_less_numeral zero_less_power) then show "aa mod 2 ^ len_of (TYPE('a)::'a itself) mod (ba mod 2 ^ len_of (TYPE('a)::'a itself)) < 2 ^ len_of (TYPE('a)::'a itself)" using f1 by (meson le_less less_le_trans unique_euclidean_semiring_numeral_class.pos_mod_bound) qed show \(1 + a) div 2 = a div 2\ if \even a\ for a :: \'a word\ using that by transfer (auto dest: le_Suc_ex simp add: mod_2_eq_odd take_bit_Suc elim!: evenE) show \(2 :: 'a word) ^ m div 2 ^ n = of_bool ((2 :: 'a word) ^ m \ 0 \ n \ m) * 2 ^ (m - n)\ for m n :: nat by transfer (simp, simp add: exp_div_exp_eq) show "a div 2 ^ m div 2 ^ n = a div 2 ^ (m + n)" for a :: "'a word" and m n :: nat apply transfer apply (auto simp add: not_less take_bit_drop_bit ac_simps simp flip: drop_bit_eq_div) apply (simp add: drop_bit_take_bit) done show "a mod 2 ^ m mod 2 ^ n = a mod 2 ^ min m n" for a :: "'a word" and m n :: nat by transfer (auto simp flip: take_bit_eq_mod simp add: ac_simps) show \a * 2 ^ m mod 2 ^ n = a mod 2 ^ (n - m) * 2 ^ m\ if \m \ n\ for a :: "'a word" and m n :: nat using that apply transfer apply (auto simp flip: take_bit_eq_mod) apply (auto simp flip: push_bit_eq_mult simp add: push_bit_take_bit split: split_min_lin) done show \a div 2 ^ n mod 2 ^ m = a mod (2 ^ (n + m)) div 2 ^ n\ for a :: "'a word" and m n :: nat by transfer (auto simp add: not_less take_bit_drop_bit ac_simps simp flip: take_bit_eq_mod drop_bit_eq_div split: split_min_lin) show \even ((2 ^ m - 1) div (2::'a word) ^ n) \ 2 ^ n = (0::'a word) \ m \ n\ for m n :: nat by transfer (auto simp add: take_bit_of_mask even_mask_div_iff) show \even (a * 2 ^ m div 2 ^ n) \ n < m \ (2::'a word) ^ n = 0 \ m \ n \ even (a div 2 ^ (n - m))\ for a :: \'a word\ and m n :: nat proof transfer show \even (take_bit LENGTH('a) (k * 2 ^ m) div take_bit LENGTH('a) (2 ^ n)) \ n < m \ take_bit LENGTH('a) ((2::int) ^ n) = take_bit LENGTH('a) 0 \ (m \ n \ even (take_bit LENGTH('a) k div take_bit LENGTH('a) (2 ^ (n - m))))\ for m n :: nat and k l :: int by (auto simp flip: take_bit_eq_mod drop_bit_eq_div push_bit_eq_mult simp add: div_push_bit_of_1_eq_drop_bit drop_bit_take_bit drop_bit_push_bit_int [of n m]) qed qed end instantiation word :: (len) semiring_bit_shifts begin lift_definition push_bit_word :: \nat \ 'a word \ 'a word\ is push_bit proof - show \take_bit LENGTH('a) (push_bit n k) = take_bit LENGTH('a) (push_bit n l)\ if \take_bit LENGTH('a) k = take_bit LENGTH('a) l\ for k l :: int and n :: nat proof - from that have \take_bit (LENGTH('a) - n) (take_bit LENGTH('a) k) = take_bit (LENGTH('a) - n) (take_bit LENGTH('a) l)\ by simp moreover have \min (LENGTH('a) - n) LENGTH('a) = LENGTH('a) - n\ by simp ultimately show ?thesis by (simp add: take_bit_push_bit) qed qed lift_definition drop_bit_word :: \nat \ 'a word \ 'a word\ is \\n. drop_bit n \ take_bit LENGTH('a)\ by (simp add: take_bit_eq_mod) lift_definition take_bit_word :: \nat \ 'a word \ 'a word\ is \\n. take_bit (min LENGTH('a) n)\ by (simp add: ac_simps) (simp only: flip: take_bit_take_bit) instance proof show \push_bit n a = a * 2 ^ n\ for n :: nat and a :: \'a word\ by transfer (simp add: push_bit_eq_mult) show \drop_bit n a = a div 2 ^ n\ for n :: nat and a :: \'a word\ by transfer (simp flip: drop_bit_eq_div add: drop_bit_take_bit) show \take_bit n a = a mod 2 ^ n\ for n :: nat and a :: \'a word\ by transfer (auto simp flip: take_bit_eq_mod) qed end lemma bit_word_eqI: \a = b\ if \\n. n \ LENGTH('a) \ bit a n \ bit b n\ for a b :: \'a::len word\ using that by transfer (auto simp add: nat_less_le bit_eq_iff bit_take_bit_iff) lemma bit_imp_le_length: \n < LENGTH('a)\ if \bit w n\ for w :: \'a::len word\ using that by transfer simp lemma not_bit_length [simp]: \\ bit w LENGTH('a)\ for w :: \'a::len word\ by transfer simp lemma bit_word_of_int_iff: \bit (word_of_int k :: 'a::len word) n \ n < LENGTH('a) \ bit k n\ by transfer rule lemma bit_uint_iff: \bit (uint w) n \ n < LENGTH('a) \ bit w n\ for w :: \'a::len word\ by transfer (simp add: bit_take_bit_iff) lemma bit_sint_iff: \bit (sint w) n \ n \ LENGTH('a) \ bit w (LENGTH('a) - 1) \ bit w n\ for w :: \'a::len word\ apply (cases \LENGTH('a)\) apply simp apply (simp add: sint_uint nth_sbintr not_less bit_uint_iff not_le Suc_le_eq) apply (auto simp add: le_less dest: bit_imp_le_length) done lemma bit_word_ucast_iff: \bit (ucast w :: 'b::len word) n \ n < LENGTH('a) \ n < LENGTH('b) \ bit w n\ for w :: \'a::len word\ by (simp add: ucast_def bit_word_of_int_iff bit_uint_iff ac_simps) lemma bit_word_scast_iff: \bit (scast w :: 'b::len word) n \ n < LENGTH('b) \ (bit w n \ LENGTH('a) \ n \ bit w (LENGTH('a) - Suc 0))\ for w :: \'a::len word\ by (simp add: scast_def bit_word_of_int_iff bit_sint_iff ac_simps) definition shiftl1 :: "'a::len word \ 'a word" where "shiftl1 w = word_of_int (2 * uint w)" lemma shiftl1_eq_mult_2: \shiftl1 = (*) 2\ apply (simp add: fun_eq_iff shiftl1_def) apply transfer apply (simp only: mult_2 take_bit_add) apply simp done lemma bit_shiftl1_iff: \bit (shiftl1 w) n \ 0 < n \ n < LENGTH('a) \ bit w (n - 1)\ for w :: \'a::len word\ by (simp add: shiftl1_eq_mult_2 bit_double_iff exp_eq_zero_iff not_le) (simp add: ac_simps) definition shiftr1 :: "'a::len word \ 'a word" \ \shift right as unsigned or as signed, ie logical or arithmetic\ where "shiftr1 w = word_of_int (bin_rest (uint w))" lemma shiftr1_eq_div_2: \shiftr1 w = w div 2\ apply (simp add: fun_eq_iff shiftr1_def) apply transfer apply (auto simp add: not_le dest: less_2_cases) done lemma bit_shiftr1_iff: \bit (shiftr1 w) n \ bit w (Suc n)\ for w :: \'a::len word\ by (simp add: shiftr1_eq_div_2 bit_Suc) instantiation word :: (len) ring_bit_operations begin lift_definition not_word :: \'a word \ 'a word\ is not by (simp add: take_bit_not_iff) lift_definition and_word :: \'a word \ 'a word \ 'a word\ is \and\ by simp lift_definition or_word :: \'a word \ 'a word \ 'a word\ is or by simp lift_definition xor_word :: \'a word \ 'a word \ 'a word\ is xor by simp instance proof fix a b :: \'a word\ and n :: nat show \- a = NOT (a - 1)\ by transfer (simp add: minus_eq_not_minus_1) show \bit (NOT a) n \ (2 :: 'a word) ^ n \ 0 \ \ bit a n\ by transfer (simp add: bit_not_iff) show \bit (a AND b) n \ bit a n \ bit b n\ by transfer (auto simp add: bit_and_iff) show \bit (a OR b) n \ bit a n \ bit b n\ by transfer (auto simp add: bit_or_iff) show \bit (a XOR b) n \ bit a n \ bit b n\ by transfer (auto simp add: bit_xor_iff) qed end instantiation word :: (len) bit_operations begin definition word_test_bit_def: "test_bit a = bin_nth (uint a)" definition word_set_bit_def: "set_bit a n x = word_of_int (bin_sc n x (uint a))" definition word_lsb_def: "lsb a \ bin_last (uint a)" definition "msb a \ bin_sign (sbintrunc (LENGTH('a) - 1) (uint a)) = - 1" definition shiftl_def: "w << n = (shiftl1 ^^ n) w" definition shiftr_def: "w >> n = (shiftr1 ^^ n) w" instance .. end lemma test_bit_word_eq: \test_bit w = bit w\ for w :: \'a::len word\ apply (simp add: word_test_bit_def fun_eq_iff) apply transfer apply (simp add: bit_take_bit_iff) done lemma set_bit_unfold: \set_bit w n b = (if b then Bit_Operations.set_bit n w else unset_bit n w)\ for w :: \'a::len word\ apply (auto simp add: word_set_bit_def bin_clr_conv_NAND bin_set_conv_OR unset_bit_def set_bit_def shiftl_int_def push_bit_of_1; transfer) apply simp_all done lemma bit_set_bit_word_iff: \bit (set_bit w m b) n \ (if m = n then n < LENGTH('a) \ b else bit w n)\ for w :: \'a::len word\ by (auto simp add: set_bit_unfold bit_unset_bit_iff bit_set_bit_iff exp_eq_zero_iff not_le bit_imp_le_length) lemma lsb_word_eq: \lsb = (odd :: 'a word \ bool)\ for w :: \'a::len word\ apply (simp add: word_lsb_def fun_eq_iff) apply transfer apply simp done lemma msb_word_eq: \msb w \ bit w (LENGTH('a) - 1)\ for w :: \'a::len word\ apply (simp add: msb_word_def bin_sign_lem) apply transfer apply (simp add: bit_take_bit_iff) done lemma shiftl_word_eq: \w << n = push_bit n w\ for w :: \'a::len word\ by (induction n) (simp_all add: shiftl_def shiftl1_eq_mult_2 push_bit_double) lemma bit_shiftl_word_iff: \bit (w << m) n \ m \ n \ n < LENGTH('a) \ bit w (n - m)\ for w :: \'a::len word\ by (simp add: shiftl_word_eq bit_push_bit_iff exp_eq_zero_iff not_le) lemma [code]: \push_bit n w = w << n\ for w :: \'a::len word\ by (simp add: shiftl_word_eq) lemma shiftr_word_eq: \w >> n = drop_bit n w\ for w :: \'a::len word\ by (induction n) (simp_all add: shiftr_def shiftr1_eq_div_2 drop_bit_Suc drop_bit_half) lemma bit_shiftr_word_iff: \bit (w >> m) n \ bit w (m + n)\ for w :: \'a::len word\ by (simp add: shiftr_word_eq bit_drop_bit_eq) lemma [code]: \drop_bit n w = w >> n\ for w :: \'a::len word\ by (simp add: shiftr_word_eq) lemma [code]: \take_bit n a = a AND Bit_Operations.mask n\ for a :: \'a::len word\ by (fact take_bit_eq_mask) lemma [code_abbrev]: \push_bit n 1 = (2 :: 'a::len word) ^ n\ by (fact push_bit_of_1) lemma word_msb_def: "msb a \ bin_sign (sint a) = - 1" by (simp add: msb_word_def sint_uint) lemma [code]: shows word_not_def: "NOT (a::'a::len word) = word_of_int (NOT (uint a))" and word_and_def: "(a::'a word) AND b = word_of_int (uint a AND uint b)" and word_or_def: "(a::'a word) OR b = word_of_int (uint a OR uint b)" and word_xor_def: "(a::'a word) XOR b = word_of_int (uint a XOR uint b)" by (transfer, simp add: take_bit_not_take_bit)+ definition setBit :: "'a::len word \ nat \ 'a word" where "setBit w n = set_bit w n True" lemma setBit_eq_set_bit: \setBit w n = Bit_Operations.set_bit n w\ for w :: \'a::len word\ by (simp add: setBit_def set_bit_unfold) lemma bit_setBit_iff: \bit (setBit w m) n \ (m = n \ n < LENGTH('a) \ bit w n)\ for w :: \'a::len word\ by (simp add: setBit_eq_set_bit bit_set_bit_iff exp_eq_zero_iff not_le ac_simps) definition clearBit :: "'a::len word \ nat \ 'a word" where "clearBit w n = set_bit w n False" lemma clearBit_eq_unset_bit: \clearBit w n = unset_bit n w\ for w :: \'a::len word\ by (simp add: clearBit_def set_bit_unfold) lemma bit_clearBit_iff: \bit (clearBit w m) n \ m \ n \ bit w n\ for w :: \'a::len word\ by (simp add: clearBit_eq_unset_bit bit_unset_bit_iff ac_simps) definition even_word :: \'a::len word \ bool\ where [code_abbrev]: \even_word = even\ lemma even_word_iff [code]: \even_word a \ a AND 1 = 0\ by (simp add: and_one_eq even_iff_mod_2_eq_zero even_word_def) lemma bit_word_iff_drop_bit_and [code]: \bit a n \ drop_bit n a AND 1 = 1\ for a :: \'a::len word\ by (simp add: bit_iff_odd_drop_bit odd_iff_mod_2_eq_one and_one_eq) subsection \Shift operations\ definition sshiftr1 :: "'a::len word \ 'a word" where "sshiftr1 w = word_of_int (bin_rest (sint w))" definition bshiftr1 :: "bool \ 'a::len word \ 'a word" where "bshiftr1 b w = of_bl (b # butlast (to_bl w))" definition sshiftr :: "'a::len word \ nat \ 'a word" (infixl ">>>" 55) where "w >>> n = (sshiftr1 ^^ n) w" definition mask :: "nat \ 'a::len word" where "mask n = (1 << n) - 1" definition slice1 :: "nat \ 'a::len word \ 'b::len word" where "slice1 n w = of_bl (takefill False n (to_bl w))" definition revcast :: "'a::len word \ 'b::len word" where "revcast w = of_bl (takefill False (LENGTH('b)) (to_bl w))" lemma revcast_eq: \(revcast :: 'a::len word \ 'b::len word) = slice1 LENGTH('b)\ by (simp add: fun_eq_iff revcast_def slice1_def) definition slice :: "nat \ 'a::len word \ 'b::len word" where "slice n w = slice1 (size w - n) w" subsection \Rotation\ definition rotater1 :: "'a list \ 'a list" where "rotater1 ys = (case ys of [] \ [] | x # xs \ last ys # butlast ys)" definition rotater :: "nat \ 'a list \ 'a list" where "rotater n = rotater1 ^^ n" definition word_rotr :: "nat \ 'a::len word \ 'a::len word" where "word_rotr n w = of_bl (rotater n (to_bl w))" definition word_rotl :: "nat \ 'a::len word \ 'a::len word" where "word_rotl n w = of_bl (rotate n (to_bl w))" definition word_roti :: "int \ 'a::len word \ 'a::len word" where "word_roti i w = (if i \ 0 then word_rotr (nat i) w else word_rotl (nat (- i)) w)" subsection \Split and cat operations\ definition word_cat :: "'a::len word \ 'b::len word \ 'c::len word" where "word_cat a b = word_of_int (bin_cat (uint a) (LENGTH('b)) (uint b))" lemma word_cat_eq: \(word_cat v w :: 'c::len word) = push_bit LENGTH('b) (ucast v) + ucast w\ for v :: \'a::len word\ and w :: \'b::len word\ apply (simp add: word_cat_def bin_cat_eq_push_bit_add_take_bit ucast_def) apply transfer apply simp done lemma bit_word_cat_iff: \bit (word_cat v w :: 'c::len word) n \ n < LENGTH('c) \ (if n < LENGTH('b) then bit w n else bit v (n - LENGTH('b)))\ for v :: \'a::len word\ and w :: \'b::len word\ by (auto simp add: word_cat_def bit_word_of_int_iff bin_nth_cat bit_uint_iff not_less bit_imp_le_length) definition word_split :: "'a::len word \ 'b::len word \ 'c::len word" where "word_split a = (case bin_split (LENGTH('c)) (uint a) of (u, v) \ (word_of_int u, word_of_int v))" definition word_rcat :: "'a::len word list \ 'b::len word" where "word_rcat ws = word_of_int (bin_rcat (LENGTH('a)) (map uint ws))" definition word_rsplit :: "'a::len word \ 'b::len word list" where "word_rsplit w = map word_of_int (bin_rsplit (LENGTH('b)) (LENGTH('a), uint w))" abbreviation (input) max_word :: \'a::len word\ \ \Largest representable machine integer.\ where "max_word \ - 1" subsection \Theorems about typedefs\ lemma sint_sbintrunc': "sint (word_of_int bin :: 'a word) = sbintrunc (LENGTH('a::len) - 1) bin" by (auto simp: sint_uint word_ubin.eq_norm sbintrunc_bintrunc_lt) lemma uint_sint: "uint w = bintrunc (LENGTH('a)) (sint w)" for w :: "'a::len word" by (auto simp: sint_uint bintrunc_sbintrunc_le) lemma bintr_uint: "LENGTH('a) \ n \ bintrunc n (uint w) = uint w" for w :: "'a::len word" apply (subst word_ubin.norm_Rep [symmetric]) apply (simp only: bintrunc_bintrunc_min word_size) apply (simp add: min.absorb2) done lemma wi_bintr: "LENGTH('a::len) \ n \ word_of_int (bintrunc n w) = (word_of_int w :: 'a word)" by (auto simp: word_ubin.norm_eq_iff [symmetric] min.absorb1) lemma td_ext_sbin: "td_ext (sint :: 'a word \ int) word_of_int (sints (LENGTH('a::len))) (sbintrunc (LENGTH('a) - 1))" apply (unfold td_ext_def' sint_uint) apply (simp add : word_ubin.eq_norm) apply (cases "LENGTH('a)") apply (auto simp add : sints_def) apply (rule sym [THEN trans]) apply (rule word_ubin.Abs_norm) apply (simp only: bintrunc_sbintrunc) apply (drule sym) apply simp done lemma td_ext_sint: "td_ext (sint :: 'a word \ int) word_of_int (sints (LENGTH('a::len))) (\w. (w + 2 ^ (LENGTH('a) - 1)) mod 2 ^ LENGTH('a) - 2 ^ (LENGTH('a) - 1))" using td_ext_sbin [where ?'a = 'a] by (simp add: no_sbintr_alt2) text \ We do \sint\ before \sbin\, before \sint\ is the user version and interpretations do not produce thm duplicates. I.e. we get the name \word_sint.Rep_eqD\, but not \word_sbin.Req_eqD\, because the latter is the same thm as the former. \ interpretation word_sint: td_ext "sint ::'a::len word \ int" word_of_int "sints (LENGTH('a::len))" "\w. (w + 2^(LENGTH('a::len) - 1)) mod 2^LENGTH('a::len) - 2 ^ (LENGTH('a::len) - 1)" by (rule td_ext_sint) interpretation word_sbin: td_ext "sint ::'a::len word \ int" word_of_int "sints (LENGTH('a::len))" "sbintrunc (LENGTH('a::len) - 1)" by (rule td_ext_sbin) lemmas int_word_sint = td_ext_sint [THEN td_ext.eq_norm] lemmas td_sint = word_sint.td lemma to_bl_def': "(to_bl :: 'a::len word \ bool list) = bin_to_bl (LENGTH('a)) \ uint" by (auto simp: to_bl_def) lemmas word_reverse_no_def [simp] = word_reverse_def [of "numeral w"] for w lemma uints_mod: "uints n = range (\w. w mod 2 ^ n)" by (fact uints_def [unfolded no_bintr_alt1]) lemma word_numeral_alt: "numeral b = word_of_int (numeral b)" by (induct b, simp_all only: numeral.simps word_of_int_homs) declare word_numeral_alt [symmetric, code_abbrev] lemma word_neg_numeral_alt: "- numeral b = word_of_int (- numeral b)" by (simp only: word_numeral_alt wi_hom_neg) declare word_neg_numeral_alt [symmetric, code_abbrev] lemma uint_bintrunc [simp]: "uint (numeral bin :: 'a word) = bintrunc (LENGTH('a::len)) (numeral bin)" unfolding word_numeral_alt by (rule word_ubin.eq_norm) lemma uint_bintrunc_neg [simp]: "uint (- numeral bin :: 'a word) = bintrunc (LENGTH('a::len)) (- numeral bin)" by (simp only: word_neg_numeral_alt word_ubin.eq_norm) lemma sint_sbintrunc [simp]: "sint (numeral bin :: 'a word) = sbintrunc (LENGTH('a::len) - 1) (numeral bin)" by (simp only: word_numeral_alt word_sbin.eq_norm) lemma sint_sbintrunc_neg [simp]: "sint (- numeral bin :: 'a word) = sbintrunc (LENGTH('a::len) - 1) (- numeral bin)" by (simp only: word_neg_numeral_alt word_sbin.eq_norm) lemma unat_bintrunc [simp]: "unat (numeral bin :: 'a::len word) = nat (bintrunc (LENGTH('a)) (numeral bin))" by (simp only: unat_def uint_bintrunc) lemma unat_bintrunc_neg [simp]: "unat (- numeral bin :: 'a::len word) = nat (bintrunc (LENGTH('a)) (- numeral bin))" by (simp only: unat_def uint_bintrunc_neg) lemma size_0_eq: "size w = 0 \ v = w" for v w :: "'a::len word" apply (unfold word_size) apply (rule word_uint.Rep_eqD) apply (rule box_equals) defer apply (rule word_ubin.norm_Rep)+ apply simp done lemma uint_ge_0 [iff]: "0 \ uint x" for x :: "'a::len word" using word_uint.Rep [of x] by (simp add: uints_num) lemma uint_lt2p [iff]: "uint x < 2 ^ LENGTH('a)" for x :: "'a::len word" using word_uint.Rep [of x] by (simp add: uints_num) lemma word_exp_length_eq_0 [simp]: \(2 :: 'a::len word) ^ LENGTH('a) = 0\ by transfer (simp add: bintrunc_mod2p) lemma sint_ge: "- (2 ^ (LENGTH('a) - 1)) \ sint x" for x :: "'a::len word" using word_sint.Rep [of x] by (simp add: sints_num) lemma sint_lt: "sint x < 2 ^ (LENGTH('a) - 1)" for x :: "'a::len word" using word_sint.Rep [of x] by (simp add: sints_num) lemma sign_uint_Pls [simp]: "bin_sign (uint x) = 0" by (simp add: sign_Pls_ge_0) lemma uint_m2p_neg: "uint x - 2 ^ LENGTH('a) < 0" for x :: "'a::len word" by (simp only: diff_less_0_iff_less uint_lt2p) lemma uint_m2p_not_non_neg: "\ 0 \ uint x - 2 ^ LENGTH('a)" for x :: "'a::len word" by (simp only: not_le uint_m2p_neg) lemma lt2p_lem: "LENGTH('a) \ n \ uint w < 2 ^ n" for w :: "'a::len word" - by (metis bintr_uint bintrunc_mod2p int_mod_lem zless2p) + by (metis bintr_lt2p bintr_uint) lemma uint_le_0_iff [simp]: "uint x \ 0 \ uint x = 0" by (fact uint_ge_0 [THEN leD, THEN antisym_conv1]) lemma uint_nat: "uint w = int (unat w)" by (auto simp: unat_def) lemma uint_numeral: "uint (numeral b :: 'a::len word) = numeral b mod 2 ^ LENGTH('a)" by (simp only: word_numeral_alt int_word_uint) lemma uint_neg_numeral: "uint (- numeral b :: 'a::len word) = - numeral b mod 2 ^ LENGTH('a)" by (simp only: word_neg_numeral_alt int_word_uint) lemma unat_numeral: "unat (numeral b :: 'a::len word) = numeral b mod 2 ^ LENGTH('a)" apply (unfold unat_def) apply (clarsimp simp only: uint_numeral) apply (rule nat_mod_distrib [THEN trans]) apply (rule zero_le_numeral) apply (simp_all add: nat_power_eq) done lemma sint_numeral: "sint (numeral b :: 'a::len word) = (numeral b + 2 ^ (LENGTH('a) - 1)) mod 2 ^ LENGTH('a) - 2 ^ (LENGTH('a) - 1)" unfolding word_numeral_alt by (rule int_word_sint) lemma word_of_int_0 [simp, code_post]: "word_of_int 0 = 0" unfolding word_0_wi .. lemma word_of_int_1 [simp, code_post]: "word_of_int 1 = 1" unfolding word_1_wi .. lemma word_of_int_neg_1 [simp]: "word_of_int (- 1) = - 1" by (simp add: wi_hom_syms) lemma word_of_int_numeral [simp] : "(word_of_int (numeral bin) :: 'a::len word) = numeral bin" by (simp only: word_numeral_alt) lemma word_of_int_neg_numeral [simp]: "(word_of_int (- numeral bin) :: 'a::len word) = - numeral bin" by (simp only: word_numeral_alt wi_hom_syms) lemma word_int_case_wi: "word_int_case f (word_of_int i :: 'b word) = f (i mod 2 ^ LENGTH('b::len))" by (simp add: word_int_case_def word_uint.eq_norm) lemma word_int_split: "P (word_int_case f x) = (\i. x = (word_of_int i :: 'b::len word) \ 0 \ i \ i < 2 ^ LENGTH('b) \ P (f i))" by (auto simp: word_int_case_def word_uint.eq_norm) lemma word_int_split_asm: "P (word_int_case f x) = (\n. x = (word_of_int n :: 'b::len word) \ 0 \ n \ n < 2 ^ LENGTH('b::len) \ \ P (f n))" by (auto simp: word_int_case_def word_uint.eq_norm) lemmas uint_range' = word_uint.Rep [unfolded uints_num mem_Collect_eq] lemmas sint_range' = word_sint.Rep [unfolded One_nat_def sints_num mem_Collect_eq] lemma uint_range_size: "0 \ uint w \ uint w < 2 ^ size w" unfolding word_size by (rule uint_range') lemma sint_range_size: "- (2 ^ (size w - Suc 0)) \ sint w \ sint w < 2 ^ (size w - Suc 0)" unfolding word_size by (rule sint_range') lemma sint_above_size: "2 ^ (size w - 1) \ x \ sint w < x" for w :: "'a::len word" unfolding word_size by (rule less_le_trans [OF sint_lt]) lemma sint_below_size: "x \ - (2 ^ (size w - 1)) \ x \ sint w" for w :: "'a::len word" unfolding word_size by (rule order_trans [OF _ sint_ge]) subsection \Testing bits\ lemma test_bit_eq_iff: "test_bit u = test_bit v \ u = v" for u v :: "'a::len word" unfolding word_test_bit_def by (simp add: bin_nth_eq_iff) lemma test_bit_size [rule_format] : "w !! n \ n < size w" for w :: "'a::len word" apply (unfold word_test_bit_def) apply (subst word_ubin.norm_Rep [symmetric]) apply (simp only: nth_bintr word_size) apply fast done lemma word_eq_iff: "x = y \ (\n?P \ ?Q\) for x y :: "'a::len word" proof assume ?P then show ?Q by simp next assume ?Q then have *: \bit (uint x) n \ bit (uint y) n\ if \n < LENGTH('a)\ for n using that by (simp add: word_test_bit_def) show ?P proof (rule word_uint_eqI, rule bit_eqI, rule iffI) fix n assume \bit (uint x) n\ then have \n < LENGTH('a)\ by (simp add: bit_take_bit_iff uint.rep_eq) with * \bit (uint x) n\ show \bit (uint y) n\ by simp next fix n assume \bit (uint y) n\ then have \n < LENGTH('a)\ by (simp add: bit_take_bit_iff uint.rep_eq) with * \bit (uint y) n\ show \bit (uint x) n\ by simp qed qed lemma word_eqI: "(\n. n < size u \ u !! n = v !! n) \ u = v" for u :: "'a::len word" by (simp add: word_size word_eq_iff) lemma word_eqD: "u = v \ u !! x = v !! x" for u v :: "'a::len word" by simp lemma test_bit_bin': "w !! n \ n < size w \ bin_nth (uint w) n" by (simp add: word_test_bit_def word_size nth_bintr [symmetric]) lemmas test_bit_bin = test_bit_bin' [unfolded word_size] lemma bin_nth_uint_imp: "bin_nth (uint w) n \ n < LENGTH('a)" for w :: "'a::len word" apply (rule nth_bintr [THEN iffD1, THEN conjunct1]) apply (subst word_ubin.norm_Rep) apply assumption done lemma bin_nth_sint: "LENGTH('a) \ n \ bin_nth (sint w) n = bin_nth (sint w) (LENGTH('a) - 1)" for w :: "'a::len word" apply (subst word_sbin.norm_Rep [symmetric]) apply (auto simp add: nth_sbintr) done \ \type definitions theorem for in terms of equivalent bool list\ lemma td_bl: "type_definition (to_bl :: 'a::len word \ bool list) of_bl {bl. length bl = LENGTH('a)}" apply (unfold type_definition_def of_bl_def to_bl_def) apply (simp add: word_ubin.eq_norm) apply safe apply (drule sym) apply simp done interpretation word_bl: type_definition "to_bl :: 'a::len word \ bool list" of_bl "{bl. length bl = LENGTH('a::len)}" by (fact td_bl) lemmas word_bl_Rep' = word_bl.Rep [unfolded mem_Collect_eq, iff] lemma word_size_bl: "size w = size (to_bl w)" by (auto simp: word_size) lemma to_bl_use_of_bl: "to_bl w = bl \ w = of_bl bl \ length bl = length (to_bl w)" by (fastforce elim!: word_bl.Abs_inverse [unfolded mem_Collect_eq]) lemma to_bl_word_rev: "to_bl (word_reverse w) = rev (to_bl w)" by (simp add: word_reverse_def word_bl.Abs_inverse) lemma word_rev_rev [simp] : "word_reverse (word_reverse w) = w" by (simp add: word_reverse_def word_bl.Abs_inverse) lemma word_rev_gal: "word_reverse w = u \ word_reverse u = w" by (metis word_rev_rev) lemma word_rev_gal': "u = word_reverse w \ w = word_reverse u" by simp lemma length_bl_gt_0 [iff]: "0 < length (to_bl x)" for x :: "'a::len word" unfolding word_bl_Rep' by (rule len_gt_0) lemma bl_not_Nil [iff]: "to_bl x \ []" for x :: "'a::len word" by (fact length_bl_gt_0 [unfolded length_greater_0_conv]) lemma length_bl_neq_0 [iff]: "length (to_bl x) \ 0" for x :: "'a::len word" by (fact length_bl_gt_0 [THEN gr_implies_not0]) lemma hd_bl_sign_sint: "hd (to_bl w) = (bin_sign (sint w) = -1)" apply (unfold to_bl_def sint_uint) apply (rule trans [OF _ bl_sbin_sign]) apply simp done lemma of_bl_drop': "lend = length bl - LENGTH('a::len) \ of_bl (drop lend bl) = (of_bl bl :: 'a word)" by (auto simp: of_bl_def trunc_bl2bin [symmetric]) lemma test_bit_of_bl: "(of_bl bl::'a::len word) !! n = (rev bl ! n \ n < LENGTH('a) \ n < length bl)" by (auto simp add: of_bl_def word_test_bit_def word_size word_ubin.eq_norm nth_bintr bin_nth_of_bl) lemma bit_of_bl_iff: \bit (of_bl bs :: 'a word) n \ rev bs ! n \ n < LENGTH('a::len) \ n < length bs\ using test_bit_of_bl [of bs n] by (simp add: test_bit_word_eq) lemma no_of_bl: "(numeral bin ::'a::len word) = of_bl (bin_to_bl (LENGTH('a)) (numeral bin))" by (simp add: of_bl_def) lemma uint_bl: "to_bl w = bin_to_bl (size w) (uint w)" by (auto simp: word_size to_bl_def) lemma to_bl_bin: "bl_to_bin (to_bl w) = uint w" by (simp add: uint_bl word_size) lemma to_bl_of_bin: "to_bl (word_of_int bin::'a::len word) = bin_to_bl (LENGTH('a)) bin" by (auto simp: uint_bl word_ubin.eq_norm word_size) lemma to_bl_numeral [simp]: "to_bl (numeral bin::'a::len word) = bin_to_bl (LENGTH('a)) (numeral bin)" unfolding word_numeral_alt by (rule to_bl_of_bin) lemma to_bl_neg_numeral [simp]: "to_bl (- numeral bin::'a::len word) = bin_to_bl (LENGTH('a)) (- numeral bin)" unfolding word_neg_numeral_alt by (rule to_bl_of_bin) lemma to_bl_to_bin [simp] : "bl_to_bin (to_bl w) = uint w" by (simp add: uint_bl word_size) lemma uint_bl_bin: "bl_to_bin (bin_to_bl (LENGTH('a)) (uint x)) = uint x" for x :: "'a::len word" by (rule trans [OF bin_bl_bin word_ubin.norm_Rep]) \ \naturals\ lemma uints_unats: "uints n = int ` unats n" apply (unfold unats_def uints_num) apply safe apply (rule_tac image_eqI) apply (erule_tac nat_0_le [symmetric]) by auto lemma unats_uints: "unats n = nat ` uints n" by (auto simp: uints_unats image_iff) lemmas bintr_num = word_ubin.norm_eq_iff [of "numeral a" "numeral b", symmetric, folded word_numeral_alt] for a b lemmas sbintr_num = word_sbin.norm_eq_iff [of "numeral a" "numeral b", symmetric, folded word_numeral_alt] for a b lemma num_of_bintr': "bintrunc (LENGTH('a::len)) (numeral a) = (numeral b) \ numeral a = (numeral b :: 'a word)" unfolding bintr_num by (erule subst, simp) lemma num_of_sbintr': "sbintrunc (LENGTH('a::len) - 1) (numeral a) = (numeral b) \ numeral a = (numeral b :: 'a word)" unfolding sbintr_num by (erule subst, simp) lemma num_abs_bintr: "(numeral x :: 'a word) = word_of_int (bintrunc (LENGTH('a::len)) (numeral x))" by (simp only: word_ubin.Abs_norm word_numeral_alt) lemma num_abs_sbintr: "(numeral x :: 'a word) = word_of_int (sbintrunc (LENGTH('a::len) - 1) (numeral x))" by (simp only: word_sbin.Abs_norm word_numeral_alt) text \ \cast\ -- note, no arg for new length, as it's determined by type of result, thus in \cast w = w\, the type means cast to length of \w\! \ lemma bit_ucast_iff: \Parity.bit (ucast a :: 'a::len word) n \ n < LENGTH('a::len) \ Parity.bit a n\ by (simp add: ucast_def, transfer) (auto simp add: bit_take_bit_iff) lemma ucast_id: "ucast w = w" by (auto simp: ucast_def) lemma scast_id: "scast w = w" by (auto simp: scast_def) lemma ucast_bl: "ucast w = of_bl (to_bl w)" by (auto simp: ucast_def of_bl_def uint_bl word_size) lemma nth_ucast: "(ucast w::'a::len word) !! n = (w !! n \ n < LENGTH('a))" by (simp add: ucast_def test_bit_bin word_ubin.eq_norm nth_bintr word_size) (fast elim!: bin_nth_uint_imp) context includes lifting_syntax begin lemma transfer_rule_mask_word [transfer_rule]: \((=) ===> pcr_word) Bit_Operations.mask Bit_Operations.mask\ by (simp only: mask_eq_exp_minus_1 [abs_def]) transfer_prover end lemma ucast_mask_eq: \ucast (Bit_Operations.mask n :: 'b word) = Bit_Operations.mask (min LENGTH('b::len) n)\ by (simp add: bit_eq_iff) (auto simp add: bit_mask_iff bit_ucast_iff exp_eq_zero_iff) \ \literal u(s)cast\ lemma ucast_bintr [simp]: "ucast (numeral w :: 'a::len word) = word_of_int (bintrunc (LENGTH('a)) (numeral w))" by (simp add: ucast_def) (* TODO: neg_numeral *) lemma scast_sbintr [simp]: "scast (numeral w ::'a::len word) = word_of_int (sbintrunc (LENGTH('a) - Suc 0) (numeral w))" by (simp add: scast_def) lemma source_size: "source_size (c::'a::len word \ _) = LENGTH('a)" unfolding source_size_def word_size Let_def .. lemma target_size: "target_size (c::_ \ 'b::len word) = LENGTH('b)" unfolding target_size_def word_size Let_def .. lemma is_down: "is_down c \ LENGTH('b) \ LENGTH('a)" for c :: "'a::len word \ 'b::len word" by (simp only: is_down_def source_size target_size) lemma is_up: "is_up c \ LENGTH('a) \ LENGTH('b)" for c :: "'a::len word \ 'b::len word" by (simp only: is_up_def source_size target_size) lemmas is_up_down = trans [OF is_up is_down [symmetric]] lemma down_cast_same [OF refl]: "uc = ucast \ is_down uc \ uc = scast" apply (unfold is_down) apply safe apply (rule ext) apply (unfold ucast_def scast_def uint_sint) apply (rule word_ubin.norm_eq_iff [THEN iffD1]) apply simp done lemma word_rev_tf: "to_bl (of_bl bl::'a::len word) = rev (takefill False (LENGTH('a)) (rev bl))" by (auto simp: of_bl_def uint_bl bl_bin_bl_rtf word_ubin.eq_norm word_size) lemma word_rep_drop: "to_bl (of_bl bl::'a::len word) = replicate (LENGTH('a) - length bl) False @ drop (length bl - LENGTH('a)) bl" by (simp add: word_rev_tf takefill_alt rev_take) lemma to_bl_ucast: "to_bl (ucast (w::'b::len word) ::'a::len word) = replicate (LENGTH('a) - LENGTH('b)) False @ drop (LENGTH('b) - LENGTH('a)) (to_bl w)" apply (unfold ucast_bl) apply (rule trans) apply (rule word_rep_drop) apply simp done lemma ucast_up_app [OF refl]: "uc = ucast \ source_size uc + n = target_size uc \ to_bl (uc w) = replicate n False @ (to_bl w)" by (auto simp add : source_size target_size to_bl_ucast) lemma ucast_down_drop [OF refl]: "uc = ucast \ source_size uc = target_size uc + n \ to_bl (uc w) = drop n (to_bl w)" by (auto simp add : source_size target_size to_bl_ucast) lemma scast_down_drop [OF refl]: "sc = scast \ source_size sc = target_size sc + n \ to_bl (sc w) = drop n (to_bl w)" apply (subgoal_tac "sc = ucast") apply safe apply simp apply (erule ucast_down_drop) apply (rule down_cast_same [symmetric]) apply (simp add : source_size target_size is_down) done lemma sint_up_scast [OF refl]: "sc = scast \ is_up sc \ sint (sc w) = sint w" apply (unfold is_up) apply safe apply (simp add: scast_def word_sbin.eq_norm) apply (rule box_equals) prefer 3 apply (rule word_sbin.norm_Rep) apply (rule sbintrunc_sbintrunc_l) defer apply (subst word_sbin.norm_Rep) apply (rule refl) apply simp done lemma uint_up_ucast [OF refl]: "uc = ucast \ is_up uc \ uint (uc w) = uint w" apply (unfold is_up) apply safe apply (rule bin_eqI) apply (fold word_test_bit_def) apply (auto simp add: nth_ucast) apply (auto simp add: test_bit_bin) done lemma ucast_up_ucast [OF refl]: "uc = ucast \ is_up uc \ ucast (uc w) = ucast w" apply (simp (no_asm) add: ucast_def) apply (clarsimp simp add: uint_up_ucast) done lemma scast_up_scast [OF refl]: "sc = scast \ is_up sc \ scast (sc w) = scast w" apply (simp (no_asm) add: scast_def) apply (clarsimp simp add: sint_up_scast) done lemma ucast_of_bl_up [OF refl]: "w = of_bl bl \ size bl \ size w \ ucast w = of_bl bl" by (auto simp add : nth_ucast word_size test_bit_of_bl intro!: word_eqI) lemmas ucast_up_ucast_id = trans [OF ucast_up_ucast ucast_id] lemmas scast_up_scast_id = trans [OF scast_up_scast scast_id] lemmas isduu = is_up_down [where c = "ucast", THEN iffD2] lemmas isdus = is_up_down [where c = "scast", THEN iffD2] lemmas ucast_down_ucast_id = isduu [THEN ucast_up_ucast_id] lemmas scast_down_scast_id = isdus [THEN ucast_up_ucast_id] lemma up_ucast_surj: "is_up (ucast :: 'b::len word \ 'a::len word) \ surj (ucast :: 'a word \ 'b word)" by (rule surjI) (erule ucast_up_ucast_id) lemma up_scast_surj: "is_up (scast :: 'b::len word \ 'a::len word) \ surj (scast :: 'a word \ 'b word)" by (rule surjI) (erule scast_up_scast_id) lemma down_scast_inj: "is_down (scast :: 'b::len word \ 'a::len word) \ inj_on (ucast :: 'a word \ 'b word) A" by (rule inj_on_inverseI, erule scast_down_scast_id) lemma down_ucast_inj: "is_down (ucast :: 'b::len word \ 'a::len word) \ inj_on (ucast :: 'a word \ 'b word) A" by (rule inj_on_inverseI) (erule ucast_down_ucast_id) lemma of_bl_append_same: "of_bl (X @ to_bl w) = w" by (rule word_bl.Rep_eqD) (simp add: word_rep_drop) lemma ucast_down_wi [OF refl]: "uc = ucast \ is_down uc \ uc (word_of_int x) = word_of_int x" apply (unfold is_down) apply (clarsimp simp add: ucast_def word_ubin.eq_norm) apply (rule word_ubin.norm_eq_iff [THEN iffD1]) apply (erule bintrunc_bintrunc_ge) done lemma ucast_down_no [OF refl]: "uc = ucast \ is_down uc \ uc (numeral bin) = numeral bin" unfolding word_numeral_alt by clarify (rule ucast_down_wi) lemma ucast_down_bl [OF refl]: "uc = ucast \ is_down uc \ uc (of_bl bl) = of_bl bl" unfolding of_bl_def by clarify (erule ucast_down_wi) lemmas slice_def' = slice_def [unfolded word_size] lemmas test_bit_def' = word_test_bit_def [THEN fun_cong] lemmas word_log_defs = word_and_def word_or_def word_xor_def word_not_def subsection \Word Arithmetic\ lemma word_less_alt: "a < b \ uint a < uint b" by (fact word_less_def) lemma signed_linorder: "class.linorder word_sle word_sless" by standard (auto simp: word_sle_def word_sless_def) interpretation signed: linorder "word_sle" "word_sless" by (rule signed_linorder) lemma udvdI: "0 \ n \ uint b = n * uint a \ a udvd b" by (auto simp: udvd_def) lemmas word_div_no [simp] = word_div_def [of "numeral a" "numeral b"] for a b lemmas word_mod_no [simp] = word_mod_def [of "numeral a" "numeral b"] for a b lemmas word_less_no [simp] = word_less_def [of "numeral a" "numeral b"] for a b lemmas word_le_no [simp] = word_le_def [of "numeral a" "numeral b"] for a b lemmas word_sless_no [simp] = word_sless_def [of "numeral a" "numeral b"] for a b lemmas word_sle_no [simp] = word_sle_def [of "numeral a" "numeral b"] for a b lemma word_m1_wi: "- 1 = word_of_int (- 1)" by (simp add: word_neg_numeral_alt [of Num.One]) lemma word_0_bl [simp]: "of_bl [] = 0" by (simp add: of_bl_def) lemma word_1_bl: "of_bl [True] = 1" by (simp add: of_bl_def bl_to_bin_def) lemma uint_eq_0 [simp]: "uint 0 = 0" unfolding word_0_wi word_ubin.eq_norm by simp lemma of_bl_0 [simp]: "of_bl (replicate n False) = 0" by (simp add: of_bl_def bl_to_bin_rep_False) lemma to_bl_0 [simp]: "to_bl (0::'a::len word) = replicate (LENGTH('a)) False" by (simp add: uint_bl word_size bin_to_bl_zero) lemma uint_0_iff: "uint x = 0 \ x = 0" by (simp add: word_uint_eq_iff) lemma unat_0_iff: "unat x = 0 \ x = 0" by (auto simp: unat_def nat_eq_iff uint_0_iff) lemma unat_0 [simp]: "unat 0 = 0" by (auto simp: unat_def) lemma size_0_same': "size w = 0 \ w = v" for v w :: "'a::len word" apply (unfold word_size) apply (rule box_equals) defer apply (rule word_uint.Rep_inverse)+ apply (rule word_ubin.norm_eq_iff [THEN iffD1]) apply simp done lemmas size_0_same = size_0_same' [unfolded word_size] lemmas unat_eq_0 = unat_0_iff lemmas unat_eq_zero = unat_0_iff lemma unat_gt_0: "0 < unat x \ x \ 0" by (auto simp: unat_0_iff [symmetric]) lemma ucast_0 [simp]: "ucast 0 = 0" by (simp add: ucast_def) lemma sint_0 [simp]: "sint 0 = 0" by (simp add: sint_uint) lemma scast_0 [simp]: "scast 0 = 0" by (simp add: scast_def) lemma sint_n1 [simp] : "sint (- 1) = - 1" by (simp only: word_m1_wi word_sbin.eq_norm) simp lemma scast_n1 [simp]: "scast (- 1) = - 1" by (simp add: scast_def) lemma uint_1 [simp]: "uint (1::'a::len word) = 1" by (simp only: word_1_wi word_ubin.eq_norm) simp lemma unat_1 [simp]: "unat (1::'a::len word) = 1" by (simp add: unat_def) lemma ucast_1 [simp]: "ucast (1::'a::len word) = 1" by (simp add: ucast_def) \ \now, to get the weaker results analogous to \word_div\/\mod_def\\ subsection \Transferring goals from words to ints\ lemma word_ths: shows word_succ_p1: "word_succ a = a + 1" and word_pred_m1: "word_pred a = a - 1" and word_pred_succ: "word_pred (word_succ a) = a" and word_succ_pred: "word_succ (word_pred a) = a" and word_mult_succ: "word_succ a * b = b + a * b" by (transfer, simp add: algebra_simps)+ lemma uint_cong: "x = y \ uint x = uint y" by simp lemma uint_word_ariths: fixes a b :: "'a::len word" shows "uint (a + b) = (uint a + uint b) mod 2 ^ LENGTH('a::len)" and "uint (a - b) = (uint a - uint b) mod 2 ^ LENGTH('a)" and "uint (a * b) = uint a * uint b mod 2 ^ LENGTH('a)" and "uint (- a) = - uint a mod 2 ^ LENGTH('a)" and "uint (word_succ a) = (uint a + 1) mod 2 ^ LENGTH('a)" and "uint (word_pred a) = (uint a - 1) mod 2 ^ LENGTH('a)" and "uint (0 :: 'a word) = 0 mod 2 ^ LENGTH('a)" and "uint (1 :: 'a word) = 1 mod 2 ^ LENGTH('a)" by (simp_all add: word_arith_wis [THEN trans [OF uint_cong int_word_uint]]) lemma uint_word_arith_bintrs: fixes a b :: "'a::len word" shows "uint (a + b) = bintrunc (LENGTH('a)) (uint a + uint b)" and "uint (a - b) = bintrunc (LENGTH('a)) (uint a - uint b)" and "uint (a * b) = bintrunc (LENGTH('a)) (uint a * uint b)" and "uint (- a) = bintrunc (LENGTH('a)) (- uint a)" and "uint (word_succ a) = bintrunc (LENGTH('a)) (uint a + 1)" and "uint (word_pred a) = bintrunc (LENGTH('a)) (uint a - 1)" and "uint (0 :: 'a word) = bintrunc (LENGTH('a)) 0" and "uint (1 :: 'a word) = bintrunc (LENGTH('a)) 1" by (simp_all add: uint_word_ariths bintrunc_mod2p) lemma sint_word_ariths: fixes a b :: "'a::len word" shows "sint (a + b) = sbintrunc (LENGTH('a) - 1) (sint a + sint b)" and "sint (a - b) = sbintrunc (LENGTH('a) - 1) (sint a - sint b)" and "sint (a * b) = sbintrunc (LENGTH('a) - 1) (sint a * sint b)" and "sint (- a) = sbintrunc (LENGTH('a) - 1) (- sint a)" and "sint (word_succ a) = sbintrunc (LENGTH('a) - 1) (sint a + 1)" and "sint (word_pred a) = sbintrunc (LENGTH('a) - 1) (sint a - 1)" and "sint (0 :: 'a word) = sbintrunc (LENGTH('a) - 1) 0" and "sint (1 :: 'a word) = sbintrunc (LENGTH('a) - 1) 1" apply (simp_all only: word_sbin.inverse_norm [symmetric]) apply (simp_all add: wi_hom_syms) apply transfer apply simp apply transfer apply simp done lemmas uint_div_alt = word_div_def [THEN trans [OF uint_cong int_word_uint]] lemmas uint_mod_alt = word_mod_def [THEN trans [OF uint_cong int_word_uint]] lemma word_pred_0_n1: "word_pred 0 = word_of_int (- 1)" unfolding word_pred_m1 by simp lemma succ_pred_no [simp]: "word_succ (numeral w) = numeral w + 1" "word_pred (numeral w) = numeral w - 1" "word_succ (- numeral w) = - numeral w + 1" "word_pred (- numeral w) = - numeral w - 1" by (simp_all add: word_succ_p1 word_pred_m1) lemma word_sp_01 [simp]: "word_succ (- 1) = 0 \ word_succ 0 = 1 \ word_pred 0 = - 1 \ word_pred 1 = 0" by (simp_all add: word_succ_p1 word_pred_m1) \ \alternative approach to lifting arithmetic equalities\ lemma word_of_int_Ex: "\y. x = word_of_int y" by (rule_tac x="uint x" in exI) simp subsection \Order on fixed-length words\ lemma word_zero_le [simp]: "0 \ y" for y :: "'a::len word" unfolding word_le_def by auto lemma word_m1_ge [simp] : "word_pred 0 \ y" (* FIXME: delete *) - by (simp only: word_le_def word_pred_0_n1 word_uint.eq_norm m1mod2k) auto + by transfer (simp add: take_bit_minus_one_eq_mask mask_eq_exp_minus_1 bintr_lt2p) lemma word_n1_ge [simp]: "y \ -1" for y :: "'a::len word" by (fact word_order.extremum) lemmas word_not_simps [simp] = word_zero_le [THEN leD] word_m1_ge [THEN leD] word_n1_ge [THEN leD] lemma word_gt_0: "0 < y \ 0 \ y" for y :: "'a::len word" by (simp add: less_le) lemmas word_gt_0_no [simp] = word_gt_0 [of "numeral y"] for y lemma word_sless_alt: "a sint a < sint b" by (auto simp add: word_sle_def word_sless_def less_le) lemma word_le_nat_alt: "a \ b \ unat a \ unat b" unfolding unat_def word_le_def by (rule nat_le_eq_zle [symmetric]) simp lemma word_less_nat_alt: "a < b \ unat a < unat b" unfolding unat_def word_less_alt by (rule nat_less_eq_zless [symmetric]) simp lemmas unat_mono = word_less_nat_alt [THEN iffD1] instance word :: (len) wellorder proof fix P :: "'a word \ bool" and a assume *: "(\b. (\a. a < b \ P a) \ P b)" have "wf (measure unat)" .. moreover have "{(a, b :: ('a::len) word). a < b} \ measure unat" by (auto simp add: word_less_nat_alt) ultimately have "wf {(a, b :: ('a::len) word). a < b}" by (rule wf_subset) then show "P a" using * by induction blast qed lemma wi_less: "(word_of_int n < (word_of_int m :: 'a::len word)) = (n mod 2 ^ LENGTH('a) < m mod 2 ^ LENGTH('a))" unfolding word_less_alt by (simp add: word_uint.eq_norm) lemma wi_le: "(word_of_int n \ (word_of_int m :: 'a::len word)) = (n mod 2 ^ LENGTH('a) \ m mod 2 ^ LENGTH('a))" unfolding word_le_def by (simp add: word_uint.eq_norm) lemma udvd_nat_alt: "a udvd b \ (\n\0. unat b = n * unat a)" apply (unfold udvd_def) apply safe apply (simp add: unat_def nat_mult_distrib) apply (simp add: uint_nat) apply (rule exI) apply safe prefer 2 apply (erule notE) apply (rule refl) apply force done lemma udvd_iff_dvd: "x udvd y \ unat x dvd unat y" unfolding dvd_def udvd_nat_alt by force lemma unat_minus_one: assumes "w \ 0" shows "unat (w - 1) = unat w - 1" proof - have "0 \ uint w" by (fact uint_nonnegative) moreover from assms have "0 \ uint w" by (simp add: uint_0_iff) ultimately have "1 \ uint w" by arith from uint_lt2p [of w] have "uint w - 1 < 2 ^ LENGTH('a)" by arith with \1 \ uint w\ have "(uint w - 1) mod 2 ^ LENGTH('a) = uint w - 1" by (auto intro: mod_pos_pos_trivial) with \1 \ uint w\ have "nat ((uint w - 1) mod 2 ^ LENGTH('a)) = nat (uint w) - 1" by auto then show ?thesis by (simp only: unat_def int_word_uint word_arith_wis mod_diff_right_eq) qed lemma measure_unat: "p \ 0 \ unat (p - 1) < unat p" by (simp add: unat_minus_one) (simp add: unat_0_iff [symmetric]) lemmas uint_add_ge0 [simp] = add_nonneg_nonneg [OF uint_ge_0 uint_ge_0] lemmas uint_mult_ge0 [simp] = mult_nonneg_nonneg [OF uint_ge_0 uint_ge_0] lemma uint_sub_lt2p [simp]: "uint x - uint y < 2 ^ LENGTH('a)" for x :: "'a::len word" and y :: "'b::len word" using uint_ge_0 [of y] uint_lt2p [of x] by arith subsection \Conditions for the addition (etc) of two words to overflow\ lemma uint_add_lem: "(uint x + uint y < 2 ^ LENGTH('a)) = (uint (x + y) = uint x + uint y)" for x y :: "'a::len word" - by (unfold uint_word_ariths) (auto intro!: trans [OF _ int_mod_lem]) + by (metis add.right_neutral add_mono_thms_linordered_semiring(1) mod_pos_pos_trivial of_nat_0_le_iff uint_lt2p uint_nat uint_word_ariths(1)) lemma uint_mult_lem: "(uint x * uint y < 2 ^ LENGTH('a)) = (uint (x * y) = uint x * uint y)" for x y :: "'a::len word" - by (unfold uint_word_ariths) (auto intro!: trans [OF _ int_mod_lem]) + by (metis mod_pos_pos_trivial uint_lt2p uint_mult_ge0 uint_word_ariths(3)) lemma uint_sub_lem: "uint x \ uint y \ uint (x - y) = uint x - uint y" - by (auto simp: uint_word_ariths intro!: trans [OF _ int_mod_lem]) + by (metis (mono_tags, hide_lams) diff_ge_0_iff_ge mod_pos_pos_trivial of_nat_0_le_iff take_bit_eq_mod uint_nat uint_sub_lt2p word_sub_wi word_ubin.eq_norm) find_theorems uint \- _\ lemma uint_add_le: "uint (x + y) \ uint x + uint y" - unfolding uint_word_ariths by (metis uint_add_ge0 zmod_le_nonneg_dividend) + unfolding uint_word_ariths by (simp add: zmod_le_nonneg_dividend) lemma uint_sub_ge: "uint (x - y) \ uint x - uint y" - unfolding uint_word_ariths by (metis int_mod_ge uint_sub_lt2p zless2p) - + unfolding uint_word_ariths by (simp add: int_mod_ge) + lemma mod_add_if_z: "x < z \ y < z \ 0 \ y \ 0 \ x \ 0 \ z \ (x + y) mod z = (if x + y < z then x + y else x + y - z)" for x y z :: int - by (auto intro: int_mod_eq) + apply (auto simp add: not_less) + apply (rule antisym) + apply (metis diff_ge_0_iff_ge minus_mod_self2 zmod_le_nonneg_dividend) + apply (simp only: flip: minus_mod_self2 [of \x + y\ z]) + apply (rule int_mod_ge) + apply simp_all + done lemma uint_plus_if': "uint (a + b) = (if uint a + uint b < 2 ^ LENGTH('a) then uint a + uint b else uint a + uint b - 2 ^ LENGTH('a))" for a b :: "'a::len word" using mod_add_if_z [of "uint a" _ "uint b"] by (simp add: uint_word_ariths) lemma mod_sub_if_z: "x < z \ y < z \ 0 \ y \ 0 \ x \ 0 \ z \ (x - y) mod z = (if y \ x then x - y else x - y + z)" for x y z :: int - by (auto intro: int_mod_eq) + apply (auto simp add: not_le) + apply (rule antisym) + apply (simp only: flip: mod_add_self2 [of \x - y\ z]) + apply (rule zmod_le_nonneg_dividend) + apply simp + apply (metis add.commute add.right_neutral add_le_cancel_left diff_ge_0_iff_ge int_mod_ge le_less le_less_trans mod_add_self1 not_le not_less) + done lemma uint_sub_if': "uint (a - b) = (if uint b \ uint a then uint a - uint b else uint a - uint b + 2 ^ LENGTH('a))" for a b :: "'a::len word" using mod_sub_if_z [of "uint a" _ "uint b"] by (simp add: uint_word_ariths) subsection \Definition of \uint_arith\\ lemma word_of_int_inverse: "word_of_int r = a \ 0 \ r \ r < 2 ^ LENGTH('a) \ uint a = r" for a :: "'a::len word" apply (erule word_uint.Abs_inverse' [rotated]) apply (simp add: uints_num) done lemma uint_split: "P (uint x) = (\i. word_of_int i = x \ 0 \ i \ i < 2^LENGTH('a) \ P i)" for x :: "'a::len word" apply (fold word_int_case_def) apply (auto dest!: word_of_int_inverse simp: int_word_uint split: word_int_split) done lemma uint_split_asm: "P (uint x) = (\i. word_of_int i = x \ 0 \ i \ i < 2^LENGTH('a) \ \ P i)" for x :: "'a::len word" by (auto dest!: word_of_int_inverse simp: int_word_uint split: uint_split) lemmas uint_splits = uint_split uint_split_asm lemmas uint_arith_simps = word_le_def word_less_alt word_uint.Rep_inject [symmetric] uint_sub_if' uint_plus_if' \ \use this to stop, eg. \2 ^ LENGTH(32)\ being simplified\ lemma power_False_cong: "False \ a ^ b = c ^ d" by auto \ \\uint_arith_tac\: reduce to arithmetic on int, try to solve by arith\ ML \ fun uint_arith_simpset ctxt = ctxt addsimps @{thms uint_arith_simps} delsimps @{thms word_uint.Rep_inject} |> fold Splitter.add_split @{thms if_split_asm} |> fold Simplifier.add_cong @{thms power_False_cong} fun uint_arith_tacs ctxt = let fun arith_tac' n t = Arith_Data.arith_tac ctxt n t handle Cooper.COOPER _ => Seq.empty; in [ clarify_tac ctxt 1, full_simp_tac (uint_arith_simpset ctxt) 1, ALLGOALS (full_simp_tac (put_simpset HOL_ss ctxt |> fold Splitter.add_split @{thms uint_splits} |> fold Simplifier.add_cong @{thms power_False_cong})), rewrite_goals_tac ctxt @{thms word_size}, ALLGOALS (fn n => REPEAT (resolve_tac ctxt [allI, impI] n) THEN REPEAT (eresolve_tac ctxt [conjE] n) THEN REPEAT (dresolve_tac ctxt @{thms word_of_int_inverse} n THEN assume_tac ctxt n THEN assume_tac ctxt n)), TRYALL arith_tac' ] end fun uint_arith_tac ctxt = SELECT_GOAL (EVERY (uint_arith_tacs ctxt)) \ method_setup uint_arith = \Scan.succeed (SIMPLE_METHOD' o uint_arith_tac)\ "solving word arithmetic via integers and arith" subsection \More on overflows and monotonicity\ lemma no_plus_overflow_uint_size: "x \ x + y \ uint x + uint y < 2 ^ size x" for x y :: "'a::len word" unfolding word_size by uint_arith lemmas no_olen_add = no_plus_overflow_uint_size [unfolded word_size] lemma no_ulen_sub: "x \ x - y \ uint y \ uint x" for x y :: "'a::len word" by uint_arith lemma no_olen_add': "x \ y + x \ uint y + uint x < 2 ^ LENGTH('a)" for x y :: "'a::len word" by (simp add: ac_simps no_olen_add) lemmas olen_add_eqv = trans [OF no_olen_add no_olen_add' [symmetric]] lemmas uint_plus_simple_iff = trans [OF no_olen_add uint_add_lem] lemmas uint_plus_simple = uint_plus_simple_iff [THEN iffD1] lemmas uint_minus_simple_iff = trans [OF no_ulen_sub uint_sub_lem] lemmas uint_minus_simple_alt = uint_sub_lem [folded word_le_def] lemmas word_sub_le_iff = no_ulen_sub [folded word_le_def] lemmas word_sub_le = word_sub_le_iff [THEN iffD2] lemma word_less_sub1: "x \ 0 \ 1 < x \ 0 < x - 1" for x :: "'a::len word" by uint_arith lemma word_le_sub1: "x \ 0 \ 1 \ x \ 0 \ x - 1" for x :: "'a::len word" by uint_arith lemma sub_wrap_lt: "x < x - z \ x < z" for x z :: "'a::len word" by uint_arith lemma sub_wrap: "x \ x - z \ z = 0 \ x < z" for x z :: "'a::len word" by uint_arith lemma plus_minus_not_NULL_ab: "x \ ab - c \ c \ ab \ c \ 0 \ x + c \ 0" for x ab c :: "'a::len word" by uint_arith lemma plus_minus_no_overflow_ab: "x \ ab - c \ c \ ab \ x \ x + c" for x ab c :: "'a::len word" by uint_arith lemma le_minus': "a + c \ b \ a \ a + c \ c \ b - a" for a b c :: "'a::len word" by uint_arith lemma le_plus': "a \ b \ c \ b - a \ a + c \ b" for a b c :: "'a::len word" by uint_arith lemmas le_plus = le_plus' [rotated] lemmas le_minus = leD [THEN thin_rl, THEN le_minus'] (* FIXME *) lemma word_plus_mono_right: "y \ z \ x \ x + z \ x + y \ x + z" for x y z :: "'a::len word" by uint_arith lemma word_less_minus_cancel: "y - x < z - x \ x \ z \ y < z" for x y z :: "'a::len word" by uint_arith lemma word_less_minus_mono_left: "y < z \ x \ y \ y - x < z - x" for x y z :: "'a::len word" by uint_arith lemma word_less_minus_mono: "a < c \ d < b \ a - b < a \ c - d < c \ a - b < c - d" for a b c d :: "'a::len word" by uint_arith lemma word_le_minus_cancel: "y - x \ z - x \ x \ z \ y \ z" for x y z :: "'a::len word" by uint_arith lemma word_le_minus_mono_left: "y \ z \ x \ y \ y - x \ z - x" for x y z :: "'a::len word" by uint_arith lemma word_le_minus_mono: "a \ c \ d \ b \ a - b \ a \ c - d \ c \ a - b \ c - d" for a b c d :: "'a::len word" by uint_arith lemma plus_le_left_cancel_wrap: "x + y' < x \ x + y < x \ x + y' < x + y \ y' < y" for x y y' :: "'a::len word" by uint_arith lemma plus_le_left_cancel_nowrap: "x \ x + y' \ x \ x + y \ x + y' < x + y \ y' < y" for x y y' :: "'a::len word" by uint_arith lemma word_plus_mono_right2: "a \ a + b \ c \ b \ a \ a + c" for a b c :: "'a::len word" by uint_arith lemma word_less_add_right: "x < y - z \ z \ y \ x + z < y" for x y z :: "'a::len word" by uint_arith lemma word_less_sub_right: "x < y + z \ y \ x \ x - y < z" for x y z :: "'a::len word" by uint_arith lemma word_le_plus_either: "x \ y \ x \ z \ y \ y + z \ x \ y + z" for x y z :: "'a::len word" by uint_arith lemma word_less_nowrapI: "x < z - k \ k \ z \ 0 < k \ x < x + k" for x z k :: "'a::len word" by uint_arith lemma inc_le: "i < m \ i + 1 \ m" for i m :: "'a::len word" by uint_arith lemma inc_i: "1 \ i \ i < m \ 1 \ i + 1 \ i + 1 \ m" for i m :: "'a::len word" by uint_arith lemma udvd_incr_lem: "up < uq \ up = ua + n * uint K \ uq = ua + n' * uint K \ up + uint K \ uq" - apply clarsimp - apply (drule less_le_mult) - apply safe - done + by auto (metis int_distrib(1) linorder_not_less mult.left_neutral mult_right_mono uint_nonnegative zless_imp_add1_zle) lemma udvd_incr': "p < q \ uint p = ua + n * uint K \ uint q = ua + n' * uint K \ p + K \ q" apply (unfold word_less_alt word_le_def) apply (drule (2) udvd_incr_lem) apply (erule uint_add_le [THEN order_trans]) done lemma udvd_decr': "p < q \ uint p = ua + n * uint K \ uint q = ua + n' * uint K \ p \ q - K" apply (unfold word_less_alt word_le_def) apply (drule (2) udvd_incr_lem) apply (drule le_diff_eq [THEN iffD2]) apply (erule order_trans) apply (rule uint_sub_ge) done lemmas udvd_incr_lem0 = udvd_incr_lem [where ua=0, unfolded add_0_left] lemmas udvd_incr0 = udvd_incr' [where ua=0, unfolded add_0_left] lemmas udvd_decr0 = udvd_decr' [where ua=0, unfolded add_0_left] lemma udvd_minus_le': "xy < k \ z udvd xy \ z udvd k \ xy \ k - z" apply (unfold udvd_def) apply clarify apply (erule (2) udvd_decr0) done lemma udvd_incr2_K: "p < a + s \ a \ a + s \ K udvd s \ K udvd p - a \ a \ p \ 0 < K \ p \ p + K \ p + K \ a + s" supply [[simproc del: linordered_ring_less_cancel_factor]] apply (unfold udvd_def) apply clarify apply (simp add: uint_arith_simps split: if_split_asm) prefer 2 apply (insert uint_range' [of s])[1] apply arith - apply (drule add.commute [THEN xtr1]) - apply (simp add: diff_less_eq [symmetric]) - apply (drule less_le_mult) - apply arith + apply (drule add.commute [THEN xtrans(1)]) + apply (simp flip: diff_less_eq) + apply (subst (asm) mult_less_cancel_right) apply simp + apply (simp add: diff_eq_eq not_less) + apply (subst (asm) (3) zless_iff_Suc_zadd) + apply auto + apply (auto simp add: algebra_simps) + apply (drule less_le_trans [of _ \2 ^ LENGTH('a)\]) apply assumption + apply (simp add: mult_less_0_iff) done \ \links with \rbl\ operations\ lemma word_succ_rbl: "to_bl w = bl \ to_bl (word_succ w) = rev (rbl_succ (rev bl))" apply (unfold word_succ_alt) apply clarify apply (simp add: to_bl_of_bin) apply (simp add: to_bl_def rbl_succ) done lemma word_pred_rbl: "to_bl w = bl \ to_bl (word_pred w) = rev (rbl_pred (rev bl))" apply (unfold word_pred_alt) apply clarify apply (simp add: to_bl_of_bin) apply (simp add: to_bl_def rbl_pred) done lemma word_add_rbl: "to_bl v = vbl \ to_bl w = wbl \ to_bl (v + w) = rev (rbl_add (rev vbl) (rev wbl))" apply (unfold word_add_def) apply clarify apply (simp add: to_bl_of_bin) apply (simp add: to_bl_def rbl_add) done lemma word_mult_rbl: "to_bl v = vbl \ to_bl w = wbl \ to_bl (v * w) = rev (rbl_mult (rev vbl) (rev wbl))" apply (unfold word_mult_def) apply clarify apply (simp add: to_bl_of_bin) apply (simp add: to_bl_def rbl_mult) done lemma rtb_rbl_ariths: "rev (to_bl w) = ys \ rev (to_bl (word_succ w)) = rbl_succ ys" "rev (to_bl w) = ys \ rev (to_bl (word_pred w)) = rbl_pred ys" "rev (to_bl v) = ys \ rev (to_bl w) = xs \ rev (to_bl (v * w)) = rbl_mult ys xs" "rev (to_bl v) = ys \ rev (to_bl w) = xs \ rev (to_bl (v + w)) = rbl_add ys xs" by (auto simp: rev_swap [symmetric] word_succ_rbl word_pred_rbl word_mult_rbl word_add_rbl) subsection \Arithmetic type class instantiations\ lemmas word_le_0_iff [simp] = word_zero_le [THEN leD, THEN antisym_conv1] lemma word_of_int_nat: "0 \ x \ word_of_int x = of_nat (nat x)" by (simp add: word_of_int) text \ note that \iszero_def\ is only for class \comm_semiring_1_cancel\, which requires word length \\ 1\, ie \'a::len word\ \ lemma iszero_word_no [simp]: "iszero (numeral bin :: 'a::len word) = iszero (bintrunc (LENGTH('a)) (numeral bin))" using word_ubin.norm_eq_iff [where 'a='a, of "numeral bin" 0] by (simp add: iszero_def [symmetric]) text \Use \iszero\ to simplify equalities between word numerals.\ lemmas word_eq_numeral_iff_iszero [simp] = eq_numeral_iff_iszero [where 'a="'a::len word"] subsection \Word and nat\ lemma td_ext_unat [OF refl]: "n = LENGTH('a::len) \ td_ext (unat :: 'a word \ nat) of_nat (unats n) (\i. i mod 2 ^ n)" apply (unfold td_ext_def' unat_def word_of_nat unats_uints) apply (auto intro!: imageI simp add : word_of_int_hom_syms) apply (erule word_uint.Abs_inverse [THEN arg_cong]) apply (simp add: int_word_uint nat_mod_distrib nat_power_eq) done lemmas unat_of_nat = td_ext_unat [THEN td_ext.eq_norm] interpretation word_unat: td_ext "unat::'a::len word \ nat" of_nat "unats (LENGTH('a::len))" "\i. i mod 2 ^ LENGTH('a::len)" by (rule td_ext_unat) lemmas td_unat = word_unat.td_thm lemmas unat_lt2p [iff] = word_unat.Rep [unfolded unats_def mem_Collect_eq] lemma unat_le: "y \ unat z \ y \ unats (LENGTH('a))" for z :: "'a::len word" apply (unfold unats_def) apply clarsimp apply (rule xtrans, rule unat_lt2p, assumption) done lemma word_nchotomy: "\w :: 'a::len word. \n. w = of_nat n \ n < 2 ^ LENGTH('a)" apply (rule allI) apply (rule word_unat.Abs_cases) apply (unfold unats_def) apply auto done lemma of_nat_eq: "of_nat n = w \ (\q. n = unat w + q * 2 ^ LENGTH('a))" for w :: "'a::len word" using mod_div_mult_eq [of n "2 ^ LENGTH('a)", symmetric] by (auto simp add: word_unat.inverse_norm) lemma of_nat_eq_size: "of_nat n = w \ (\q. n = unat w + q * 2 ^ size w)" unfolding word_size by (rule of_nat_eq) lemma of_nat_0: "of_nat m = (0::'a::len word) \ (\q. m = q * 2 ^ LENGTH('a))" by (simp add: of_nat_eq) lemma of_nat_2p [simp]: "of_nat (2 ^ LENGTH('a)) = (0::'a::len word)" by (fact mult_1 [symmetric, THEN iffD2 [OF of_nat_0 exI]]) lemma of_nat_gt_0: "of_nat k \ 0 \ 0 < k" by (cases k) auto lemma of_nat_neq_0: "0 < k \ k < 2 ^ LENGTH('a::len) \ of_nat k \ (0 :: 'a word)" by (auto simp add : of_nat_0) lemma Abs_fnat_hom_add: "of_nat a + of_nat b = of_nat (a + b)" by simp lemma Abs_fnat_hom_mult: "of_nat a * of_nat b = (of_nat (a * b) :: 'a::len word)" by (simp add: word_of_nat wi_hom_mult) lemma Abs_fnat_hom_Suc: "word_succ (of_nat a) = of_nat (Suc a)" by (simp add: word_of_nat wi_hom_succ ac_simps) lemma Abs_fnat_hom_0: "(0::'a::len word) = of_nat 0" by simp lemma Abs_fnat_hom_1: "(1::'a::len word) = of_nat (Suc 0)" by simp lemmas Abs_fnat_homs = Abs_fnat_hom_add Abs_fnat_hom_mult Abs_fnat_hom_Suc Abs_fnat_hom_0 Abs_fnat_hom_1 lemma word_arith_nat_add: "a + b = of_nat (unat a + unat b)" by simp lemma word_arith_nat_mult: "a * b = of_nat (unat a * unat b)" by simp lemma word_arith_nat_Suc: "word_succ a = of_nat (Suc (unat a))" by (subst Abs_fnat_hom_Suc [symmetric]) simp lemma word_arith_nat_div: "a div b = of_nat (unat a div unat b)" by (simp add: word_div_def word_of_nat zdiv_int uint_nat) lemma word_arith_nat_mod: "a mod b = of_nat (unat a mod unat b)" by (simp add: word_mod_def word_of_nat zmod_int uint_nat) lemmas word_arith_nat_defs = word_arith_nat_add word_arith_nat_mult word_arith_nat_Suc Abs_fnat_hom_0 Abs_fnat_hom_1 word_arith_nat_div word_arith_nat_mod lemma unat_cong: "x = y \ unat x = unat y" by simp lemmas unat_word_ariths = word_arith_nat_defs [THEN trans [OF unat_cong unat_of_nat]] lemmas word_sub_less_iff = word_sub_le_iff [unfolded linorder_not_less [symmetric] Not_eq_iff] lemma unat_add_lem: "unat x + unat y < 2 ^ LENGTH('a) \ unat (x + y) = unat x + unat y" for x y :: "'a::len word" - by (auto simp: unat_word_ariths intro!: trans [OF _ nat_mod_lem]) + apply (auto simp: unat_word_ariths) + apply (metis unat_lt2p word_unat.eq_norm) + done lemma unat_mult_lem: "unat x * unat y < 2 ^ LENGTH('a) \ unat (x * y) = unat x * unat y" for x y :: "'a::len word" - by (auto simp: unat_word_ariths intro!: trans [OF _ nat_mod_lem]) - -lemmas unat_plus_if' = - trans [OF unat_word_ariths(1) mod_nat_add, simplified] + apply (auto simp: unat_word_ariths) + apply (metis unat_lt2p word_unat.eq_norm) + done + +lemma unat_plus_if': + \unat (a + b) = + (if unat a + unat b < 2 ^ LENGTH('a) + then unat a + unat b + else unat a + unat b - 2 ^ LENGTH('a))\ for a b :: \'a::len word\ + apply (auto simp: unat_word_ariths not_less) + apply (subst (asm) le_iff_add) + apply auto + apply (metis add_less_cancel_left add_less_cancel_right le_less_trans less_imp_le mod_less unat_lt2p) + done lemma le_no_overflow: "x \ b \ a \ a + b \ x \ a + b" for a b x :: "'a::len word" apply (erule order_trans) apply (erule olen_add_eqv [THEN iffD1]) done lemmas un_ui_le = trans [OF word_le_nat_alt [symmetric] word_le_def] lemma unat_sub_if_size: "unat (x - y) = (if unat y \ unat x then unat x - unat y else unat x + 2 ^ size x - unat y)" apply (unfold word_size) apply (simp add: un_ui_le) apply (auto simp add: unat_def uint_sub_if') apply (rule nat_diff_distrib) prefer 3 apply (simp add: algebra_simps) apply (rule nat_diff_distrib [THEN trans]) prefer 3 apply (subst nat_add_distrib) prefer 3 apply (simp add: nat_power_eq) apply auto apply uint_arith done lemmas unat_sub_if' = unat_sub_if_size [unfolded word_size] -lemma unat_div: "unat (x div y) = unat x div unat y" - for x y :: " 'a::len word" - apply (simp add : unat_word_ariths) - apply (rule unat_lt2p [THEN xtr7, THEN nat_mod_eq']) - apply (rule div_le_dividend) - done - +lemma uint_div: + \uint (x div y) = uint x div uint y\ + by (metis div_le_dividend le_less_trans mod_less uint_nat unat_lt2p unat_word_ariths(6) zdiv_int) + +lemma unat_div: + \unat (x div y) = unat x div unat y\ + by (simp add: unat_def uint_div add: nat_div_distrib) + +lemma uint_mod: + \uint (x mod y) = uint x mod uint y\ + by (metis (no_types, lifting) le_less_trans mod_by_0 mod_le_divisor mod_less neq0_conv uint_nat unat_lt2p unat_word_ariths(7) zmod_int) + lemma unat_mod: "unat (x mod y) = unat x mod unat y" for x y :: "'a::len word" - apply (clarsimp simp add : unat_word_ariths) - apply (cases "unat y") - prefer 2 - apply (rule unat_lt2p [THEN xtr7, THEN nat_mod_eq']) - apply (rule mod_le_divisor) - apply auto - done - -lemma uint_div: "uint (x div y) = uint x div uint y" - for x y :: "'a::len word" - by (simp add: uint_nat unat_div zdiv_int) - -lemma uint_mod: "uint (x mod y) = uint x mod uint y" - for x y :: "'a::len word" - by (simp add: uint_nat unat_mod zmod_int) + by (simp add: unat_def uint_mod add: nat_mod_distrib) + text \Definition of \unat_arith\ tactic\ lemma unat_split: "P (unat x) \ (\n. of_nat n = x \ n < 2^LENGTH('a) \ P n)" for x :: "'a::len word" by (auto simp: unat_of_nat) lemma unat_split_asm: "P (unat x) \ (\n. of_nat n = x \ n < 2^LENGTH('a) \ \ P n)" for x :: "'a::len word" by (auto simp: unat_of_nat) lemmas of_nat_inverse = word_unat.Abs_inverse' [rotated, unfolded unats_def, simplified] lemmas unat_splits = unat_split unat_split_asm lemmas unat_arith_simps = word_le_nat_alt word_less_nat_alt word_unat.Rep_inject [symmetric] unat_sub_if' unat_plus_if' unat_div unat_mod \ \\unat_arith_tac\: tactic to reduce word arithmetic to \nat\, try to solve via \arith\\ ML \ fun unat_arith_simpset ctxt = ctxt addsimps @{thms unat_arith_simps} delsimps @{thms word_unat.Rep_inject} |> fold Splitter.add_split @{thms if_split_asm} |> fold Simplifier.add_cong @{thms power_False_cong} fun unat_arith_tacs ctxt = let fun arith_tac' n t = Arith_Data.arith_tac ctxt n t handle Cooper.COOPER _ => Seq.empty; in [ clarify_tac ctxt 1, full_simp_tac (unat_arith_simpset ctxt) 1, ALLGOALS (full_simp_tac (put_simpset HOL_ss ctxt |> fold Splitter.add_split @{thms unat_splits} |> fold Simplifier.add_cong @{thms power_False_cong})), rewrite_goals_tac ctxt @{thms word_size}, ALLGOALS (fn n => REPEAT (resolve_tac ctxt [allI, impI] n) THEN REPEAT (eresolve_tac ctxt [conjE] n) THEN REPEAT (dresolve_tac ctxt @{thms of_nat_inverse} n THEN assume_tac ctxt n)), TRYALL arith_tac' ] end fun unat_arith_tac ctxt = SELECT_GOAL (EVERY (unat_arith_tacs ctxt)) \ method_setup unat_arith = \Scan.succeed (SIMPLE_METHOD' o unat_arith_tac)\ "solving word arithmetic via natural numbers and arith" lemma no_plus_overflow_unat_size: "x \ x + y \ unat x + unat y < 2 ^ size x" for x y :: "'a::len word" unfolding word_size by unat_arith lemmas no_olen_add_nat = no_plus_overflow_unat_size [unfolded word_size] lemmas unat_plus_simple = trans [OF no_olen_add_nat unat_add_lem] lemma word_div_mult: "0 < y \ unat x * unat y < 2 ^ LENGTH('a) \ x * y div y = x" for x y :: "'a::len word" apply unat_arith apply clarsimp apply (subst unat_mult_lem [THEN iffD1]) apply auto done lemma div_lt': "i \ k div x \ unat i * unat x < 2 ^ LENGTH('a)" for i k x :: "'a::len word" apply unat_arith apply clarsimp apply (drule mult_le_mono1) apply (erule order_le_less_trans) - apply (rule xtr7 [OF unat_lt2p div_mult_le]) + apply (metis add_lessD1 div_mult_mod_eq unat_lt2p) done lemmas div_lt'' = order_less_imp_le [THEN div_lt'] lemma div_lt_mult: "i < k div x \ 0 < x \ i * x < k" for i k x :: "'a::len word" apply (frule div_lt'' [THEN unat_mult_lem [THEN iffD1]]) apply (simp add: unat_arith_simps) apply (drule (1) mult_less_mono1) apply (erule order_less_le_trans) - apply (rule div_mult_le) + apply auto done lemma div_le_mult: "i \ k div x \ 0 < x \ i * x \ k" for i k x :: "'a::len word" apply (frule div_lt' [THEN unat_mult_lem [THEN iffD1]]) apply (simp add: unat_arith_simps) apply (drule mult_le_mono1) apply (erule order_trans) - apply (rule div_mult_le) + apply auto done lemma div_lt_uint': "i \ k div x \ uint i * uint x < 2 ^ LENGTH('a)" for i k x :: "'a::len word" apply (unfold uint_nat) apply (drule div_lt') apply (metis of_nat_less_iff of_nat_mult of_nat_numeral of_nat_power) done lemmas div_lt_uint'' = order_less_imp_le [THEN div_lt_uint'] lemma word_le_exists': "x \ y \ \z. y = x + z \ uint x + uint z < 2 ^ LENGTH('a)" for x y z :: "'a::len word" - apply (rule exI) - apply (rule conjI) - apply (rule zadd_diff_inverse) - apply uint_arith - done - + by (metis add_diff_cancel_left' add_diff_eq uint_add_lem uint_plus_simple) + lemmas plus_minus_not_NULL = order_less_imp_le [THEN plus_minus_not_NULL_ab] lemmas plus_minus_no_overflow = order_less_imp_le [THEN plus_minus_no_overflow_ab] lemmas mcs = word_less_minus_cancel word_less_minus_mono_left word_le_minus_cancel word_le_minus_mono_left lemmas word_l_diffs = mcs [where y = "w + x", unfolded add_diff_cancel] for w x lemmas word_diff_ls = mcs [where z = "w + x", unfolded add_diff_cancel] for w x lemmas word_plus_mcs = word_diff_ls [where y = "v + x", unfolded add_diff_cancel] for v x lemmas le_unat_uoi = unat_le [THEN word_unat.Abs_inverse] lemmas thd = times_div_less_eq_dividend -lemmas uno_simps [THEN le_unat_uoi] = mod_le_divisor div_le_dividend dtle +lemmas uno_simps [THEN le_unat_uoi] = mod_le_divisor div_le_dividend lemma word_mod_div_equality: "(n div b) * b + (n mod b) = n" for n b :: "'a::len word" - apply (unfold word_less_nat_alt word_arith_nat_defs) - apply (cut_tac y="unat b" in gt_or_eq_0) - apply (erule disjE) - apply (simp only: div_mult_mod_eq uno_simps Word.word_unat.Rep_inverse) - apply simp - done + by (fact div_mult_mod_eq) lemma word_div_mult_le: "a div b * b \ a" for a b :: "'a::len word" - apply (unfold word_le_nat_alt word_arith_nat_defs) - apply (cut_tac y="unat b" in gt_or_eq_0) - apply (erule disjE) - apply (simp only: div_mult_le uno_simps Word.word_unat.Rep_inverse) - apply simp - done + by (metis div_le_mult mult_not_zero order.not_eq_order_implies_strict order_refl word_zero_le) lemma word_mod_less_divisor: "0 < n \ m mod n < n" for m n :: "'a::len word" - apply (simp only: word_less_nat_alt word_arith_nat_defs) - apply (auto simp: uno_simps) - done - + by (simp add: unat_arith_simps) + lemma word_of_int_power_hom: "word_of_int a ^ n = (word_of_int (a ^ n) :: 'a::len word)" by (induct n) (simp_all add: wi_hom_mult [symmetric]) lemma word_arith_power_alt: "a ^ n = (word_of_int (uint a ^ n) :: 'a::len word)" by (simp add : word_of_int_power_hom [symmetric]) lemma of_bl_length_less: "length x = k \ k < LENGTH('a) \ (of_bl x :: 'a::len word) < 2 ^ k" apply (unfold of_bl_def word_less_alt word_numeral_alt) apply safe apply (simp (no_asm) add: word_of_int_power_hom word_uint.eq_norm del: word_of_int_numeral) apply simp apply (subst mod_pos_pos_trivial) apply (rule bl_to_bin_ge0) apply (rule order_less_trans) apply (rule bl_to_bin_lt2p) apply simp apply (rule bl_to_bin_lt2p) done lemma unatSuc: "1 + n \ 0 \ unat (1 + n) = Suc (unat n)" for n :: "'a::len word" by unat_arith subsection \Cardinality, finiteness of set of words\ lemma inj_on_word_of_int: \inj_on (word_of_int :: int \ 'a word) {0..<2 ^ LENGTH('a::len)}\ by (rule inj_onI) (simp add: word.abs_eq_iff take_bit_eq_mod) lemma inj_uint: \inj uint\ by (rule injI) simp lemma range_uint: \range (uint :: 'a word \ int) = {0..<2 ^ LENGTH('a::len)}\ by transfer (auto simp add: bintr_lt2p range_bintrunc) lemma UNIV_eq: \(UNIV :: 'a word set) = word_of_int ` {0..<2 ^ LENGTH('a::len)}\ proof - have \uint ` (UNIV :: 'a word set) = uint ` (word_of_int :: int \ 'a word) ` {0..<2 ^ LENGTH('a::len)}\ by (simp add: range_uint image_image uint.abs_eq take_bit_eq_mod) then show ?thesis using inj_image_eq_iff [of \uint :: 'a word \ int\ \UNIV :: 'a word set\ \word_of_int ` {0..<2 ^ LENGTH('a)} :: 'a word set\, OF inj_uint] by simp qed lemma card_word: "CARD('a word) = 2 ^ LENGTH('a::len)" by (simp add: UNIV_eq card_image inj_on_word_of_int) lemma card_word_size: "CARD('a word) = 2 ^ size x" for x :: "'a::len word" unfolding word_size by (rule card_word) instance word :: (len) finite by standard (simp add: UNIV_eq) subsection \Bitwise Operations on Words\ lemma word_eq_rbl_eq: "x = y \ rev (to_bl x) = rev (to_bl y)" by simp lemmas bin_log_bintrs = bin_trunc_not bin_trunc_xor bin_trunc_and bin_trunc_or \ \following definitions require both arithmetic and bit-wise word operations\ \ \to get \word_no_log_defs\ from \word_log_defs\, using \bin_log_bintrs\\ lemmas wils1 = bin_log_bintrs [THEN word_ubin.norm_eq_iff [THEN iffD1], folded word_ubin.eq_norm, THEN eq_reflection] \ \the binary operations only\ (* BH: why is this needed? *) lemmas word_log_binary_defs = word_and_def word_or_def word_xor_def lemma word_wi_log_defs: "NOT (word_of_int a) = word_of_int (NOT a)" "word_of_int a AND word_of_int b = word_of_int (a AND b)" "word_of_int a OR word_of_int b = word_of_int (a OR b)" "word_of_int a XOR word_of_int b = word_of_int (a XOR b)" by (transfer, rule refl)+ lemma word_no_log_defs [simp]: "NOT (numeral a) = word_of_int (NOT (numeral a))" "NOT (- numeral a) = word_of_int (NOT (- numeral a))" "numeral a AND numeral b = word_of_int (numeral a AND numeral b)" "numeral a AND - numeral b = word_of_int (numeral a AND - numeral b)" "- numeral a AND numeral b = word_of_int (- numeral a AND numeral b)" "- numeral a AND - numeral b = word_of_int (- numeral a AND - numeral b)" "numeral a OR numeral b = word_of_int (numeral a OR numeral b)" "numeral a OR - numeral b = word_of_int (numeral a OR - numeral b)" "- numeral a OR numeral b = word_of_int (- numeral a OR numeral b)" "- numeral a OR - numeral b = word_of_int (- numeral a OR - numeral b)" "numeral a XOR numeral b = word_of_int (numeral a XOR numeral b)" "numeral a XOR - numeral b = word_of_int (numeral a XOR - numeral b)" "- numeral a XOR numeral b = word_of_int (- numeral a XOR numeral b)" "- numeral a XOR - numeral b = word_of_int (- numeral a XOR - numeral b)" by (transfer, rule refl)+ text \Special cases for when one of the arguments equals 1.\ lemma word_bitwise_1_simps [simp]: "NOT (1::'a::len word) = -2" "1 AND numeral b = word_of_int (1 AND numeral b)" "1 AND - numeral b = word_of_int (1 AND - numeral b)" "numeral a AND 1 = word_of_int (numeral a AND 1)" "- numeral a AND 1 = word_of_int (- numeral a AND 1)" "1 OR numeral b = word_of_int (1 OR numeral b)" "1 OR - numeral b = word_of_int (1 OR - numeral b)" "numeral a OR 1 = word_of_int (numeral a OR 1)" "- numeral a OR 1 = word_of_int (- numeral a OR 1)" "1 XOR numeral b = word_of_int (1 XOR numeral b)" "1 XOR - numeral b = word_of_int (1 XOR - numeral b)" "numeral a XOR 1 = word_of_int (numeral a XOR 1)" "- numeral a XOR 1 = word_of_int (- numeral a XOR 1)" by (transfer, simp)+ text \Special cases for when one of the arguments equals -1.\ lemma word_bitwise_m1_simps [simp]: "NOT (-1::'a::len word) = 0" "(-1::'a::len word) AND x = x" "x AND (-1::'a::len word) = x" "(-1::'a::len word) OR x = -1" "x OR (-1::'a::len word) = -1" " (-1::'a::len word) XOR x = NOT x" "x XOR (-1::'a::len word) = NOT x" by (transfer, simp)+ lemma uint_and: \uint (x AND y) = uint x AND uint y\ by transfer simp lemma uint_or: \uint (x OR y) = uint x OR uint y\ by transfer simp lemma uint_xor: \uint (x XOR y) = uint x XOR uint y\ by transfer simp lemma test_bit_wi [simp]: "(word_of_int x :: 'a::len word) !! n \ n < LENGTH('a) \ bin_nth x n" by (simp add: word_test_bit_def word_ubin.eq_norm nth_bintr) lemma word_test_bit_transfer [transfer_rule]: "(rel_fun pcr_word (rel_fun (=) (=))) (\x n. n < LENGTH('a) \ bin_nth x n) (test_bit :: 'a::len word \ _)" unfolding rel_fun_def word.pcr_cr_eq cr_word_def by simp lemma word_ops_nth_size: "n < size x \ (x OR y) !! n = (x !! n | y !! n) \ (x AND y) !! n = (x !! n \ y !! n) \ (x XOR y) !! n = (x !! n \ y !! n) \ (NOT x) !! n = (\ x !! n)" for x :: "'a::len word" unfolding word_size by transfer (simp add: bin_nth_ops) lemma word_ao_nth: "(x OR y) !! n = (x !! n | y !! n) \ (x AND y) !! n = (x !! n \ y !! n)" for x :: "'a::len word" by transfer (auto simp add: bin_nth_ops) lemma test_bit_numeral [simp]: "(numeral w :: 'a::len word) !! n \ n < LENGTH('a) \ bin_nth (numeral w) n" by transfer (rule refl) lemma test_bit_neg_numeral [simp]: "(- numeral w :: 'a::len word) !! n \ n < LENGTH('a) \ bin_nth (- numeral w) n" by transfer (rule refl) lemma test_bit_1 [simp]: "(1 :: 'a::len word) !! n \ n = 0" by transfer auto lemma nth_0 [simp]: "\ (0 :: 'a::len word) !! n" by transfer simp lemma nth_minus1 [simp]: "(-1 :: 'a::len word) !! n \ n < LENGTH('a)" by transfer simp \ \get from commutativity, associativity etc of \int_and\ etc to same for \word_and etc\\ lemmas bwsimps = wi_hom_add word_wi_log_defs lemma word_bw_assocs: "(x AND y) AND z = x AND y AND z" "(x OR y) OR z = x OR y OR z" "(x XOR y) XOR z = x XOR y XOR z" for x :: "'a::len word" by (auto simp: word_eq_iff word_ops_nth_size [unfolded word_size]) lemma word_bw_comms: "x AND y = y AND x" "x OR y = y OR x" "x XOR y = y XOR x" for x :: "'a::len word" by (auto simp: word_eq_iff word_ops_nth_size [unfolded word_size]) lemma word_bw_lcs: "y AND x AND z = x AND y AND z" "y OR x OR z = x OR y OR z" "y XOR x XOR z = x XOR y XOR z" for x :: "'a::len word" by (auto simp: word_eq_iff word_ops_nth_size [unfolded word_size]) lemma word_log_esimps: "x AND 0 = 0" "x AND -1 = x" "x OR 0 = x" "x OR -1 = -1" "x XOR 0 = x" "x XOR -1 = NOT x" "0 AND x = 0" "-1 AND x = x" "0 OR x = x" "-1 OR x = -1" "0 XOR x = x" "-1 XOR x = NOT x" for x :: "'a::len word" by simp_all lemma word_not_dist: "NOT (x OR y) = NOT x AND NOT y" "NOT (x AND y) = NOT x OR NOT y" for x :: "'a::len word" by simp_all lemma word_bw_same: "x AND x = x" "x OR x = x" "x XOR x = 0" for x :: "'a::len word" by simp_all lemma word_ao_absorbs [simp]: "x AND (y OR x) = x" "x OR y AND x = x" "x AND (x OR y) = x" "y AND x OR x = x" "(y OR x) AND x = x" "x OR x AND y = x" "(x OR y) AND x = x" "x AND y OR x = x" for x :: "'a::len word" by (auto simp: word_eq_iff word_ops_nth_size [unfolded word_size]) lemma word_not_not [simp]: "NOT (NOT x) = x" for x :: "'a::len word" by simp lemma word_ao_dist: "(x OR y) AND z = x AND z OR y AND z" for x :: "'a::len word" by (auto simp: word_eq_iff word_ops_nth_size [unfolded word_size]) lemma word_oa_dist: "x AND y OR z = (x OR z) AND (y OR z)" for x :: "'a::len word" by (auto simp: word_eq_iff word_ops_nth_size [unfolded word_size]) lemma word_add_not [simp]: "x + NOT x = -1" for x :: "'a::len word" by transfer (simp add: bin_add_not) lemma word_plus_and_or [simp]: "(x AND y) + (x OR y) = x + y" for x :: "'a::len word" by transfer (simp add: plus_and_or) lemma leoa: "w = x OR y \ y = w AND y" for x :: "'a::len word" by auto lemma leao: "w' = x' AND y' \ x' = x' OR w'" for x' :: "'a::len word" by auto lemma word_ao_equiv: "w = w OR w' \ w' = w AND w'" for w w' :: "'a::len word" by (auto intro: leoa leao) lemma le_word_or2: "x \ x OR y" for x y :: "'a::len word" by (auto simp: word_le_def uint_or intro: le_int_or) -lemmas le_word_or1 = xtr3 [OF word_bw_comms (2) le_word_or2] -lemmas word_and_le1 = xtr3 [OF word_ao_absorbs (4) [symmetric] le_word_or2] -lemmas word_and_le2 = xtr3 [OF word_ao_absorbs (8) [symmetric] le_word_or2] +lemmas le_word_or1 = xtrans(3) [OF word_bw_comms (2) le_word_or2] +lemmas word_and_le1 = xtrans(3) [OF word_ao_absorbs (4) [symmetric] le_word_or2] +lemmas word_and_le2 = xtrans(3) [OF word_ao_absorbs (8) [symmetric] le_word_or2] lemma bl_word_not: "to_bl (NOT w) = map Not (to_bl w)" unfolding to_bl_def word_log_defs bl_not_bin by (simp add: word_ubin.eq_norm) lemma bl_word_xor: "to_bl (v XOR w) = map2 (\) (to_bl v) (to_bl w)" unfolding to_bl_def word_log_defs bl_xor_bin by (simp add: word_ubin.eq_norm) lemma bl_word_or: "to_bl (v OR w) = map2 (\) (to_bl v) (to_bl w)" unfolding to_bl_def word_log_defs bl_or_bin by (simp add: word_ubin.eq_norm) lemma bl_word_and: "to_bl (v AND w) = map2 (\) (to_bl v) (to_bl w)" unfolding to_bl_def word_log_defs bl_and_bin by (simp add: word_ubin.eq_norm) lemma word_lsb_alt: "lsb w = test_bit w 0" for w :: "'a::len word" by (auto simp: word_test_bit_def word_lsb_def) lemma word_lsb_1_0 [simp]: "lsb (1::'a::len word) \ \ lsb (0::'b::len word)" unfolding word_lsb_def uint_eq_0 uint_1 by simp lemma word_lsb_last: "lsb w = last (to_bl w)" for w :: "'a::len word" apply (unfold word_lsb_def uint_bl bin_to_bl_def) apply (rule_tac bin="uint w" in bin_exhaust) apply (cases "size w") apply auto apply (auto simp add: bin_to_bl_aux_alt) done lemma word_lsb_int: "lsb w \ uint w mod 2 = 1" by (auto simp: word_lsb_def bin_last_def) lemma word_msb_sint: "msb w \ sint w < 0" by (simp only: word_msb_def sign_Min_lt_0) lemma msb_word_of_int: "msb (word_of_int x::'a::len word) = bin_nth x (LENGTH('a) - 1)" by (simp add: word_msb_def word_sbin.eq_norm bin_sign_lem) lemma word_msb_numeral [simp]: "msb (numeral w::'a::len word) = bin_nth (numeral w) (LENGTH('a) - 1)" unfolding word_numeral_alt by (rule msb_word_of_int) lemma word_msb_neg_numeral [simp]: "msb (- numeral w::'a::len word) = bin_nth (- numeral w) (LENGTH('a) - 1)" unfolding word_neg_numeral_alt by (rule msb_word_of_int) lemma word_msb_0 [simp]: "\ msb (0::'a::len word)" by (simp add: word_msb_def) lemma word_msb_1 [simp]: "msb (1::'a::len word) \ LENGTH('a) = 1" unfolding word_1_wi msb_word_of_int eq_iff [where 'a=nat] by (simp add: Suc_le_eq) lemma word_msb_nth: "msb w = bin_nth (uint w) (LENGTH('a) - 1)" for w :: "'a::len word" by (simp add: word_msb_def sint_uint bin_sign_lem) lemma word_msb_alt: "msb w = hd (to_bl w)" for w :: "'a::len word" apply (unfold word_msb_nth uint_bl) apply (subst hd_conv_nth) apply (rule length_greater_0_conv [THEN iffD1]) apply simp apply (simp add : nth_bin_to_bl word_size) done lemma word_set_nth [simp]: "set_bit w n (test_bit w n) = w" for w :: "'a::len word" by (auto simp: word_test_bit_def word_set_bit_def) lemma bin_nth_uint': "bin_nth (uint w) n \ rev (bin_to_bl (size w) (uint w)) ! n \ n < size w" apply (unfold word_size) apply (safe elim!: bin_nth_uint_imp) apply (frule bin_nth_uint_imp) apply (fast dest!: bin_nth_bl)+ done lemmas bin_nth_uint = bin_nth_uint' [unfolded word_size] lemma test_bit_bl: "w !! n \ rev (to_bl w) ! n \ n < size w" unfolding to_bl_def word_test_bit_def word_size by (rule bin_nth_uint) lemma to_bl_nth: "n < size w \ to_bl w ! n = w !! (size w - Suc n)" - apply (unfold test_bit_bl) - apply clarsimp - apply (rule trans) - apply (rule nth_rev_alt) - apply (auto simp add: word_size) - done + by (simp add: word_size rev_nth test_bit_bl) lemma map_bit_interval_eq: \map (bit w) [0.. for w :: \'a::len word\ proof (rule nth_equalityI) show \length (map (bit w) [0.. by simp fix m assume \m < length (map (bit w) [0.. then have \m < n\ by simp then have \bit w m \ takefill False n (rev (to_bl w)) ! m\ by (auto simp add: nth_takefill not_less rev_nth to_bl_nth word_size test_bit_word_eq dest: bit_imp_le_length) with \m < n \show \map (bit w) [0.. takefill False n (rev (to_bl w)) ! m\ by simp qed lemma to_bl_unfold: \to_bl w = rev (map (bit w) [0.. for w :: \'a::len word\ by (simp add: map_bit_interval_eq takefill_bintrunc to_bl_def flip: bin_to_bl_def) lemma nth_rev_to_bl: \rev (to_bl w) ! n \ bit w n\ if \n < LENGTH('a)\ for w :: \'a::len word\ using that by (simp add: to_bl_unfold) lemma nth_to_bl: \to_bl w ! n \ bit w (LENGTH('a) - Suc n)\ if \n < LENGTH('a)\ for w :: \'a::len word\ using that by (simp add: to_bl_unfold rev_nth) lemma test_bit_set: "(set_bit w n x) !! n \ n < size w \ x" for w :: "'a::len word" by (auto simp: word_size word_test_bit_def word_set_bit_def word_ubin.eq_norm nth_bintr) lemma test_bit_set_gen: "test_bit (set_bit w n x) m = (if m = n then n < size w \ x else test_bit w m)" for w :: "'a::len word" apply (unfold word_size word_test_bit_def word_set_bit_def) apply (clarsimp simp add: word_ubin.eq_norm nth_bintr bin_nth_sc_gen) apply (auto elim!: test_bit_size [unfolded word_size] simp add: word_test_bit_def [symmetric]) done lemma of_bl_rep_False: "of_bl (replicate n False @ bs) = of_bl bs" by (auto simp: of_bl_def bl_to_bin_rep_F) lemma bit_word_reverse_iff: \bit (word_reverse w) n \ n < LENGTH('a) \ bit w (LENGTH('a) - Suc n)\ for w :: \'a::len word\ by (cases \n < LENGTH('a)\) (simp_all add: word_reverse_def bit_of_bl_iff nth_to_bl) lemma bit_slice1_iff: \bit (slice1 m w :: 'b::len word) n \ m - LENGTH('a) \ n \ n < min LENGTH('b) m \ bit w (n + (LENGTH('a) - m) - (m - LENGTH('a)))\ for w :: \'a::len word\ by (cases \n + (LENGTH('a) - m) - (m - LENGTH('a)) < LENGTH('a)\) (auto simp add: slice1_def bit_of_bl_iff takefill_alt rev_take nth_append not_less nth_rev_to_bl ac_simps) lemma bit_revcast_iff: \bit (revcast w :: 'b::len word) n \ LENGTH('b) - LENGTH('a) \ n \ n < LENGTH('b) \ bit w (n + (LENGTH('a) - LENGTH('b)) - (LENGTH('b) - LENGTH('a)))\ for w :: \'a::len word\ by (simp add: revcast_eq bit_slice1_iff) lemma bit_slice_iff: \bit (slice m w :: 'b::len word) n \ n < min LENGTH('b) (LENGTH('a) - m) \ bit w (n + LENGTH('a) - (LENGTH('a) - m))\ for w :: \'a::len word\ by (simp add: slice_def word_size bit_slice1_iff) lemma msb_nth: "msb w = w !! (LENGTH('a) - 1)" for w :: "'a::len word" by (simp add: word_msb_nth word_test_bit_def) lemmas msb0 = len_gt_0 [THEN diff_Suc_less, THEN word_ops_nth_size [unfolded word_size]] lemmas msb1 = msb0 [where i = 0] lemmas word_ops_msb = msb1 [unfolded msb_nth [symmetric, unfolded One_nat_def]] lemmas lsb0 = len_gt_0 [THEN word_ops_nth_size [unfolded word_size]] lemmas word_ops_lsb = lsb0 [unfolded word_lsb_alt] lemma word_set_set_same [simp]: "set_bit (set_bit w n x) n y = set_bit w n y" for w :: "'a::len word" by (rule word_eqI) (simp add : test_bit_set_gen word_size) lemma word_set_set_diff: fixes w :: "'a::len word" assumes "m \ n" shows "set_bit (set_bit w m x) n y = set_bit (set_bit w n y) m x" by (rule word_eqI) (auto simp: test_bit_set_gen word_size assms) lemma nth_sint: fixes w :: "'a::len word" defines "l \ LENGTH('a)" shows "bin_nth (sint w) n = (if n < l - 1 then w !! n else w !! (l - 1))" unfolding sint_uint l_def by (auto simp: nth_sbintr word_test_bit_def [symmetric]) lemma word_lsb_numeral [simp]: "lsb (numeral bin :: 'a::len word) \ bin_last (numeral bin)" unfolding word_lsb_alt test_bit_numeral by simp lemma word_lsb_neg_numeral [simp]: "lsb (- numeral bin :: 'a::len word) \ bin_last (- numeral bin)" by (simp add: word_lsb_alt) lemma set_bit_word_of_int: "set_bit (word_of_int x) n b = word_of_int (bin_sc n b x)" unfolding word_set_bit_def by (rule word_eqI)(simp add: word_size bin_nth_sc_gen word_ubin.eq_norm nth_bintr) lemma word_set_numeral [simp]: "set_bit (numeral bin::'a::len word) n b = word_of_int (bin_sc n b (numeral bin))" unfolding word_numeral_alt by (rule set_bit_word_of_int) lemma word_set_neg_numeral [simp]: "set_bit (- numeral bin::'a::len word) n b = word_of_int (bin_sc n b (- numeral bin))" unfolding word_neg_numeral_alt by (rule set_bit_word_of_int) lemma word_set_bit_0 [simp]: "set_bit 0 n b = word_of_int (bin_sc n b 0)" unfolding word_0_wi by (rule set_bit_word_of_int) lemma word_set_bit_1 [simp]: "set_bit 1 n b = word_of_int (bin_sc n b 1)" unfolding word_1_wi by (rule set_bit_word_of_int) lemma setBit_no [simp]: "setBit (numeral bin) n = word_of_int (bin_sc n True (numeral bin))" by (simp add: setBit_def) lemma clearBit_no [simp]: "clearBit (numeral bin) n = word_of_int (bin_sc n False (numeral bin))" by (simp add: clearBit_def) lemma to_bl_n1 [simp]: "to_bl (-1::'a::len word) = replicate (LENGTH('a)) True" apply (rule word_bl.Abs_inverse') apply simp apply (rule word_eqI) apply (clarsimp simp add: word_size) apply (auto simp add: word_bl.Abs_inverse test_bit_bl word_size) done lemma word_msb_n1 [simp]: "msb (-1::'a::len word)" unfolding word_msb_alt to_bl_n1 by simp lemma word_set_nth_iff: "set_bit w n b = w \ w !! n = b \ n \ size w" for w :: "'a::len word" apply (rule iffI) apply (rule disjCI) apply (drule word_eqD) apply (erule sym [THEN trans]) apply (simp add: test_bit_set) apply (erule disjE) apply clarsimp apply (rule word_eqI) apply (clarsimp simp add : test_bit_set_gen) apply (drule test_bit_size) apply force done lemma test_bit_2p: "(word_of_int (2 ^ n)::'a::len word) !! m \ m = n \ m < LENGTH('a)" by (auto simp: word_test_bit_def word_ubin.eq_norm nth_bintr nth_2p_bin) lemma nth_w2p: "((2::'a::len word) ^ n) !! m \ m = n \ m < LENGTH('a::len)" by (simp add: test_bit_2p [symmetric] word_of_int [symmetric]) lemma uint_2p: "(0::'a::len word) < 2 ^ n \ uint (2 ^ n::'a::len word) = 2 ^ n" apply (unfold word_arith_power_alt) apply (case_tac "LENGTH('a)") apply clarsimp apply (case_tac "nat") apply clarsimp apply (case_tac "n") apply clarsimp apply clarsimp apply (drule word_gt_0 [THEN iffD1]) apply (safe intro!: word_eqI) apply (auto simp add: nth_2p_bin) apply (erule notE) apply (simp (no_asm_use) add: uint_word_of_int word_size) apply (subst mod_pos_pos_trivial) apply simp apply (rule power_strict_increasing) apply simp_all done lemma word_of_int_2p: "(word_of_int (2 ^ n) :: 'a::len word) = 2 ^ n" by (induct n) (simp_all add: wi_hom_syms) lemma bang_is_le: "x !! m \ 2 ^ m \ x" for x :: "'a::len word" - apply (rule xtr3) + apply (rule xtrans(3)) apply (rule_tac [2] y = "x" in le_word_or2) apply (rule word_eqI) apply (auto simp add: word_ao_nth nth_w2p word_size) done lemma word_clr_le: "w \ set_bit w n False" for w :: "'a::len word" apply (unfold word_set_bit_def word_le_def word_ubin.eq_norm) apply (rule order_trans) apply (rule bintr_bin_clr_le) apply simp done lemma word_set_ge: "w \ set_bit w n True" for w :: "'a::len word" apply (unfold word_set_bit_def word_le_def word_ubin.eq_norm) apply (rule order_trans [OF _ bintr_bin_set_ge]) apply simp done lemma set_bit_beyond: "size x \ n \ set_bit x n b = x" for x :: "'a :: len word" by (auto intro: word_eqI simp add: test_bit_set_gen word_size) lemma rbl_word_or: "rev (to_bl (x OR y)) = map2 (\) (rev (to_bl x)) (rev (to_bl y))" by (simp add: zip_rev bl_word_or rev_map) lemma rbl_word_and: "rev (to_bl (x AND y)) = map2 (\) (rev (to_bl x)) (rev (to_bl y))" by (simp add: zip_rev bl_word_and rev_map) lemma rbl_word_xor: "rev (to_bl (x XOR y)) = map2 (\) (rev (to_bl x)) (rev (to_bl y))" by (simp add: zip_rev bl_word_xor rev_map) lemma rbl_word_not: "rev (to_bl (NOT x)) = map Not (rev (to_bl x))" by (simp add: bl_word_not rev_map) subsection \Bit comprehension\ instantiation word :: (len) bit_comprehension begin definition word_set_bits_def: "(BITS n. f n) = of_bl (bl_of_nth LENGTH('a) f)" instance .. end lemma bit_set_bits_word_iff: \bit (set_bits P :: 'a::len word) n \ n < LENGTH('a) \ P n\ by (auto simp add: word_set_bits_def bit_of_bl_iff) lemmas of_nth_def = word_set_bits_def (* FIXME duplicate *) lemma td_ext_nth [OF refl refl refl, unfolded word_size]: "n = size w \ ofn = set_bits \ [w, ofn g] = l \ td_ext test_bit ofn {f. \i. f i \ i < n} (\h i. h i \ i < n)" for w :: "'a::len word" apply (unfold word_size td_ext_def') apply safe apply (rule_tac [3] ext) apply (rule_tac [4] ext) apply (unfold word_size of_nth_def test_bit_bl) apply safe defer apply (clarsimp simp: word_bl.Abs_inverse)+ apply (rule word_bl.Rep_inverse') apply (rule sym [THEN trans]) apply (rule bl_of_nth_nth) apply simp apply (rule bl_of_nth_inj) apply (clarsimp simp add : test_bit_bl word_size) done interpretation test_bit: td_ext "(!!) :: 'a::len word \ nat \ bool" set_bits "{f. \i. f i \ i < LENGTH('a::len)}" "(\h i. h i \ i < LENGTH('a::len))" by (rule td_ext_nth) lemmas td_nth = test_bit.td_thm lemma set_bits_K_False [simp]: "set_bits (\_. False) = (0 :: 'a :: len word)" by (rule word_eqI) (simp add: test_bit.eq_norm) subsection \Shifting, Rotating, and Splitting Words\ lemma shiftl1_wi [simp]: "shiftl1 (word_of_int w) = word_of_int (2 * w)" unfolding shiftl1_def apply (simp add: word_ubin.norm_eq_iff [symmetric] word_ubin.eq_norm) apply (simp add: mod_mult_right_eq take_bit_eq_mod) done lemma shiftl1_numeral [simp]: "shiftl1 (numeral w) = numeral (Num.Bit0 w)" unfolding word_numeral_alt shiftl1_wi by simp lemma shiftl1_neg_numeral [simp]: "shiftl1 (- numeral w) = - numeral (Num.Bit0 w)" unfolding word_neg_numeral_alt shiftl1_wi by simp lemma shiftl1_0 [simp] : "shiftl1 0 = 0" by (simp add: shiftl1_def) lemma shiftl1_def_u: "shiftl1 w = word_of_int (2 * uint w)" - by (simp only: shiftl1_def) (* FIXME: duplicate *) + by (fact shiftl1_def) lemma shiftl1_def_s: "shiftl1 w = word_of_int (2 * sint w)" by (simp add: shiftl1_def wi_hom_syms) lemma shiftr1_0 [simp]: "shiftr1 0 = 0" by (simp add: shiftr1_def) lemma sshiftr1_0 [simp]: "sshiftr1 0 = 0" by (simp add: sshiftr1_def) lemma sshiftr1_n1 [simp]: "sshiftr1 (- 1) = - 1" by (simp add: sshiftr1_def) lemma shiftl_0 [simp]: "(0::'a::len word) << n = 0" by (induct n) (auto simp: shiftl_def) lemma shiftr_0 [simp]: "(0::'a::len word) >> n = 0" by (induct n) (auto simp: shiftr_def) lemma sshiftr_0 [simp]: "0 >>> n = 0" by (induct n) (auto simp: sshiftr_def) lemma sshiftr_n1 [simp]: "-1 >>> n = -1" by (induct n) (auto simp: sshiftr_def) lemma nth_shiftl1: "shiftl1 w !! n \ n < size w \ n > 0 \ w !! (n - 1)" apply (unfold shiftl1_def word_test_bit_def) apply (simp add: nth_bintr word_ubin.eq_norm word_size) apply (cases n) apply (simp_all add: bit_Suc) done lemma nth_shiftl': "(w << m) !! n \ n < size w \ n >= m \ w !! (n - m)" for w :: "'a::len word" apply (unfold shiftl_def) apply (induct m arbitrary: n) apply (force elim!: test_bit_size) apply (clarsimp simp add : nth_shiftl1 word_size) apply arith done lemmas nth_shiftl = nth_shiftl' [unfolded word_size] lemma nth_shiftr1: "shiftr1 w !! n = w !! Suc n" apply (auto simp add: shiftr1_def word_test_bit_def word_ubin.eq_norm bit_take_bit_iff bit_Suc) apply (metis (no_types, hide_lams) add_Suc_right add_diff_cancel_left' bit_Suc diff_is_0_eq' le_Suc_ex less_imp_le linorder_not_le test_bit_bin word_test_bit_def) done lemma nth_shiftr: "(w >> m) !! n = w !! (n + m)" for w :: "'a::len word" apply (unfold shiftr_def) apply (induct "m" arbitrary: n) apply (auto simp add: nth_shiftr1) done text \ see paper page 10, (1), (2), \shiftr1_def\ is of the form of (1), where \f\ (ie \bin_rest\) takes normal arguments to normal results, thus we get (2) from (1) \ lemma uint_shiftr1: "uint (shiftr1 w) = bin_rest (uint w)" apply (unfold shiftr1_def word_ubin.eq_norm bin_rest_trunc_i) apply (subst bintr_uint [symmetric, OF order_refl]) apply (simp only : bintrunc_bintrunc_l) apply simp done lemma bit_sshiftr1_iff: \bit (sshiftr1 w) n \ bit w (if n = LENGTH('a) - 1 then LENGTH('a) - 1 else Suc n)\ for w :: \'a::len word\ apply (cases \LENGTH('a)\) apply simp apply (simp add: sshiftr1_def bit_word_of_int_iff bit_sint_iff flip: bit_Suc) apply transfer apply auto done lemma bit_sshiftr_word_iff: \bit (w >>> m) n \ bit w (if LENGTH('a) - m \ n \ n < LENGTH('a) then LENGTH('a) - 1 else (m + n))\ for w :: \'a::len word\ apply (cases \LENGTH('a)\) apply simp apply (simp only:) apply (induction m arbitrary: n) apply (auto simp add: sshiftr_def bit_sshiftr1_iff not_le less_diff_conv) done lemma nth_sshiftr1: "sshiftr1 w !! n = (if n = size w - 1 then w !! n else w !! Suc n)" apply (unfold sshiftr1_def word_test_bit_def) apply (simp add: nth_bintr word_ubin.eq_norm bit_Suc [symmetric] word_size) apply (simp add: nth_bintr uint_sint) apply (auto simp add: bin_nth_sint) done lemma nth_sshiftr [rule_format] : "\n. sshiftr w m !! n = (n < size w \ (if n + m \ size w then w !! (size w - 1) else w !! (n + m)))" apply (unfold sshiftr_def) apply (induct_tac m) apply (simp add: test_bit_bl) apply (clarsimp simp add: nth_sshiftr1 word_size) apply safe apply arith apply arith apply (erule thin_rl) apply (case_tac n) apply safe apply simp apply simp apply (erule thin_rl) apply (case_tac n) apply safe apply simp apply simp apply arith+ done lemma shiftr1_div_2: "uint (shiftr1 w) = uint w div 2" apply (unfold shiftr1_def) apply (rule word_uint.Abs_inverse) apply (simp add: uints_num pos_imp_zdiv_nonneg_iff) - apply (rule xtr7) - prefer 2 - apply (rule zdiv_le_dividend) - apply auto + apply (metis uint_lt2p uint_shiftr1) done lemma sshiftr1_div_2: "sint (sshiftr1 w) = sint w div 2" apply (unfold sshiftr1_def) apply (simp add: word_sbin.eq_norm) apply (rule trans) defer apply (subst word_sbin.norm_Rep [symmetric]) apply (rule refl) apply (subst word_sbin.norm_Rep [symmetric]) apply (unfold One_nat_def) apply (rule sbintrunc_rest) done lemma shiftr_div_2n: "uint (shiftr w n) = uint w div 2 ^ n" apply (unfold shiftr_def) apply (induct n) apply simp apply (simp add: shiftr1_div_2 mult.commute zdiv_zmult2_eq [symmetric]) done lemma sshiftr_div_2n: "sint (sshiftr w n) = sint w div 2 ^ n" apply (unfold sshiftr_def) apply (induct n) apply simp apply (simp add: sshiftr1_div_2 mult.commute zdiv_zmult2_eq [symmetric]) done lemma bit_bshiftr1_iff: \bit (bshiftr1 b w) n \ b \ n = LENGTH('a) - 1 \ bit w (Suc n)\ for w :: \'a::len word\ apply (cases \LENGTH('a)\) apply simp apply (simp add: bshiftr1_def bit_of_bl_iff nth_append not_less rev_nth nth_butlast nth_to_bl) apply (use bit_imp_le_length in fastforce) done subsubsection \shift functions in terms of lists of bools\ -lemmas bshiftr1_numeral [simp] = - bshiftr1_def [where w="numeral w", unfolded to_bl_numeral] for w +lemma bshiftr1_numeral [simp]: + \bshiftr1 b (numeral w :: 'a word) = of_bl (b # butlast (bin_to_bl LENGTH('a::len) (numeral w)))\ + by (simp add: bshiftr1_def) lemma bshiftr1_bl: "to_bl (bshiftr1 b w) = b # butlast (to_bl w)" unfolding bshiftr1_def by (rule word_bl.Abs_inverse) simp lemma shiftl1_of_bl: "shiftl1 (of_bl bl) = of_bl (bl @ [False])" by (simp add: of_bl_def bl_to_bin_append) lemma shiftl1_bl: "shiftl1 w = of_bl (to_bl w @ [False])" for w :: "'a::len word" proof - have "shiftl1 w = shiftl1 (of_bl (to_bl w))" by simp also have "\ = of_bl (to_bl w @ [False])" by (rule shiftl1_of_bl) finally show ?thesis . qed lemma bl_shiftl1: "to_bl (shiftl1 w) = tl (to_bl w) @ [False]" for w :: "'a::len word" by (simp add: shiftl1_bl word_rep_drop drop_Suc drop_Cons') (fast intro!: Suc_leI) \ \Generalized version of \bl_shiftl1\. Maybe this one should replace it?\ lemma bl_shiftl1': "to_bl (shiftl1 w) = tl (to_bl w @ [False])" by (simp add: shiftl1_bl word_rep_drop drop_Suc del: drop_append) lemma shiftr1_bl: "shiftr1 w = of_bl (butlast (to_bl w))" apply (unfold shiftr1_def uint_bl of_bl_def) apply (simp add: butlast_rest_bin word_size) apply (simp add: bin_rest_trunc [symmetric, unfolded One_nat_def]) done lemma bl_shiftr1: "to_bl (shiftr1 w) = False # butlast (to_bl w)" for w :: "'a::len word" by (simp add: shiftr1_bl word_rep_drop len_gt_0 [THEN Suc_leI]) \ \Generalized version of \bl_shiftr1\. Maybe this one should replace it?\ lemma bl_shiftr1': "to_bl (shiftr1 w) = butlast (False # to_bl w)" apply (rule word_bl.Abs_inverse') apply (simp del: butlast.simps) apply (simp add: shiftr1_bl of_bl_def) done lemma shiftl1_rev: "shiftl1 w = word_reverse (shiftr1 (word_reverse w))" apply (unfold word_reverse_def) apply (rule word_bl.Rep_inverse' [symmetric]) apply (simp add: bl_shiftl1' bl_shiftr1' word_bl.Abs_inverse) done lemma shiftl_rev: "shiftl w n = word_reverse (shiftr (word_reverse w) n)" by (induct n) (auto simp add: shiftl_def shiftr_def shiftl1_rev) lemma rev_shiftl: "word_reverse w << n = word_reverse (w >> n)" by (simp add: shiftl_rev) lemma shiftr_rev: "w >> n = word_reverse (word_reverse w << n)" by (simp add: rev_shiftl) lemma rev_shiftr: "word_reverse w >> n = word_reverse (w << n)" by (simp add: shiftr_rev) lemma bl_sshiftr1: "to_bl (sshiftr1 w) = hd (to_bl w) # butlast (to_bl w)" for w :: "'a::len word" apply (unfold sshiftr1_def uint_bl word_size) apply (simp add: butlast_rest_bin word_ubin.eq_norm) apply (simp add: sint_uint) apply (rule nth_equalityI) apply clarsimp apply clarsimp apply (case_tac i) apply (simp_all add: hd_conv_nth length_0_conv [symmetric] nth_bin_to_bl bit_Suc [symmetric] nth_sbintr) apply force apply (rule impI) apply (rule_tac f = "bin_nth (uint w)" in arg_cong) apply simp done lemma drop_shiftr: "drop n (to_bl (w >> n)) = take (size w - n) (to_bl w)" for w :: "'a::len word" apply (unfold shiftr_def) apply (induct n) prefer 2 apply (simp add: drop_Suc bl_shiftr1 butlast_drop [symmetric]) apply (rule butlast_take [THEN trans]) apply (auto simp: word_size) done lemma drop_sshiftr: "drop n (to_bl (w >>> n)) = take (size w - n) (to_bl w)" for w :: "'a::len word" apply (unfold sshiftr_def) apply (induct n) prefer 2 apply (simp add: drop_Suc bl_sshiftr1 butlast_drop [symmetric]) apply (rule butlast_take [THEN trans]) apply (auto simp: word_size) done lemma take_shiftr: "n \ size w \ take n (to_bl (w >> n)) = replicate n False" apply (unfold shiftr_def) apply (induct n) prefer 2 apply (simp add: bl_shiftr1' length_0_conv [symmetric] word_size) apply (rule take_butlast [THEN trans]) apply (auto simp: word_size) done lemma take_sshiftr' [rule_format] : "n \ size w \ hd (to_bl (w >>> n)) = hd (to_bl w) \ take n (to_bl (w >>> n)) = replicate n (hd (to_bl w))" for w :: "'a::len word" apply (unfold sshiftr_def) apply (induct n) prefer 2 apply (simp add: bl_sshiftr1) apply (rule impI) apply (rule take_butlast [THEN trans]) apply (auto simp: word_size) done lemmas hd_sshiftr = take_sshiftr' [THEN conjunct1] lemmas take_sshiftr = take_sshiftr' [THEN conjunct2] lemma atd_lem: "take n xs = t \ drop n xs = d \ xs = t @ d" by (auto intro: append_take_drop_id [symmetric]) lemmas bl_shiftr = atd_lem [OF take_shiftr drop_shiftr] lemmas bl_sshiftr = atd_lem [OF take_sshiftr drop_sshiftr] lemma shiftl_of_bl: "of_bl bl << n = of_bl (bl @ replicate n False)" by (induct n) (auto simp: shiftl_def shiftl1_of_bl replicate_app_Cons_same) lemma shiftl_bl: "w << n = of_bl (to_bl w @ replicate n False)" for w :: "'a::len word" proof - have "w << n = of_bl (to_bl w) << n" by simp also have "\ = of_bl (to_bl w @ replicate n False)" by (rule shiftl_of_bl) finally show ?thesis . qed -lemmas shiftl_numeral [simp] = shiftl_def [where w="numeral w"] for w +lemma shiftl_numeral [simp]: + \numeral k << numeral l = (push_bit (numeral l) (numeral k) :: 'a::len word)\ + by (fact shiftl_word_eq) lemma bl_shiftl: "to_bl (w << n) = drop n (to_bl w) @ replicate (min (size w) n) False" by (simp add: shiftl_bl word_rep_drop word_size) lemma shiftl_zero_size: "size x \ n \ x << n = 0" for x :: "'a::len word" apply (unfold word_size) apply (rule word_eqI) apply (clarsimp simp add: shiftl_bl word_size test_bit_of_bl nth_append) done \ \note -- the following results use \'a::len word < number_ring\\ lemma shiftl1_2t: "shiftl1 w = 2 * w" for w :: "'a::len word" by (simp add: shiftl1_def wi_hom_mult [symmetric]) lemma shiftl1_p: "shiftl1 w = w + w" for w :: "'a::len word" by (simp add: shiftl1_2t) lemma shiftl_t2n: "shiftl w n = 2 ^ n * w" for w :: "'a::len word" by (induct n) (auto simp: shiftl_def shiftl1_2t) lemma shiftr1_bintr [simp]: "(shiftr1 (numeral w) :: 'a::len word) = word_of_int (bin_rest (bintrunc (LENGTH('a)) (numeral w)))" unfolding shiftr1_def word_numeral_alt by (simp add: word_ubin.eq_norm) lemma sshiftr1_sbintr [simp]: "(sshiftr1 (numeral w) :: 'a::len word) = word_of_int (bin_rest (sbintrunc (LENGTH('a) - 1) (numeral w)))" unfolding sshiftr1_def word_numeral_alt by (simp add: word_sbin.eq_norm) -lemma shiftr_no [simp]: - (* FIXME: neg_numeral *) - "(numeral w::'a::len word) >> n = word_of_int - ((bin_rest ^^ n) (bintrunc (LENGTH('a)) (numeral w)))" - by (rule word_eqI) (auto simp: nth_shiftr nth_rest_power_bin nth_bintr word_size) - -lemma sshiftr_no [simp]: - (* FIXME: neg_numeral *) - "(numeral w::'a::len word) >>> n = word_of_int - ((bin_rest ^^ n) (sbintrunc (LENGTH('a) - 1) (numeral w)))" +text \TODO: rules for \<^term>\- (numeral n)\\ + +lemma drop_bit_word_numeral [simp]: + \drop_bit (numeral n) (numeral k) = + (word_of_int (drop_bit (numeral n) (take_bit LENGTH('a) (numeral k))) :: 'a::len word)\ + by transfer simp + +lemma shiftr_numeral [simp]: + \(numeral k >> numeral n :: 'a::len word) = drop_bit (numeral n) (numeral k)\ + by (fact shiftr_word_eq) + +lemma sshiftr_numeral [simp]: + \(numeral k >>> numeral n :: 'a::len word) = + word_of_int (drop_bit (numeral n) (sbintrunc (LENGTH('a) - 1) (numeral k)))\ apply (rule word_eqI) - apply (auto simp: nth_sshiftr nth_rest_power_bin nth_sbintr word_size) - apply (subgoal_tac "na + n = LENGTH('a) - Suc 0", simp, simp)+ + apply (cases \LENGTH('a)\) + apply (simp_all add: word_size bit_drop_bit_eq nth_sshiftr nth_sbintr not_le not_less less_Suc_eq_le ac_simps) done lemma shiftr1_bl_of: "length bl \ LENGTH('a) \ shiftr1 (of_bl bl::'a::len word) = of_bl (butlast bl)" by (clarsimp simp: shiftr1_def of_bl_def butlast_rest_bl2bin word_ubin.eq_norm trunc_bl2bin) lemma shiftr_bl_of: "length bl \ LENGTH('a) \ (of_bl bl::'a::len word) >> n = of_bl (take (length bl - n) bl)" apply (unfold shiftr_def) apply (induct n) apply clarsimp apply clarsimp apply (subst shiftr1_bl_of) apply simp apply (simp add: butlast_take) done lemma shiftr_bl: "x >> n \ of_bl (take (LENGTH('a) - n) (to_bl x))" for x :: "'a::len word" using shiftr_bl_of [where 'a='a, of "to_bl x"] by simp lemma msb_shift: "msb w \ w >> (LENGTH('a) - 1) \ 0" for w :: "'a::len word" apply (unfold shiftr_bl word_msb_alt) apply (simp add: word_size Suc_le_eq take_Suc) apply (cases "hd (to_bl w)") apply (auto simp: word_1_bl of_bl_rep_False [where n=1 and bs="[]", simplified]) done lemma zip_replicate: "n \ length ys \ zip (replicate n x) ys = map (\y. (x, y)) ys" apply (induct ys arbitrary: n) apply simp_all apply (case_tac n) apply simp_all done lemma align_lem_or [rule_format] : "\x m. length x = n + m \ length y = n + m \ drop m x = replicate n False \ take m y = replicate m False \ map2 (|) x y = take m x @ drop m y" apply (induct y) apply force apply clarsimp apply (case_tac x) apply force apply (case_tac m) apply auto apply (drule_tac t="length xs" for xs in sym) apply (auto simp: zip_replicate o_def) done lemma align_lem_and [rule_format] : "\x m. length x = n + m \ length y = n + m \ drop m x = replicate n False \ take m y = replicate m False \ map2 (\) x y = replicate (n + m) False" apply (induct y) apply force apply clarsimp apply (case_tac x) apply force apply (case_tac m) apply auto apply (drule_tac t="length xs" for xs in sym) apply (auto simp: zip_replicate o_def map_replicate_const) done lemma aligned_bl_add_size [OF refl]: "size x - n = m \ n \ size x \ drop m (to_bl x) = replicate n False \ take m (to_bl y) = replicate m False \ to_bl (x + y) = take m (to_bl x) @ drop m (to_bl y)" for x :: \'a::len word\ apply (subgoal_tac "x AND y = 0") prefer 2 apply (rule word_bl.Rep_eqD) apply (simp add: bl_word_and) apply (rule align_lem_and [THEN trans]) apply (simp_all add: word_size)[5] apply simp apply (subst word_plus_and_or [symmetric]) apply (simp add : bl_word_or) apply (rule align_lem_or) apply (simp_all add: word_size) done subsubsection \Mask\ lemma minus_1_eq_mask: \- 1 = (Bit_Operations.mask LENGTH('a) :: 'a::len word)\ by (rule bit_eqI) (simp add: bit_exp_iff bit_mask_iff exp_eq_zero_iff) lemma mask_eq_mask: \mask = Bit_Operations.mask\ by (simp add: fun_eq_iff mask_eq_exp_minus_1 mask_def shiftl_word_eq push_bit_eq_mult) lemma mask_eq: \mask n = 2 ^ n - 1\ by (simp add: mask_eq_mask mask_eq_exp_minus_1) lemma mask_Suc_rec: \mask (Suc n) = 2 * mask n + 1\ by (simp add: mask_eq) context begin qualified lemma bit_mask_iff: \bit (mask m :: 'a::len word) n \ n < min LENGTH('a) m\ by (simp add: mask_eq_mask bit_mask_iff exp_eq_zero_iff not_le) end lemma nth_mask [simp]: \(mask n :: 'a::len word) !! i \ i < n \ i < size (mask n :: 'a word)\ by (auto simp add: test_bit_word_eq word_size Word.bit_mask_iff) lemma mask_bl: "mask n = of_bl (replicate n True)" by (auto simp add : test_bit_of_bl word_size intro: word_eqI) lemma mask_bin: "mask n = word_of_int (bintrunc n (- 1))" by (auto simp add: nth_bintr word_size intro: word_eqI) lemma and_mask_bintr: "w AND mask n = word_of_int (bintrunc n (uint w))" apply (rule word_eqI) apply (simp add: nth_bintr word_size word_ops_nth_size) apply (auto simp add: test_bit_bin) done lemma and_mask_wi: "word_of_int i AND mask n = word_of_int (bintrunc n i)" by (auto simp add: nth_bintr word_size word_ops_nth_size word_eq_iff) lemma and_mask_wi': "word_of_int i AND mask n = (word_of_int (bintrunc (min LENGTH('a) n) i) :: 'a::len word)" by (auto simp add: nth_bintr word_size word_ops_nth_size word_eq_iff) lemma and_mask_no: "numeral i AND mask n = word_of_int (bintrunc n (numeral i))" unfolding word_numeral_alt by (rule and_mask_wi) lemma bl_and_mask': "to_bl (w AND mask n :: 'a::len word) = replicate (LENGTH('a) - n) False @ drop (LENGTH('a) - n) (to_bl w)" apply (rule nth_equalityI) apply simp apply (clarsimp simp add: to_bl_nth word_size) apply (simp add: word_size word_ops_nth_size) - apply (auto simp add: word_size test_bit_bl nth_append nth_rev) + apply (auto simp add: word_size test_bit_bl nth_append rev_nth) done lemma and_mask_mod_2p: "w AND mask n = word_of_int (uint w mod 2 ^ n)" by (simp only: and_mask_bintr bintrunc_mod2p) lemma and_mask_lt_2p: "uint (w AND mask n) < 2 ^ n" - apply (simp add: and_mask_bintr word_ubin.eq_norm) - apply (simp add: bintrunc_mod2p) - apply (rule xtr8) - prefer 2 - apply (rule pos_mod_bound) - apply auto - done + by (simp add: and_mask_bintr uint.abs_eq min_def not_le lt2p_lem bintr_lt2p) lemma eq_mod_iff: "0 < n \ b = b mod n \ 0 \ b \ b < n" for b n :: int - by (simp add: int_mod_lem eq_sym_conv) + by auto (metis pos_mod_conj)+ lemma mask_eq_iff: "w AND mask n = w \ uint w < 2 ^ n" apply (simp add: and_mask_bintr) apply (simp add: word_ubin.inverse_norm) apply (simp add: eq_mod_iff bintrunc_mod2p min_def) apply (fast intro!: lt2p_lem) done lemma and_mask_dvd: "2 ^ n dvd uint w \ w AND mask n = 0" apply (simp add: dvd_eq_mod_eq_0 and_mask_mod_2p) apply (simp add: word_uint.norm_eq_iff [symmetric] word_of_int_homs del: word_of_int_0) apply (subst word_uint.norm_Rep [symmetric]) apply (simp only: bintrunc_bintrunc_min bintrunc_mod2p [symmetric] min_def) apply auto done lemma and_mask_dvd_nat: "2 ^ n dvd unat w \ w AND mask n = 0" apply (unfold unat_def) apply (rule trans [OF _ and_mask_dvd]) apply (unfold dvd_def) apply auto apply (drule uint_ge_0 [THEN nat_int.Abs_inverse' [simplified], symmetric]) apply simp apply (simp add: nat_mult_distrib nat_power_eq) done lemma word_2p_lem: "n < size w \ w < 2 ^ n = (uint w < 2 ^ n)" for w :: "'a::len word" apply (unfold word_size word_less_alt word_numeral_alt) apply (auto simp add: word_of_int_power_hom word_uint.eq_norm simp del: word_of_int_numeral) done lemma less_mask_eq: "x < 2 ^ n \ x AND mask n = x" for x :: "'a::len word" - apply (unfold word_less_alt word_numeral_alt) - apply (clarsimp simp add: and_mask_mod_2p word_of_int_power_hom word_uint.eq_norm - simp del: word_of_int_numeral) - apply (drule xtr8 [rotated]) - apply (rule int_mod_le) - apply simp_all + apply (simp add: and_mask_bintr) + apply transfer + apply (simp add: ac_simps) + apply (auto simp add: min_def) + apply (metis bintrunc_bintrunc_ge mod_pos_pos_trivial mult.commute mult.left_neutral mult_zero_left not_le of_bool_def take_bit_eq_mod take_bit_nonnegative) done lemmas mask_eq_iff_w2p = trans [OF mask_eq_iff word_2p_lem [symmetric]] lemmas and_mask_less' = iffD2 [OF word_2p_lem and_mask_lt_2p, simplified word_size] lemma and_mask_less_size: "n < size x \ x AND mask n < 2^n" unfolding word_size by (erule and_mask_less') lemma word_mod_2p_is_mask [OF refl]: "c = 2 ^ n \ c > 0 \ x mod c = x AND mask n" for c x :: "'a::len word" by (auto simp: word_mod_def uint_2p and_mask_mod_2p) lemma mask_eqs: "(a AND mask n) + b AND mask n = a + b AND mask n" "a + (b AND mask n) AND mask n = a + b AND mask n" "(a AND mask n) - b AND mask n = a - b AND mask n" "a - (b AND mask n) AND mask n = a - b AND mask n" "a * (b AND mask n) AND mask n = a * b AND mask n" "(b AND mask n) * a AND mask n = b * a AND mask n" "(a AND mask n) + (b AND mask n) AND mask n = a + b AND mask n" "(a AND mask n) - (b AND mask n) AND mask n = a - b AND mask n" "(a AND mask n) * (b AND mask n) AND mask n = a * b AND mask n" "- (a AND mask n) AND mask n = - a AND mask n" "word_succ (a AND mask n) AND mask n = word_succ a AND mask n" "word_pred (a AND mask n) AND mask n = word_pred a AND mask n" using word_of_int_Ex [where x=a] word_of_int_Ex [where x=b] by (auto simp: and_mask_wi' word_of_int_homs word.abs_eq_iff bintrunc_mod2p mod_simps) lemma mask_power_eq: "(x AND mask n) ^ k AND mask n = x ^ k AND mask n" using word_of_int_Ex [where x=x] by (auto simp: and_mask_wi' word_of_int_power_hom word.abs_eq_iff bintrunc_mod2p mod_simps) lemma mask_full [simp]: "mask LENGTH('a) = (- 1 :: 'a::len word)" by (simp add: mask_def word_size shiftl_zero_size) subsubsection \Revcast\ lemmas revcast_def' = revcast_def [simplified] lemmas revcast_def'' = revcast_def' [simplified word_size] lemmas revcast_no_def [simp] = revcast_def' [where w="numeral w", unfolded word_size] for w lemma to_bl_revcast: "to_bl (revcast w :: 'a::len word) = takefill False (LENGTH('a)) (to_bl w)" apply (unfold revcast_def' word_size) apply (rule word_bl.Abs_inverse) apply simp done lemma revcast_rev_ucast [OF refl refl refl]: "cs = [rc, uc] \ rc = revcast (word_reverse w) \ uc = ucast w \ rc = word_reverse uc" apply (unfold ucast_def revcast_def' Let_def word_reverse_def) apply (auto simp: to_bl_of_bin takefill_bintrunc) apply (simp add: word_bl.Abs_inverse word_size) done lemma revcast_ucast: "revcast w = word_reverse (ucast (word_reverse w))" using revcast_rev_ucast [of "word_reverse w"] by simp lemma ucast_revcast: "ucast w = word_reverse (revcast (word_reverse w))" by (fact revcast_rev_ucast [THEN word_rev_gal']) lemma ucast_rev_revcast: "ucast (word_reverse w) = word_reverse (revcast w)" by (fact revcast_ucast [THEN word_rev_gal']) text "linking revcast and cast via shift" lemmas wsst_TYs = source_size target_size word_size lemma revcast_down_uu [OF refl]: "rc = revcast \ source_size rc = target_size rc + n \ rc w = ucast (w >> n)" for w :: "'a::len word" apply (simp add: revcast_def') apply (rule word_bl.Rep_inverse') apply (rule trans, rule ucast_down_drop) prefer 2 apply (rule trans, rule drop_shiftr) apply (auto simp: takefill_alt wsst_TYs) done lemma revcast_down_us [OF refl]: "rc = revcast \ source_size rc = target_size rc + n \ rc w = ucast (w >>> n)" for w :: "'a::len word" apply (simp add: revcast_def') apply (rule word_bl.Rep_inverse') apply (rule trans, rule ucast_down_drop) prefer 2 apply (rule trans, rule drop_sshiftr) apply (auto simp: takefill_alt wsst_TYs) done lemma revcast_down_su [OF refl]: "rc = revcast \ source_size rc = target_size rc + n \ rc w = scast (w >> n)" for w :: "'a::len word" apply (simp add: revcast_def') apply (rule word_bl.Rep_inverse') apply (rule trans, rule scast_down_drop) prefer 2 apply (rule trans, rule drop_shiftr) apply (auto simp: takefill_alt wsst_TYs) done lemma revcast_down_ss [OF refl]: "rc = revcast \ source_size rc = target_size rc + n \ rc w = scast (w >>> n)" for w :: "'a::len word" apply (simp add: revcast_def') apply (rule word_bl.Rep_inverse') apply (rule trans, rule scast_down_drop) prefer 2 apply (rule trans, rule drop_sshiftr) apply (auto simp: takefill_alt wsst_TYs) done (* FIXME: should this also be [OF refl] ? *) lemma cast_down_rev: "uc = ucast \ source_size uc = target_size uc + n \ uc w = revcast (w << n)" for w :: "'a::len word" apply (unfold shiftl_rev) apply clarify apply (simp add: revcast_rev_ucast) apply (rule word_rev_gal') apply (rule trans [OF _ revcast_rev_ucast]) apply (rule revcast_down_uu [symmetric]) apply (auto simp add: wsst_TYs) done lemma revcast_up [OF refl]: "rc = revcast \ source_size rc + n = target_size rc \ rc w = (ucast w :: 'a::len word) << n" apply (simp add: revcast_def') apply (rule word_bl.Rep_inverse') apply (simp add: takefill_alt) apply (rule bl_shiftl [THEN trans]) apply (subst ucast_up_app) apply (auto simp add: wsst_TYs) done lemmas rc1 = revcast_up [THEN revcast_rev_ucast [symmetric, THEN trans, THEN word_rev_gal, symmetric]] lemmas rc2 = revcast_down_uu [THEN revcast_rev_ucast [symmetric, THEN trans, THEN word_rev_gal, symmetric]] lemmas ucast_up = rc1 [simplified rev_shiftr [symmetric] revcast_ucast [symmetric]] lemmas ucast_down = rc2 [simplified rev_shiftr revcast_ucast [symmetric]] subsubsection \Slices\ lemma slice1_no_bin [simp]: "slice1 n (numeral w :: 'b word) = of_bl (takefill False n (bin_to_bl (LENGTH('b::len)) (numeral w)))" by (simp add: slice1_def) (* TODO: neg_numeral *) lemma slice_no_bin [simp]: "slice n (numeral w :: 'b word) = of_bl (takefill False (LENGTH('b::len) - n) (bin_to_bl (LENGTH('b::len)) (numeral w)))" by (simp add: slice_def word_size) (* TODO: neg_numeral *) lemma slice1_0 [simp] : "slice1 n 0 = 0" unfolding slice1_def by simp lemma slice_0 [simp] : "slice n 0 = 0" unfolding slice_def by auto lemma slice_take': "slice n w = of_bl (take (size w - n) (to_bl w))" unfolding slice_def' slice1_def by (simp add : takefill_alt word_size) lemmas slice_take = slice_take' [unfolded word_size] \ \shiftr to a word of the same size is just slice, slice is just shiftr then ucast\ lemmas shiftr_slice = trans [OF shiftr_bl [THEN meta_eq_to_obj_eq] slice_take [symmetric]] lemma slice_shiftr: "slice n w = ucast (w >> n)" apply (unfold slice_take shiftr_bl) apply (rule ucast_of_bl_up [symmetric]) apply (simp add: word_size) done lemma nth_slice: "(slice n w :: 'a::len word) !! m = (w !! (m + n) \ m < LENGTH('a))" by (simp add: slice_shiftr nth_ucast nth_shiftr) lemma slice1_down_alt': "sl = slice1 n w \ fs = size sl \ fs + k = n \ to_bl sl = takefill False fs (drop k (to_bl w))" by (auto simp: slice1_def word_size of_bl_def uint_bl word_ubin.eq_norm bl_bin_bl_rep_drop drop_takefill) lemma slice1_up_alt': "sl = slice1 n w \ fs = size sl \ fs = n + k \ to_bl sl = takefill False fs (replicate k False @ (to_bl w))" apply (unfold slice1_def word_size of_bl_def uint_bl) apply (clarsimp simp: word_ubin.eq_norm bl_bin_bl_rep_drop takefill_append [symmetric]) apply (rule_tac f = "\k. takefill False (LENGTH('a)) (replicate k False @ bin_to_bl (LENGTH('b)) (uint w))" in arg_cong) apply arith done lemmas sd1 = slice1_down_alt' [OF refl refl, unfolded word_size] lemmas su1 = slice1_up_alt' [OF refl refl, unfolded word_size] lemmas slice1_down_alt = le_add_diff_inverse [THEN sd1] lemmas slice1_up_alts = le_add_diff_inverse [symmetric, THEN su1] le_add_diff_inverse2 [symmetric, THEN su1] lemma ucast_slice1: "ucast w = slice1 (size w) w" by (simp add: slice1_def ucast_bl takefill_same' word_size) lemma ucast_slice: "ucast w = slice 0 w" by (simp add: slice_def ucast_slice1) lemma slice_id: "slice 0 t = t" by (simp only: ucast_slice [symmetric] ucast_id) lemma revcast_slice1 [OF refl]: "rc = revcast w \ slice1 (size rc) w = rc" by (simp add: slice1_def revcast_def' word_size) lemma slice1_tf_tf': "to_bl (slice1 n w :: 'a::len word) = rev (takefill False (LENGTH('a)) (rev (takefill False n (to_bl w))))" unfolding slice1_def by (rule word_rev_tf) lemmas slice1_tf_tf = slice1_tf_tf' [THEN word_bl.Rep_inverse', symmetric] lemma rev_slice1: "n + k = LENGTH('a) + LENGTH('b) \ slice1 n (word_reverse w :: 'b::len word) = word_reverse (slice1 k w :: 'a::len word)" apply (unfold word_reverse_def slice1_tf_tf) apply (rule word_bl.Rep_inverse') apply (rule rev_swap [THEN iffD1]) apply (rule trans [symmetric]) apply (rule tf_rev) apply (simp add: word_bl.Abs_inverse) apply (simp add: word_bl.Abs_inverse) done lemma rev_slice: "n + k + LENGTH('a::len) = LENGTH('b::len) \ slice n (word_reverse (w::'b word)) = word_reverse (slice k w :: 'a word)" apply (unfold slice_def word_size) apply (rule rev_slice1) apply arith done lemmas sym_notr = not_iff [THEN iffD2, THEN not_sym, THEN not_iff [THEN iffD1]] \ \problem posed by TPHOLs referee: criterion for overflow of addition of signed integers\ lemma sofl_test: "(sint x + sint y = sint (x + y)) = ((((x + y) XOR x) AND ((x + y) XOR y)) >> (size x - 1) = 0)" for x y :: "'a::len word" apply (unfold word_size) apply (cases "LENGTH('a)", simp) apply (subst msb_shift [THEN sym_notr]) apply (simp add: word_ops_msb) apply (simp add: word_msb_sint) apply safe apply simp_all apply (unfold sint_word_ariths) apply (unfold word_sbin.set_iff_norm [symmetric] sints_num) apply safe apply (insert sint_range' [where x=x]) apply (insert sint_range' [where x=y]) defer apply (simp (no_asm), arith) apply (simp (no_asm), arith) defer defer apply (simp (no_asm), arith) apply (simp (no_asm), arith) apply (rule notI [THEN notnotD], drule leI not_le_imp_less, drule sbintrunc_inc sbintrunc_dec, simp)+ done lemma shiftr_zero_size: "size x \ n \ x >> n = 0" for x :: "'a :: len word" by (rule word_eqI) (auto simp add: nth_shiftr dest: test_bit_size) subsection \Split and cat\ lemmas word_split_bin' = word_split_def lemmas word_cat_bin' = word_cat_def lemma word_rsplit_no: "(word_rsplit (numeral bin :: 'b::len word) :: 'a word list) = map word_of_int (bin_rsplit (LENGTH('a::len)) (LENGTH('b), bintrunc (LENGTH('b)) (numeral bin)))" by (simp add: word_rsplit_def word_ubin.eq_norm) lemmas word_rsplit_no_cl [simp] = word_rsplit_no [unfolded bin_rsplitl_def bin_rsplit_l [symmetric]] lemma test_bit_cat: "wc = word_cat a b \ wc !! n = (n < size wc \ (if n < size b then b !! n else a !! (n - size b)))" apply (auto simp: word_cat_bin' test_bit_bin word_ubin.eq_norm nth_bintr bin_nth_cat word_size) apply (erule bin_nth_uint_imp) done lemma word_cat_bl: "word_cat a b = of_bl (to_bl a @ to_bl b)" by (simp add: of_bl_def to_bl_def word_cat_bin' bl_to_bin_app_cat) lemma of_bl_append: "(of_bl (xs @ ys) :: 'a::len word) = of_bl xs * 2^(length ys) + of_bl ys" apply (simp add: of_bl_def bl_to_bin_app_cat bin_cat_num) apply (simp add: word_of_int_power_hom [symmetric] word_of_int_hom_syms) done lemma of_bl_False [simp]: "of_bl (False#xs) = of_bl xs" by (rule word_eqI) (auto simp: test_bit_of_bl nth_append) lemma of_bl_True [simp]: "(of_bl (True # xs) :: 'a::len word) = 2^length xs + of_bl xs" by (subst of_bl_append [where xs="[True]", simplified]) (simp add: word_1_bl) lemma of_bl_Cons: "of_bl (x#xs) = of_bool x * 2^length xs + of_bl xs" by (cases x) simp_all lemma split_uint_lem: "bin_split n (uint w) = (a, b) \ a = bintrunc (LENGTH('a) - n) a \ b = bintrunc (LENGTH('a)) b" for w :: "'a::len word" apply (frule word_ubin.norm_Rep [THEN ssubst]) apply (drule bin_split_trunc1) apply (drule sym [THEN trans]) apply assumption apply safe done lemma word_split_bl': "std = size c - size b \ (word_split c = (a, b)) \ (a = of_bl (take std (to_bl c)) \ b = of_bl (drop std (to_bl c)))" apply (unfold word_split_bin') apply safe defer apply (clarsimp split: prod.splits) apply (metis of_bl_drop' ucast_bl ucast_def word_size word_size_bl) apply hypsubst_thin apply (drule word_ubin.norm_Rep [THEN ssubst]) apply (simp add: of_bl_def bl2bin_drop word_size word_ubin.norm_eq_iff [symmetric] min_def del: word_ubin.norm_Rep) apply (clarsimp split: prod.splits) apply (cases "LENGTH('a) \ LENGTH('b)") apply (simp_all add: not_le) defer apply (simp add: drop_bit_eq_div lt2p_lem) apply (simp add : of_bl_def to_bl_def) apply (subst bin_to_bl_drop_bit [symmetric]) apply (subst diff_add) apply (simp_all add: take_bit_drop_bit) done lemma word_split_bl: "std = size c - size b \ (a = of_bl (take std (to_bl c)) \ b = of_bl (drop std (to_bl c))) \ word_split c = (a, b)" apply (rule iffI) defer apply (erule (1) word_split_bl') apply (case_tac "word_split c") apply (auto simp add: word_size) apply (frule word_split_bl' [rotated]) apply (auto simp add: word_size) done lemma word_split_bl_eq: "(word_split c :: ('c::len word \ 'd::len word)) = (of_bl (take (LENGTH('a::len) - LENGTH('d::len)) (to_bl c)), of_bl (drop (LENGTH('a) - LENGTH('d)) (to_bl c)))" for c :: "'a::len word" apply (rule word_split_bl [THEN iffD1]) apply (unfold word_size) apply (rule refl conjI)+ done \ \keep quantifiers for use in simplification\ lemma test_bit_split': "word_split c = (a, b) \ (\n m. b !! n = (n < size b \ c !! n) \ a !! m = (m < size a \ c !! (m + size b)))" apply (unfold word_split_bin' test_bit_bin) apply (clarify) apply (clarsimp simp: word_ubin.eq_norm nth_bintr word_size split: prod.splits) apply (auto simp add: bit_take_bit_iff bit_drop_bit_eq ac_simps bin_nth_uint_imp) done lemma test_bit_split: "word_split c = (a, b) \ (\n::nat. b !! n \ n < size b \ c !! n) \ (\m::nat. a !! m \ m < size a \ c !! (m + size b))" by (simp add: test_bit_split') lemma test_bit_split_eq: "word_split c = (a, b) \ ((\n::nat. b !! n = (n < size b \ c !! n)) \ (\m::nat. a !! m = (m < size a \ c !! (m + size b))))" apply (rule_tac iffI) apply (rule_tac conjI) apply (erule test_bit_split [THEN conjunct1]) apply (erule test_bit_split [THEN conjunct2]) apply (case_tac "word_split c") apply (frule test_bit_split) apply (erule trans) apply (fastforce intro!: word_eqI simp add: word_size) done \ \this odd result is analogous to \ucast_id\, result to the length given by the result type\ lemma word_cat_id: "word_cat a b = b" by (simp add: word_cat_bin' word_ubin.inverse_norm) \ \limited hom result\ lemma word_cat_hom: "LENGTH('a::len) \ LENGTH('b::len) + LENGTH('c::len) \ (word_cat (word_of_int w :: 'b word) (b :: 'c word) :: 'a word) = word_of_int (bin_cat w (size b) (uint b))" by (auto simp: word_cat_def word_size word_ubin.norm_eq_iff [symmetric] word_ubin.eq_norm bintr_cat min.absorb1) lemma word_cat_split_alt: "size w \ size u + size v \ word_split w = (u, v) \ word_cat u v = w" apply (rule word_eqI) apply (drule test_bit_split) apply (clarsimp simp add : test_bit_cat word_size) apply safe apply arith done lemmas word_cat_split_size = sym [THEN [2] word_cat_split_alt [symmetric]] subsubsection \Split and slice\ lemma split_slices: "word_split w = (u, v) \ u = slice (size v) w \ v = slice 0 w" apply (drule test_bit_split) apply (rule conjI) apply (rule word_eqI, clarsimp simp: nth_slice word_size)+ done lemma slice_cat1 [OF refl]: "wc = word_cat a b \ size wc >= size a + size b \ slice (size b) wc = a" apply safe apply (rule word_eqI) apply (simp add: nth_slice test_bit_cat word_size) done lemmas slice_cat2 = trans [OF slice_id word_cat_id] lemma cat_slices: "a = slice n c \ b = slice 0 c \ n = size b \ size a + size b >= size c \ word_cat a b = c" apply safe apply (rule word_eqI) apply (simp add: nth_slice test_bit_cat word_size) apply safe apply arith done lemma word_split_cat_alt: "w = word_cat u v \ size u + size v \ size w \ word_split w = (u, v)" apply (case_tac "word_split w") apply (rule trans, assumption) apply (drule test_bit_split) apply safe apply (rule word_eqI, clarsimp simp: test_bit_cat word_size)+ done lemmas word_cat_bl_no_bin [simp] = word_cat_bl [where a="numeral a" and b="numeral b", unfolded to_bl_numeral] for a b (* FIXME: negative numerals, 0 and 1 *) lemmas word_split_bl_no_bin [simp] = word_split_bl_eq [where c="numeral c", unfolded to_bl_numeral] for c text \ This odd result arises from the fact that the statement of the result implies that the decoded words are of the same type, and therefore of the same length, as the original word.\ lemma word_rsplit_same: "word_rsplit w = [w]" by (simp add: word_rsplit_def bin_rsplit_all) lemma word_rsplit_empty_iff_size: "word_rsplit w = [] \ size w = 0" by (simp add: word_rsplit_def bin_rsplit_def word_size bin_rsplit_aux_simp_alt Let_def split: prod.split) lemma test_bit_rsplit: "sw = word_rsplit w \ m < size (hd sw) \ k < length sw \ (rev sw ! k) !! m = w !! (k * size (hd sw) + m)" for sw :: "'a::len word list" apply (unfold word_rsplit_def word_test_bit_def) apply (rule trans) apply (rule_tac f = "\x. bin_nth x m" in arg_cong) apply (rule nth_map [symmetric]) apply simp apply (rule bin_nth_rsplit) apply simp_all apply (simp add : word_size rev_map) apply (rule trans) defer apply (rule map_ident [THEN fun_cong]) apply (rule refl [THEN map_cong]) apply (simp add : word_ubin.eq_norm) apply (erule bin_rsplit_size_sign [OF len_gt_0 refl]) done lemma word_rcat_bl: "word_rcat wl = of_bl (concat (map to_bl wl))" by (auto simp: word_rcat_def to_bl_def' of_bl_def bin_rcat_bl) lemma size_rcat_lem': "size (concat (map to_bl wl)) = length wl * size (hd wl)" by (induct wl) (auto simp: word_size) lemmas size_rcat_lem = size_rcat_lem' [unfolded word_size] -lemmas td_gal_lt_len = len_gt_0 [THEN td_gal_lt] - lemma nth_rcat_lem: "n < length (wl::'a word list) * LENGTH('a::len) \ rev (concat (map to_bl wl)) ! n = rev (to_bl (rev wl ! (n div LENGTH('a)))) ! (n mod LENGTH('a))" apply (induct wl) apply clarsimp apply (clarsimp simp add : nth_append size_rcat_lem) - apply (simp (no_asm_use) only: mult_Suc [symmetric] - td_gal_lt_len less_Suc_eq_le minus_div_mult_eq_mod [symmetric]) - apply clarsimp + apply (simp flip: mult_Suc minus_div_mult_eq_mod add: less_Suc_eq_le not_less) + apply (metis (no_types, lifting) diff_is_0_eq div_le_mono len_not_eq_0 less_Suc_eq less_mult_imp_div_less nonzero_mult_div_cancel_right not_le nth_Cons_0) done lemma test_bit_rcat: "sw = size (hd wl) \ rc = word_rcat wl \ rc !! n = (n < size rc \ n div sw < size wl \ (rev wl) ! (n div sw) !! (n mod sw))" for wl :: "'a::len word list" apply (unfold word_rcat_bl word_size) - apply (clarsimp simp add: test_bit_of_bl size_rcat_lem word_size td_gal_lt_len) - apply safe - apply (auto simp: test_bit_bl word_size td_gal_lt_len [THEN iffD2, THEN nth_rcat_lem]) + apply (clarsimp simp add: test_bit_of_bl size_rcat_lem word_size) + apply (metis div_le_mono len_gt_0 len_not_eq_0 less_mult_imp_div_less mod_less_divisor nonzero_mult_div_cancel_right not_le nth_rcat_lem test_bit_bl word_size) done lemma foldl_eq_foldr: "foldl (+) x xs = foldr (+) (x # xs) 0" for x :: "'a::comm_monoid_add" by (induct xs arbitrary: x) (auto simp: add.assoc) lemmas test_bit_cong = arg_cong [where f = "test_bit", THEN fun_cong] lemma test_bit_rsplit_alt: \(word_rsplit w :: 'b::len word list) ! i !! m \ w !! ((length (word_rsplit w :: 'b::len word list) - Suc i) * size (hd (word_rsplit w :: 'b::len word list)) + m)\ if \i < length (word_rsplit w :: 'b::len word list)\ \m < size (hd (word_rsplit w :: 'b::len word list))\ \0 < length (word_rsplit w :: 'b::len word list)\ for w :: \'a::len word\ apply (rule trans) apply (rule test_bit_cong) - apply (rule nth_rev_alt) + apply (rule rev_nth [of _ \rev (word_rsplit w)\, simplified rev_rev_ident]) + apply simp apply (rule that(1)) + apply simp apply (rule test_bit_rsplit) apply (rule refl) apply (rule asm_rl) apply (rule that(2)) apply (rule diff_Suc_less) apply (rule that(3)) done lemma word_rsplit_len_indep [OF refl refl refl refl]: "[u,v] = p \ [su,sv] = q \ word_rsplit u = su \ word_rsplit v = sv \ length su = length sv" by (auto simp: word_rsplit_def bin_rsplit_len_indep) lemma length_word_rsplit_size: "n = LENGTH('a::len) \ length (word_rsplit w :: 'a word list) \ m \ size w \ m * n" by (auto simp: word_rsplit_def word_size bin_rsplit_len_le) lemmas length_word_rsplit_lt_size = length_word_rsplit_size [unfolded Not_eq_iff linorder_not_less [symmetric]] lemma length_word_rsplit_exp_size: "n = LENGTH('a::len) \ length (word_rsplit w :: 'a word list) = (size w + n - 1) div n" by (auto simp: word_rsplit_def word_size bin_rsplit_len) lemma length_word_rsplit_even_size: "n = LENGTH('a::len) \ size w = m * n \ length (word_rsplit w :: 'a word list) = m" - by (auto simp: length_word_rsplit_exp_size given_quot_alt) + by (cases \LENGTH('a)\) (simp_all add: length_word_rsplit_exp_size div_nat_eqI) lemmas length_word_rsplit_exp_size' = refl [THEN length_word_rsplit_exp_size] \ \alternative proof of \word_rcat_rsplit\\ lemmas tdle = times_div_less_eq_dividend -lemmas dtle = xtr4 [OF tdle mult.commute] +lemmas dtle = xtrans(4) [OF tdle mult.commute] lemma word_rcat_rsplit: "word_rcat (word_rsplit w) = w" apply (rule word_eqI) apply (clarsimp simp: test_bit_rcat word_size) apply (subst refl [THEN test_bit_rsplit]) apply (simp_all add: word_size refl [THEN length_word_rsplit_size [simplified not_less [symmetric], simplified]]) apply safe - apply (erule xtr7, rule dtle)+ + apply (erule xtrans(7), rule dtle)+ done lemma size_word_rsplit_rcat_size: "word_rcat ws = frcw \ size frcw = length ws * LENGTH('a) \ length (word_rsplit frcw::'a word list) = length ws" for ws :: "'a::len word list" and frcw :: "'b::len word" - apply (clarsimp simp: word_size length_word_rsplit_exp_size') - apply (fast intro: given_quot_alt) - done + by (cases \LENGTH('a)\) (simp_all add: word_size length_word_rsplit_exp_size' div_nat_eqI) lemma msrevs: "0 < n \ (k * n + m) div n = m div n + k" "(k * n + m) mod n = m mod n" for n :: nat by (auto simp: add.commute) lemma word_rsplit_rcat_size [OF refl]: "word_rcat ws = frcw \ size frcw = length ws * LENGTH('a) \ word_rsplit frcw = ws" for ws :: "'a::len word list" apply (frule size_word_rsplit_rcat_size, assumption) apply (clarsimp simp add : word_size) apply (rule nth_equalityI, assumption) apply clarsimp apply (rule word_eqI [rule_format]) apply (rule trans) apply (rule test_bit_rsplit_alt) apply (clarsimp simp: word_size)+ apply (rule trans) apply (rule test_bit_rcat [OF refl refl]) apply (simp add: word_size) - apply (subst nth_rev) + apply (subst rev_nth) apply arith - apply (simp add: le0 [THEN [2] xtr7, THEN diff_Suc_less]) + apply (simp add: le0 [THEN [2] xtrans(7), THEN diff_Suc_less]) apply safe apply (simp add: diff_mult_distrib) - apply (rule mpl_lem) apply (cases "size ws") apply simp_all done subsection \Rotation\ lemmas rotater_0' [simp] = rotater_def [where n = "0", simplified] lemma bit_word_rotl_iff: \bit (word_rotl m w) n \ n < LENGTH('a) \ bit w ((n + (LENGTH('a) - m mod LENGTH('a))) mod LENGTH('a))\ for w :: \'a::len word\ proof (cases \n < LENGTH('a)\) case False then show ?thesis by (auto dest: bit_imp_le_length) next case True define k where \k = int n - int m\ then have k: \int n = k + int m\ by simp define l where \l = int LENGTH('a)\ then have l: \int LENGTH('a) = l\ \l > 0\ by simp_all have *: \int (m - n) = int m - int n\ if \n \ m\ for n m using that by (simp add: int_minus) from \l > 0\ have \l = 1 + (k mod l + ((- 1 - k) mod l))\ using minus_mod_int_eq [of l \k + 1\] by (simp add: algebra_simps) then have \int (LENGTH('a) - Suc ((m + LENGTH('a) - Suc n) mod LENGTH('a))) = int ((n + LENGTH('a) - m mod LENGTH('a)) mod LENGTH('a))\ by (simp add: * k l zmod_int Suc_leI trans_le_add2 algebra_simps mod_simps \n < LENGTH('a)\) then have \LENGTH('a) - Suc ((m + LENGTH('a) - Suc n) mod LENGTH('a)) = (n + LENGTH('a) - m mod LENGTH('a)) mod LENGTH('a)\ by simp with True show ?thesis by (simp add: word_rotl_def bit_of_bl_iff rev_nth nth_rotate nth_to_bl) qed lemmas word_rot_defs = word_roti_def word_rotr_def word_rotl_def lemma rotate_eq_mod: "m mod length xs = n mod length xs \ rotate m xs = rotate n xs" apply (rule box_equals) defer apply (rule rotate_conv_mod [symmetric])+ apply simp done lemmas rotate_eqs = trans [OF rotate0 [THEN fun_cong] id_apply] rotate_rotate [symmetric] rotate_id rotate_conv_mod rotate_eq_mod subsubsection \Rotation of list to right\ lemma rotate1_rl': "rotater1 (l @ [a]) = a # l" by (cases l) (auto simp: rotater1_def) lemma rotate1_rl [simp] : "rotater1 (rotate1 l) = l" apply (unfold rotater1_def) apply (cases "l") apply (case_tac [2] "list") apply auto done lemma rotate1_lr [simp] : "rotate1 (rotater1 l) = l" by (cases l) (auto simp: rotater1_def) lemma rotater1_rev': "rotater1 (rev xs) = rev (rotate1 xs)" by (cases "xs") (simp add: rotater1_def, simp add: rotate1_rl') lemma rotater_rev': "rotater n (rev xs) = rev (rotate n xs)" by (induct n) (auto simp: rotater_def intro: rotater1_rev') lemma rotater_rev: "rotater n ys = rev (rotate n (rev ys))" using rotater_rev' [where xs = "rev ys"] by simp lemma rotater_drop_take: "rotater n xs = drop (length xs - n mod length xs) xs @ take (length xs - n mod length xs) xs" by (auto simp: rotater_rev rotate_drop_take rev_take rev_drop) lemma rotater_Suc [simp]: "rotater (Suc n) xs = rotater1 (rotater n xs)" unfolding rotater_def by auto lemma nth_rotater: \rotater m xs ! n = xs ! ((n + (length xs - m mod length xs)) mod length xs)\ if \n < length xs\ using that by (simp add: rotater_drop_take nth_append not_less less_diff_conv ac_simps le_mod_geq) lemma nth_rotater1: \rotater1 xs ! n = xs ! ((n + (length xs - 1)) mod length xs)\ if \n < length xs\ using that nth_rotater [of n xs 1] by simp lemma rotate_inv_plus [rule_format]: "\k. k = m + n \ rotater k (rotate n xs) = rotater m xs \ rotate k (rotater n xs) = rotate m xs \ rotater n (rotate k xs) = rotate m xs \ rotate n (rotater k xs) = rotater m xs" by (induct n) (auto simp: rotater_def rotate_def intro: funpow_swap1 [THEN trans]) lemmas rotate_inv_rel = le_add_diff_inverse2 [symmetric, THEN rotate_inv_plus] lemmas rotate_inv_eq = order_refl [THEN rotate_inv_rel, simplified] lemmas rotate_lr [simp] = rotate_inv_eq [THEN conjunct1] lemmas rotate_rl [simp] = rotate_inv_eq [THEN conjunct2, THEN conjunct1] lemma rotate_gal: "rotater n xs = ys \ rotate n ys = xs" by auto lemma rotate_gal': "ys = rotater n xs \ xs = rotate n ys" by auto lemma length_rotater [simp]: "length (rotater n xs) = length xs" by (simp add : rotater_rev) lemma bit_word_rotr_iff: \bit (word_rotr m w) n \ n < LENGTH('a) \ bit w ((n + m) mod LENGTH('a))\ for w :: \'a::len word\ proof (cases \n < LENGTH('a)\) case False then show ?thesis by (auto dest: bit_imp_le_length) next case True define k where \k = int n + int m\ then have k: \int n = k - int m\ by simp define l where \l = int LENGTH('a)\ then have l: \int LENGTH('a) = l\ \l > 0\ by simp_all have *: \int (m - n) = int m - int n\ if \n \ m\ for n m using that by (simp add: int_minus) have \int ((LENGTH('a) - Suc ((LENGTH('a) + LENGTH('a) - Suc (n + m mod LENGTH('a))) mod LENGTH('a)))) = int ((n + m) mod LENGTH('a))\ using True apply (simp add: l * zmod_int Suc_leI add_strict_mono) apply (subst mod_diff_left_eq [symmetric]) apply simp using l minus_mod_int_eq [of l \int n + int m mod l + 1\] apply simp apply (simp add: mod_simps) done then have \(LENGTH('a) - Suc ((LENGTH('a) + LENGTH('a) - Suc (n + m mod LENGTH('a))) mod LENGTH('a))) = ((n + m) mod LENGTH('a))\ by simp with True show ?thesis by (simp add: word_rotr_def bit_of_bl_iff rev_nth nth_rotater nth_to_bl) qed lemma bit_word_roti_iff: \bit (word_roti k w) n \ n < LENGTH('a) \ bit w (nat ((int n + k) mod int LENGTH('a)))\ for w :: \'a::len word\ proof (cases \k \ 0\) case True moreover define m where \m = nat k\ ultimately have \k = int m\ by simp then show ?thesis by (simp add: word_roti_def bit_word_rotr_iff nat_mod_distrib nat_add_distrib) next have *: \int (m - n) = int m - int n\ if \n \ m\ for n m using that by (simp add: int_minus) case False moreover define m where \m = nat (- k)\ ultimately have \k = - int m\ \k < 0\ by simp_all moreover have \(int n - int m) mod int LENGTH('a) = int ((n + LENGTH('a) - m mod LENGTH('a)) mod LENGTH('a))\ apply (simp add: zmod_int * trans_le_add2 mod_simps) apply (metis mod_add_self2 mod_diff_cong) done ultimately show ?thesis by (simp add: word_roti_def bit_word_rotl_iff nat_mod_distrib) qed lemma restrict_to_left: "x = y \ x = z \ y = z" by simp lemmas rrs0 = rotate_eqs [THEN restrict_to_left, simplified rotate_gal [symmetric] rotate_gal' [symmetric]] lemmas rrs1 = rrs0 [THEN refl [THEN rev_iffD1]] lemmas rotater_eqs = rrs1 [simplified length_rotater] lemmas rotater_0 = rotater_eqs (1) lemmas rotater_add = rotater_eqs (2) subsubsection \map, map2, commuting with rotate(r)\ lemma butlast_map: "xs \ [] \ butlast (map f xs) = map f (butlast xs)" by (induct xs) auto lemma rotater1_map: "rotater1 (map f xs) = map f (rotater1 xs)" by (cases xs) (auto simp: rotater1_def last_map butlast_map) lemma rotater_map: "rotater n (map f xs) = map f (rotater n xs)" by (induct n) (auto simp: rotater_def rotater1_map) lemma but_last_zip [rule_format] : "\ys. length xs = length ys \ xs \ [] \ last (zip xs ys) = (last xs, last ys) \ butlast (zip xs ys) = zip (butlast xs) (butlast ys)" apply (induct xs) apply auto apply ((case_tac ys, auto simp: neq_Nil_conv)[1])+ done lemma but_last_map2 [rule_format] : "\ys. length xs = length ys \ xs \ [] \ last (map2 f xs ys) = f (last xs) (last ys) \ butlast (map2 f xs ys) = map2 f (butlast xs) (butlast ys)" apply (induct xs) apply auto apply ((case_tac ys, auto simp: neq_Nil_conv)[1])+ done lemma rotater1_zip: "length xs = length ys \ rotater1 (zip xs ys) = zip (rotater1 xs) (rotater1 ys)" apply (unfold rotater1_def) apply (cases xs) apply auto apply ((case_tac ys, auto simp: neq_Nil_conv but_last_zip)[1])+ done lemma rotater1_map2: "length xs = length ys \ rotater1 (map2 f xs ys) = map2 f (rotater1 xs) (rotater1 ys)" by (simp add: rotater1_map rotater1_zip) lemmas lrth = box_equals [OF asm_rl length_rotater [symmetric] length_rotater [symmetric], THEN rotater1_map2] lemma rotater_map2: "length xs = length ys \ rotater n (map2 f xs ys) = map2 f (rotater n xs) (rotater n ys)" by (induct n) (auto intro!: lrth) lemma rotate1_map2: "length xs = length ys \ rotate1 (map2 f xs ys) = map2 f (rotate1 xs) (rotate1 ys)" by (cases xs; cases ys) auto lemmas lth = box_equals [OF asm_rl length_rotate [symmetric] length_rotate [symmetric], THEN rotate1_map2] lemma rotate_map2: "length xs = length ys \ rotate n (map2 f xs ys) = map2 f (rotate n xs) (rotate n ys)" by (induct n) (auto intro!: lth) \ \corresponding equalities for word rotation\ lemma to_bl_rotl: "to_bl (word_rotl n w) = rotate n (to_bl w)" by (simp add: word_bl.Abs_inverse' word_rotl_def) lemmas blrs0 = rotate_eqs [THEN to_bl_rotl [THEN trans]] lemmas word_rotl_eqs = blrs0 [simplified word_bl_Rep' word_bl.Rep_inject to_bl_rotl [symmetric]] lemma to_bl_rotr: "to_bl (word_rotr n w) = rotater n (to_bl w)" by (simp add: word_bl.Abs_inverse' word_rotr_def) lemmas brrs0 = rotater_eqs [THEN to_bl_rotr [THEN trans]] lemmas word_rotr_eqs = brrs0 [simplified word_bl_Rep' word_bl.Rep_inject to_bl_rotr [symmetric]] declare word_rotr_eqs (1) [simp] declare word_rotl_eqs (1) [simp] lemma word_rot_rl [simp]: "word_rotl k (word_rotr k v) = v" and word_rot_lr [simp]: "word_rotr k (word_rotl k v) = v" by (auto simp add: to_bl_rotr to_bl_rotl word_bl.Rep_inject [symmetric]) lemma word_rot_gal: "word_rotr n v = w \ word_rotl n w = v" and word_rot_gal': "w = word_rotr n v \ v = word_rotl n w" by (auto simp: to_bl_rotr to_bl_rotl word_bl.Rep_inject [symmetric] dest: sym) lemma word_rotr_rev: "word_rotr n w = word_reverse (word_rotl n (word_reverse w))" by (simp only: word_bl.Rep_inject [symmetric] to_bl_word_rev to_bl_rotr to_bl_rotl rotater_rev) lemma word_roti_0 [simp]: "word_roti 0 w = w" by (auto simp: word_rot_defs) lemmas abl_cong = arg_cong [where f = "of_bl"] lemma word_roti_add: "word_roti (m + n) w = word_roti m (word_roti n w)" proof - have rotater_eq_lem: "\m n xs. m = n \ rotater m xs = rotater n xs" by auto have rotate_eq_lem: "\m n xs. m = n \ rotate m xs = rotate n xs" by auto note rpts [symmetric] = rotate_inv_plus [THEN conjunct1] rotate_inv_plus [THEN conjunct2, THEN conjunct1] rotate_inv_plus [THEN conjunct2, THEN conjunct2, THEN conjunct1] rotate_inv_plus [THEN conjunct2, THEN conjunct2, THEN conjunct2] note rrp = trans [symmetric, OF rotate_rotate rotate_eq_lem] note rrrp = trans [symmetric, OF rotater_add [symmetric] rotater_eq_lem] show ?thesis apply (unfold word_rot_defs) apply (simp only: split: if_split) apply (safe intro!: abl_cong) apply (simp_all only: to_bl_rotl [THEN word_bl.Rep_inverse'] to_bl_rotl to_bl_rotr [THEN word_bl.Rep_inverse'] to_bl_rotr) apply (rule rrp rrrp rpts, simp add: nat_add_distrib [symmetric] nat_diff_distrib [symmetric])+ done qed lemma word_roti_conv_mod': "word_roti n w = word_roti (n mod int (size w)) w" proof (cases "size w = 0") case True then show ?thesis by simp next case False then have [simp]: "l mod int (size w) \ 0" for l by simp then have *: "word_roti (n mod int (size w)) w = word_rotr (nat (n mod int (size w))) w" by (simp add: word_roti_def) show ?thesis proof (cases "n \ 0") case True then show ?thesis apply (auto simp add: not_le *) apply (auto simp add: word_rot_defs) apply (safe intro!: abl_cong) apply (rule rotater_eqs) apply (simp add: word_size nat_mod_distrib) done next case False moreover define k where "k = - n" ultimately have n: "n = - k" by simp_all from False show ?thesis apply (auto simp add: not_le *) apply (auto simp add: word_rot_defs) apply (simp add: n) apply (safe intro!: abl_cong) apply (simp add: rotater_add [symmetric] rotate_gal [symmetric]) apply (rule rotater_eqs) apply (simp add: word_size [symmetric, of w]) apply (rule of_nat_eq_0_iff [THEN iffD1]) apply (auto simp add: nat_add_distrib [symmetric] mod_eq_0_iff_dvd) using dvd_nat_abs_iff [of "size w" "- k mod int (size w) + k"] apply (simp add: algebra_simps) apply (simp add: word_size) apply (metis dvd_eq_mod_eq_0 eq_neg_iff_add_eq_0 k_def mod_0 mod_add_right_eq n) done qed qed lemmas word_roti_conv_mod = word_roti_conv_mod' [unfolded word_size] subsubsection \"Word rotation commutes with bit-wise operations\ \ \using locale to not pollute lemma namespace\ locale word_rotate begin lemmas word_rot_defs' = to_bl_rotl to_bl_rotr lemmas blwl_syms [symmetric] = bl_word_not bl_word_and bl_word_or bl_word_xor lemmas lbl_lbl = trans [OF word_bl_Rep' word_bl_Rep' [symmetric]] lemmas ths_map2 [OF lbl_lbl] = rotate_map2 rotater_map2 lemmas ths_map [where xs = "to_bl v"] = rotate_map rotater_map for v lemmas th1s [simplified word_rot_defs' [symmetric]] = ths_map2 ths_map lemma word_rot_logs: "word_rotl n (NOT v) = NOT (word_rotl n v)" "word_rotr n (NOT v) = NOT (word_rotr n v)" "word_rotl n (x AND y) = word_rotl n x AND word_rotl n y" "word_rotr n (x AND y) = word_rotr n x AND word_rotr n y" "word_rotl n (x OR y) = word_rotl n x OR word_rotl n y" "word_rotr n (x OR y) = word_rotr n x OR word_rotr n y" "word_rotl n (x XOR y) = word_rotl n x XOR word_rotl n y" "word_rotr n (x XOR y) = word_rotr n x XOR word_rotr n y" by (rule word_bl.Rep_eqD, rule word_rot_defs' [THEN trans], simp only: blwl_syms [symmetric], rule th1s [THEN trans], rule refl)+ end lemmas word_rot_logs = word_rotate.word_rot_logs lemmas bl_word_rotl_dt = trans [OF to_bl_rotl rotate_drop_take, simplified word_bl_Rep'] lemmas bl_word_rotr_dt = trans [OF to_bl_rotr rotater_drop_take, simplified word_bl_Rep'] lemma bl_word_roti_dt': "n = nat ((- i) mod int (size (w :: 'a::len word))) \ to_bl (word_roti i w) = drop n (to_bl w) @ take n (to_bl w)" apply (unfold word_roti_def) apply (simp add: bl_word_rotl_dt bl_word_rotr_dt word_size) apply safe apply (simp add: zmod_zminus1_eq_if) apply safe apply (simp add: nat_mult_distrib) apply (simp add: nat_diff_distrib [OF pos_mod_sign pos_mod_conj [THEN conjunct2, THEN order_less_imp_le]] nat_mod_distrib) apply (simp add: nat_mod_distrib) done lemmas bl_word_roti_dt = bl_word_roti_dt' [unfolded word_size] lemmas word_rotl_dt = bl_word_rotl_dt [THEN word_bl.Rep_inverse' [symmetric]] lemmas word_rotr_dt = bl_word_rotr_dt [THEN word_bl.Rep_inverse' [symmetric]] lemmas word_roti_dt = bl_word_roti_dt [THEN word_bl.Rep_inverse' [symmetric]] lemma word_rotx_0 [simp] : "word_rotr i 0 = 0 \ word_rotl i 0 = 0" by (simp add: word_rotr_dt word_rotl_dt replicate_add [symmetric]) lemma word_roti_0' [simp] : "word_roti n 0 = 0" by (auto simp: word_roti_def) lemmas word_rotr_dt_no_bin' [simp] = word_rotr_dt [where w="numeral w", unfolded to_bl_numeral] for w (* FIXME: negative numerals, 0 and 1 *) lemmas word_rotl_dt_no_bin' [simp] = word_rotl_dt [where w="numeral w", unfolded to_bl_numeral] for w (* FIXME: negative numerals, 0 and 1 *) declare word_roti_def [simp] subsection \Maximum machine word\ lemma word_int_cases: fixes x :: "'a::len word" obtains n where "x = word_of_int n" and "0 \ n" and "n < 2^LENGTH('a)" by (cases x rule: word_uint.Abs_cases) (simp add: uints_num) lemma word_nat_cases [cases type: word]: fixes x :: "'a::len word" obtains n where "x = of_nat n" and "n < 2^LENGTH('a)" by (cases x rule: word_unat.Abs_cases) (simp add: unats_def) lemma max_word_max [intro!]: "n \ max_word" by (fact word_order.extremum) lemma word_of_int_2p_len: "word_of_int (2 ^ LENGTH('a)) = (0::'a::len word)" by (subst word_uint.Abs_norm [symmetric]) simp lemma word_pow_0: "(2::'a::len word) ^ LENGTH('a) = 0" by (fact word_exp_length_eq_0) lemma max_word_wrap: "x + 1 = 0 \ x = max_word" by (simp add: eq_neg_iff_add_eq_0) lemma max_word_bl: "to_bl (max_word::'a::len word) = replicate LENGTH('a) True" by (fact to_bl_n1) lemma max_test_bit: "(max_word::'a::len word) !! n \ n < LENGTH('a)" by (fact nth_minus1) lemma word_and_max: "x AND max_word = x" by (fact word_log_esimps) lemma word_or_max: "x OR max_word = max_word" by (fact word_log_esimps) lemma word_ao_dist2: "x AND (y OR z) = x AND y OR x AND z" for x y z :: "'a::len word" by (rule word_eqI) (auto simp add: word_ops_nth_size word_size) lemma word_oa_dist2: "x OR y AND z = (x OR y) AND (x OR z)" for x y z :: "'a::len word" by (rule word_eqI) (auto simp add: word_ops_nth_size word_size) lemma word_and_not [simp]: "x AND NOT x = 0" for x :: "'a::len word" by (rule word_eqI) (auto simp add: word_ops_nth_size word_size) lemma word_or_not [simp]: "x OR NOT x = max_word" by (rule word_eqI) (auto simp add: word_ops_nth_size word_size) lemma word_xor_and_or: "x XOR y = x AND NOT y OR NOT x AND y" for x y :: "'a::len word" by (rule word_eqI) (auto simp add: word_ops_nth_size word_size) lemma shiftr_x_0 [iff]: "x >> 0 = x" for x :: "'a::len word" by (simp add: shiftr_bl) lemma shiftl_x_0 [simp]: "x << 0 = x" for x :: "'a::len word" by (simp add: shiftl_t2n) lemma shiftl_1 [simp]: "(1::'a::len word) << n = 2^n" by (simp add: shiftl_t2n) lemma uint_lt_0 [simp]: "uint x < 0 = False" by (simp add: linorder_not_less) lemma shiftr1_1 [simp]: "shiftr1 (1::'a::len word) = 0" unfolding shiftr1_def by simp lemma shiftr_1[simp]: "(1::'a::len word) >> n = (if n = 0 then 1 else 0)" by (induct n) (auto simp: shiftr_def) lemma word_less_1 [simp]: "x < 1 \ x = 0" for x :: "'a::len word" by (simp add: word_less_nat_alt unat_0_iff) lemma to_bl_mask: "to_bl (mask n :: 'a::len word) = replicate (LENGTH('a) - n) False @ replicate (min (LENGTH('a)) n) True" by (simp add: mask_bl word_rep_drop min_def) lemma map_replicate_True: "n = length xs \ map (\(x,y). x \ y) (zip xs (replicate n True)) = xs" by (induct xs arbitrary: n) auto lemma map_replicate_False: "n = length xs \ map (\(x,y). x \ y) (zip xs (replicate n False)) = replicate n False" by (induct xs arbitrary: n) auto lemma bl_and_mask: fixes w :: "'a::len word" and n :: nat defines "n' \ LENGTH('a) - n" shows "to_bl (w AND mask n) = replicate n' False @ drop n' (to_bl w)" proof - note [simp] = map_replicate_True map_replicate_False have "to_bl (w AND mask n) = map2 (\) (to_bl w) (to_bl (mask n::'a::len word))" by (simp add: bl_word_and) also have "to_bl w = take n' (to_bl w) @ drop n' (to_bl w)" by simp also have "map2 (\) \ (to_bl (mask n::'a::len word)) = replicate n' False @ drop n' (to_bl w)" unfolding to_bl_mask n'_def by (subst zip_append) auto finally show ?thesis . qed lemma drop_rev_takefill: "length xs \ n \ drop (n - length xs) (rev (takefill False n (rev xs))) = xs" by (simp add: takefill_alt rev_take) lemma map_nth_0 [simp]: "map ((!!) (0::'a::len word)) xs = replicate (length xs) False" by (induct xs) auto lemma uint_plus_if_size: "uint (x + y) = (if uint x + uint y < 2^size x then uint x + uint y else uint x + uint y - 2^size x)" by (simp add: word_arith_wis int_word_uint mod_add_if_z word_size) lemma unat_plus_if_size: "unat (x + y) = (if unat x + unat y < 2^size x then unat x + unat y else unat x + unat y - 2^size x)" for x y :: "'a::len word" apply (subst word_arith_nat_defs) apply (subst unat_of_nat) - apply (simp add: mod_nat_add word_size) + apply (auto simp add: not_less word_size) + apply (metis not_le unat_plus_if' unat_word_ariths(1)) done lemma word_neq_0_conv: "w \ 0 \ 0 < w" for w :: "'a::len word" by (simp add: word_gt_0) lemma max_lt: "unat (max a b div c) = unat (max a b) div unat c" for c :: "'a::len word" by (fact unat_div) lemma uint_sub_if_size: "uint (x - y) = (if uint y \ uint x then uint x - uint y else uint x - uint y + 2^size x)" by (simp add: word_arith_wis int_word_uint mod_sub_if_z word_size) lemma unat_sub: "b \ a \ unat (a - b) = unat a - unat b" by (simp add: unat_def uint_sub_if_size word_le_def nat_diff_distrib) lemmas word_less_sub1_numberof [simp] = word_less_sub1 [of "numeral w"] for w lemmas word_le_sub1_numberof [simp] = word_le_sub1 [of "numeral w"] for w lemma word_of_int_minus: "word_of_int (2^LENGTH('a) - i) = (word_of_int (-i)::'a::len word)" proof - have *: "2^LENGTH('a) - i = -i + 2^LENGTH('a)" by simp show ?thesis apply (subst *) apply (subst word_uint.Abs_norm [symmetric], subst mod_add_self2) apply simp done qed lemmas word_of_int_inj = word_uint.Abs_inject [unfolded uints_num, simplified] lemma word_le_less_eq: "x \ y \ x = y \ x < y" for x y :: "'z::len word" by (auto simp add: order_class.le_less) lemma mod_plus_cong: fixes b b' :: int assumes 1: "b = b'" and 2: "x mod b' = x' mod b'" and 3: "y mod b' = y' mod b'" and 4: "x' + y' = z'" shows "(x + y) mod b = z' mod b'" proof - from 1 2[symmetric] 3[symmetric] have "(x + y) mod b = (x' mod b' + y' mod b') mod b'" by (simp add: mod_add_eq) also have "\ = (x' + y') mod b'" by (simp add: mod_add_eq) finally show ?thesis by (simp add: 4) qed lemma mod_minus_cong: fixes b b' :: int assumes "b = b'" and "x mod b' = x' mod b'" and "y mod b' = y' mod b'" and "x' - y' = z'" shows "(x - y) mod b = z' mod b'" using assms [symmetric] by (auto intro: mod_diff_cong) lemma word_induct_less: "P 0 \ (\n. n < m \ P n \ P (1 + n)) \ P m" for P :: "'a::len word \ bool" apply (cases m) apply atomize apply (erule rev_mp)+ apply (rule_tac x=m in spec) apply (induct_tac n) apply simp apply clarsimp apply (erule impE) apply clarsimp apply (erule_tac x=n in allE) apply (erule impE) apply (simp add: unat_arith_simps) apply (clarsimp simp: unat_of_nat) apply simp apply (erule_tac x="of_nat na" in allE) apply (erule impE) apply (simp add: unat_arith_simps) apply (clarsimp simp: unat_of_nat) apply simp done lemma word_induct: "P 0 \ (\n. P n \ P (1 + n)) \ P m" for P :: "'a::len word \ bool" by (erule word_induct_less) simp lemma word_induct2 [induct type]: "P 0 \ (\n. 1 + n \ 0 \ P n \ P (1 + n)) \ P n" for P :: "'b::len word \ bool" apply (rule word_induct) apply simp apply (case_tac "1 + n = 0") apply auto done subsection \Recursion combinator for words\ definition word_rec :: "'a \ ('b::len word \ 'a \ 'a) \ 'b word \ 'a" where "word_rec forZero forSuc n = rec_nat forZero (forSuc \ of_nat) (unat n)" lemma word_rec_0: "word_rec z s 0 = z" by (simp add: word_rec_def) lemma word_rec_Suc: "1 + n \ 0 \ word_rec z s (1 + n) = s n (word_rec z s n)" for n :: "'a::len word" - apply (simp add: word_rec_def unat_word_ariths) - apply (subst nat_mod_eq') - apply (metis Suc_eq_plus1_left Suc_lessI of_nat_2p unat_1 unat_lt2p word_arith_nat_add) - apply simp + apply (auto simp add: word_rec_def unat_word_ariths) + apply (metis (mono_tags, lifting) old.nat.simps(7) unatSuc word_unat.Rep_inverse word_unat.eq_norm word_unat.td_th) done lemma word_rec_Pred: "n \ 0 \ word_rec z s n = s (n - 1) (word_rec z s (n - 1))" apply (rule subst[where t="n" and s="1 + (n - 1)"]) apply simp apply (subst word_rec_Suc) apply simp apply simp done lemma word_rec_in: "f (word_rec z (\_. f) n) = word_rec (f z) (\_. f) n" by (induct n) (simp_all add: word_rec_0 word_rec_Suc) lemma word_rec_in2: "f n (word_rec z f n) = word_rec (f 0 z) (f \ (+) 1) n" by (induct n) (simp_all add: word_rec_0 word_rec_Suc) lemma word_rec_twice: "m \ n \ word_rec z f n = word_rec (word_rec z f (n - m)) (f \ (+) (n - m)) m" apply (erule rev_mp) apply (rule_tac x=z in spec) apply (rule_tac x=f in spec) apply (induct n) apply (simp add: word_rec_0) apply clarsimp apply (rule_tac t="1 + n - m" and s="1 + (n - m)" in subst) apply simp apply (case_tac "1 + (n - m) = 0") apply (simp add: word_rec_0) apply (rule_tac f = "word_rec a b" for a b in arg_cong) apply (rule_tac t="m" and s="m + (1 + (n - m))" in subst) apply simp apply (simp (no_asm_use)) apply (simp add: word_rec_Suc word_rec_in2) apply (erule impE) apply uint_arith apply (drule_tac x="x \ (+) 1" in spec) apply (drule_tac x="x 0 xa" in spec) apply simp apply (rule_tac t="\a. x (1 + (n - m + a))" and s="\a. x (1 + (n - m) + a)" in subst) apply (clarsimp simp add: fun_eq_iff) apply (rule_tac t="(1 + (n - m + xb))" and s="1 + (n - m) + xb" in subst) apply simp apply (rule refl) apply (rule refl) done lemma word_rec_id: "word_rec z (\_. id) n = z" by (induct n) (auto simp add: word_rec_0 word_rec_Suc) lemma word_rec_id_eq: "\m < n. f m = id \ word_rec z f n = z" apply (erule rev_mp) apply (induct n) apply (auto simp add: word_rec_0 word_rec_Suc) apply (drule spec, erule mp) apply uint_arith apply (drule_tac x=n in spec, erule impE) apply uint_arith apply simp done lemma word_rec_max: "\m\n. m \ - 1 \ f m = id \ word_rec z f (- 1) = word_rec z f n" apply (subst word_rec_twice[where n="-1" and m="-1 - n"]) apply simp apply simp apply (rule word_rec_id_eq) apply clarsimp apply (drule spec, rule mp, erule mp) apply (rule word_plus_mono_right2[OF _ order_less_imp_le]) prefer 2 apply assumption apply simp apply (erule contrapos_pn) apply simp apply (drule arg_cong[where f="\x. x - n"]) apply simp done subsection \More\ lemma test_bit_1' [simp]: "(1 :: 'a :: len word) !! n \ 0 < LENGTH('a) \ n = 0" by simp lemma mask_0 [simp]: "mask 0 = 0" by (simp add: Word.mask_def) lemma shiftl0: "x << 0 = (x :: 'a :: len word)" by (fact shiftl_x_0) lemma mask_1: "mask 1 = 1" by (simp add: mask_def) lemma mask_Suc_0: "mask (Suc 0) = 1" by (simp add: mask_def) lemma mask_numeral: "mask (numeral n) = 2 * mask (pred_numeral n) + 1" by (simp add: mask_def neg_numeral_class.sub_def numeral_eq_Suc numeral_pow) lemma bin_last_bintrunc: "bin_last (bintrunc l n) = (l > 0 \ bin_last n)" by (cases l) simp_all lemma word_and_1: "n AND 1 = (if n !! 0 then 1 else 0)" for n :: "_ word" by transfer (rule bin_rl_eqI, simp_all add: bin_rest_trunc bin_last_bintrunc) lemma bintrunc_shiftl: "bintrunc n (m << i) = bintrunc (n - i) m << i" proof (induction i arbitrary: n) case 0 show ?case by simp next case (Suc i) then show ?case by (cases n) (simp_all add: take_bit_Suc) qed lemma shiftl_transfer [transfer_rule]: includes lifting_syntax shows "(pcr_word ===> (=) ===> pcr_word) (<<) (<<)" by (auto intro!: rel_funI word_eqI simp add: word.pcr_cr_eq cr_word_def word_size nth_shiftl) lemma uint_shiftl: "uint (n << i) = bintrunc (size n) (uint n << i)" apply (simp add: word_size shiftl_eq_push_bit shiftl_word_eq) apply transfer apply (simp add: push_bit_take_bit) done subsection \Misc\ declare bin_to_bl_def [simp] ML_file \Tools/word_lib.ML\ ML_file \Tools/smt_word.ML\ hide_const (open) Word end diff --git a/src/HOL/Word/Word_Examples.thy b/src/HOL/Word/Word_Examples.thy --- a/src/HOL/Word/Word_Examples.thy +++ b/src/HOL/Word/Word_Examples.thy @@ -1,168 +1,169 @@ (* Title: HOL/Word/Word_Examples.thy Authors: Gerwin Klein and Thomas Sewell, NICTA Examples demonstrating and testing various word operations. *) section "Examples of word operations" theory Word_Examples imports Word begin type_synonym word32 = "32 word" type_synonym word8 = "8 word" type_synonym byte = word8 text "modulus" lemma "(27 :: 4 word) = -5" by simp lemma "(27 :: 4 word) = 11" by simp lemma "27 \ (11 :: 6 word)" by simp text "signed" lemma "(127 :: 6 word) = -1" by simp text "number ring simps" lemma "27 + 11 = (38::'a::len word)" "27 + 11 = (6::5 word)" "7 * 3 = (21::'a::len word)" "11 - 27 = (-16::'a::len word)" "- (- 11) = (11::'a::len word)" "-40 + 1 = (-39::'a::len word)" by simp_all lemma "word_pred 2 = 1" by simp lemma "word_succ (- 3) = -2" by simp lemma "23 < (27::8 word)" by simp lemma "23 \ (27::8 word)" by simp lemma "\ 23 < (27::2 word)" by simp lemma "0 < (4::3 word)" by simp lemma "1 < (4::3 word)" by simp lemma "0 < (1::3 word)" by simp text "ring operations" lemma "a + 2 * b + c - b = (b + c) + (a :: 32 word)" by simp text "casting" lemma "uint (234567 :: 10 word) = 71" by simp lemma "uint (-234567 :: 10 word) = 953" by simp lemma "sint (234567 :: 10 word) = 71" by simp lemma "sint (-234567 :: 10 word) = -71" by simp lemma "uint (1 :: 10 word) = 1" by simp lemma "unat (-234567 :: 10 word) = 953" by simp lemma "unat (1 :: 10 word) = 1" by simp lemma "ucast (0b1010 :: 4 word) = (0b10 :: 2 word)" by simp lemma "ucast (0b1010 :: 4 word) = (0b1010 :: 10 word)" by simp lemma "scast (0b1010 :: 4 word) = (0b111010 :: 6 word)" by simp lemma "ucast (1 :: 4 word) = (1 :: 2 word)" by simp text "reducing goals to nat or int and arith:" lemma "i < x \ i < i + 1" for i x :: "'a::len word" by unat_arith lemma "i < x \ i < i + 1" for i x :: "'a::len word" by unat_arith text "bool lists" lemma "of_bl [True, False, True, True] = (0b1011::'a::len word)" by simp lemma "to_bl (0b110::4 word) = [False, True, True, False]" by simp text "this is not exactly fast, but bearable" -lemma "of_bl (replicate 32 True) = (0xFFFFFFFF::32 word)" by simp +lemma "of_bl (replicate 32 True) = (0xFFFFFFFF::32 word)" + by (simp add: numeral_eq_Suc) text "this works only for replicate n True" lemma "of_bl (replicate 32 True) = (0xFFFFFFFF::32 word)" by (unfold mask_bl [symmetric]) (simp add: mask_def) text "bit operations" lemma "0b110 AND 0b101 = (0b100 :: 32 word)" by simp lemma "0b110 OR 0b011 = (0b111 :: 8 word)" by simp lemma "0xF0 XOR 0xFF = (0x0F :: byte)" by simp lemma "NOT (0xF0 :: 16 word) = 0xFF0F" by simp lemma "0 AND 5 = (0 :: byte)" by simp lemma "1 AND 1 = (1 :: byte)" by simp lemma "1 AND 0 = (0 :: byte)" by simp lemma "1 AND 5 = (1 :: byte)" by simp lemma "1 OR 6 = (7 :: byte)" by simp lemma "1 OR 1 = (1 :: byte)" by simp lemma "1 XOR 7 = (6 :: byte)" by simp lemma "1 XOR 1 = (0 :: byte)" by simp lemma "NOT 1 = (254 :: byte)" by simp lemma "NOT 0 = (255 :: byte)" by simp lemma "(-1 :: 32 word) = 0xFFFFFFFF" by simp lemma "(0b0010 :: 4 word) !! 1" by simp lemma "\ (0b0010 :: 4 word) !! 0" by simp lemma "\ (0b1000 :: 3 word) !! 4" by simp lemma "\ (1 :: 3 word) !! 2" by simp lemma "(0b11000 :: 10 word) !! n = (n = 4 \ n = 3)" by (auto simp add: bin_nth_Bit0 bin_nth_Bit1) lemma "set_bit 55 7 True = (183::'a::len word)" by simp lemma "set_bit 0b0010 7 True = (0b10000010::'a::len word)" by simp lemma "set_bit 0b0010 1 False = (0::'a::len word)" by simp lemma "set_bit 1 3 True = (0b1001::'a::len word)" by simp lemma "set_bit 1 0 False = (0::'a::len word)" by simp lemma "set_bit 0 3 True = (0b1000::'a::len word)" by simp lemma "set_bit 0 3 False = (0::'a::len word)" by simp lemma "lsb (0b0101::'a::len word)" by simp lemma "\ lsb (0b1000::'a::len word)" by simp lemma "lsb (1::'a::len word)" by simp lemma "\ lsb (0::'a::len word)" by simp lemma "\ msb (0b0101::4 word)" by simp lemma "msb (0b1000::4 word)" by simp lemma "\ msb (1::4 word)" by simp lemma "\ msb (0::4 word)" by simp lemma "word_cat (27::4 word) (27::8 word) = (2843::'a::len word)" by simp lemma "word_cat (0b0011::4 word) (0b1111::6word) = (0b0011001111 :: 10 word)" by simp lemma "0b1011 << 2 = (0b101100::'a::len word)" by simp lemma "0b1011 >> 2 = (0b10::8 word)" by simp lemma "0b1011 >>> 2 = (0b10::8 word)" by simp lemma "1 << 2 = (0b100::'a::len word)" apply simp? oops lemma "slice 3 (0b101111::6 word) = (0b101::3 word)" by simp lemma "slice 3 (1::6 word) = (0::3 word)" apply simp? oops lemma "word_rotr 2 0b0110 = (0b1001::4 word)" by simp lemma "word_rotl 1 0b1110 = (0b1101::4 word)" by simp lemma "word_roti 2 0b1110 = (0b1011::4 word)" by simp lemma "word_roti (- 2) 0b0110 = (0b1001::4 word)" by simp lemma "word_rotr 2 0 = (0::4 word)" by simp lemma "word_rotr 2 1 = (0b0100::4 word)" apply simp? oops lemma "word_rotl 2 1 = (0b0100::4 word)" apply simp? oops lemma "word_roti (- 2) 1 = (0b0100::4 word)" apply simp? oops lemma "(x AND 0xff00) OR (x AND 0x00ff) = (x::16 word)" proof - have "(x AND 0xff00) OR (x AND 0x00ff) = x AND (0xff00 OR 0x00ff)" by (simp only: word_ao_dist2) also have "0xff00 OR 0x00ff = (-1::16 word)" by simp also have "x AND -1 = x" by simp finally show ?thesis . qed end